AWS Notes
5.59K subscribers
449 photos
42 videos
10 files
2.8K links
AWS Notes — Amazon Web Services Educational and Information Channel

Chat: https://t.iss.one/aws_notes_chat

Contacts: @apple_rom, https://www.linkedin.com/in/roman-siewko/
Download Telegram
О вреде юзеров.

В грамотно спроектированном окружении нет (не должно быть) #IAM юзеров. Почему? Потому что у юзера есть #credentials и они должны быть где-то явно указаны (в отличие от роли, прикреплённой к инстансу).

Если у вас один аккаунт на всех и всё, значит все пользователи заходят через юзеров, что проблема в степени количества этих юзеров. Обязательно включайте MFA для всех юзеров. А лучше переходите на светлую сторону #multi_account_strategy + #SSO.

В легаси-проектах, где ПО не умеет роль (требует наличия AccessKeyId и SecretAccessKey) - приходится заводить юзера. Включайте ему минимальные права - ровно на то, что он должен делать.

Для некоторых ситуаций, например, доступ в #CodeCommit по SSH или в #ES вне #VPC - тоже требуется наличие юзера. Всё это издержки Амазона (фу, как не стыдно), не придумавшего пока, как реализовать это без юзеров.

Во всех остальных случаях - никаких юзеров. Помните, хороший юзер - это роль.

#recomendation
62-users-on-project.gif
94.2 KB
Когда увидел, что на проекте 62 юзера.
Чтобы запустить #aws_cli команду для другого аккаунта, нужно сначала добавить в ~/.aws/config профиль типа:

[profile devops-codecommit]
role_arn = arn:aws:iam::123456789012:role/codecommit-role
credential_source = Ec2InstanceMetadata


Параметры:
devops-codecommit - просто имя профиля
role_arn - роль в аккаунте, куда нужно переключиться
credential_source = Ec2InstanceMetadata означает, что #IAM из роли инстанса

У codecommit-role должны быть права на переключение "sts:AssumeRole" и остальное нужное (в данном примере - доступ в #CodeCommit).

Теперь для просмотра репозиториев в другом аккаунте отработает следующая команда:

aws codecommit list-repositories --profile devops-codecommit

Т.е. благодаря флажку --profile происходит переключение в роль нужного аккаунта.

https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html
Доступ в #CodeCommit (git репозиторий) можно получить не только через привычные логин-пароль (https) и ключ (ssh), но и с помощью IAM роли. Это удобно и безопасно, т.к. нет #credentials (лишь прикреплённая к инстансу роль). В качестве адреса репозитория при этом используется https-вариант.

Когда CodeCommit-репозиторий в том же аккаунте, то всё работает очевидно. Однако что делать, если согласно #multi_account_strategy какое-то test-окружение, поднятое в своём test-аккаунте, должно загрузить репозиторий из репозитория, расположенного в (другом) devops-аккаунте?

Тут потребуется подправить настройки credential.helper - чтобы #git сам переключался в нужный аккаунт.

git config --global credential.helper '!aws codecommit --profile devops-codecommit credential-helper $@'

То есть для этого используем описанный в предыдущем посте метод.

Вот полный пример кода для #user_data с загрузкой git из другого аккаунта:
## Setup Git for CodeCommit
mkdir /root/.aws
AWS_CONFIG=/root/.aws/config

echo "[profile devops-codecommit]" > $AWS_CONFIG
echo "credential_source = Ec2InstanceMetadata" >> $AWS_CONFIG
echo "role_arn = ${CodeCommitRoleArn}" >> $AWS_CONFIG

export HOME=/root
git config --global credential.helper '!aws codecommit --profile devops-codecommit credential-helper $@'
git config --global credential.UseHttpPath true

## get repos from CodeCommit
HTTPS_GIT=https://git-codecommit.us-east-1.amazonaws.com/v1/repos
git clone -b ${ProjectBranch} --quiet $HTTPS_GIT/${ProjectName} $DOCKERPROJECT_DIR &> /dev/null


https://docs.aws.amazon.com/codecommit/latest/userguide/auth-and-access-control.html
Если в #user_data переменных нужно получить #ImportValue параметры, то используется следующая конструкция:
UserData:
Fn::Base64: !Sub
- |
#!/bin/bash -x
## ...
echo "role_arn = ${CodeCommitRoleArn}" >> $AWS_CONFIG
## ...
#### end of UserData
- AwsAccountDevops: !ImportValue AwsAccountDevops
CodeCommitRoleArn: !ImportValue CodeCommitRoleArn


Т.е. передаём в Fn::Base64: !Sub массив, где сначала сам код, а потом список используемых в нём переменных (именно в таком порядке - код, затем переменные).
#single_account vs #multi_account_strategy

Споры о преимуществах той или иной стратегии ("всё/все в одном" или #мультиаккаунт) бессмысленны. Не буду хохмить про то, что они очень часто ведутся между теми, кто уже давно ест апельсины и теми, кто никогда их не пробовал, но не одобряет. Если максимально коротко - у каждого способа есть набор очевидных и неочевидных плюсов и минусов, однако #multi_account_strategy — суть современный способ работы современного проекта, а потому ориентироваться нужно именно на него.

Объять столь большую и радикально отличающуюся тему быстро невозможно, потому буду разбирать поэтапно, усложняя и объясняя по ходу.

===
Минимальная схема
===

Это классическая и общепринятая пару лет назад схема разделения — простая и понятная, с неё удобно начинать (как и я когда-то), условно для небольшой команды с одним проектом и одним девопсом.

По принципу разбиения схему можно назвать "мухи и котлеты". Всё, что не относится к поднимаемым окружениям - это условный Devops аккаунт. Окружения dev-stg-prod (test, etc) поднимаются единым образом, т.е. условно из одного шаблона и лишь с разными настройками.

Окружения живут в своих VPC и соединяются с Management VPC с помощью VPC peering. Доступ к закрытым ресурсам (без внешних айпишников) происходит через промежуточный Bastion инстанс.

Всё необходимое для поднятия окружений, различные ресурсы и настройки - всё лежит в Devops аккаунте, куда может иметь доступ лишь девопс, а разработчики ходят в dev-окружение и им выделяется доступ (временно, для деплоя) в stage-prod-etc.

Это (относительно) просто в реализации и поддержке, схема удовлетворяет требованиям различных #compliance (например, #NIST) и наверняка подойдёт для многих проектов, особенно тех, кто хочет начать использовать мультиаккаунты.
С учётом AWS #Organizations минимальная схема принимает вид, где есть мастер (root) аккаунт (помеченный ранее как #devops) и подаккаунты с окружениями.

Некоторые AWS сервисы до сих пор рассчитаны на работу именно из мастер-аккаунта, в том числе поэтому реализовывать #мультиаккаунт по такой схеме проще всего.
Минимальная схема не является рекомендованной, т.к. поднятие ресурсов в мастер-аккаунте не есть #best_practices. Согласно оным мастер-аккаунт должен быть пустым и страшно защищённым.

Правда пока сам Амазон не способствует такой реализации - отдельные сервисы (#CloudTrail, #Config, #SSO и др.) до сих пор завязаны некоторым своим функционалом на использование именно мастера. В результате для соблюдения архитектурной чистоты приходится плодить костыли и с нетерпением ждать, когда же эти косяки будут исправлены.

Однако делать нужно правильно, несмотря на некоторые текущие моменты. Как минимум знать и стремиться.

Здесь и далее всё будет подразумевать использование AWS #Organizations, что и есть реализация #multi_account_strategy.

===
Рекомендуемая схема
===

В рекомендуемой схеме мастер аккаунт пустой (с поправкой на то, что пока ещё требует запуска в нём) - как минимум, никакие виртуалки в нём точно не запускаем, а наш #devops становится суб-аккаунтом и смещается по иерархии ниже.

Для различных функций, в том числе связанных со всей организацией, некоторая часть мух из предыдущей "мухо-котлетной" схемы выделяются в отдельный аккаунт с расплывчатым названием Secure. Туда переезжают ключи шифрования, домены (только регистрации, а не Hosted zones), бэкапы, #CloudTrail-логи и прочие сущности с особой важностью для организации в целом.

Современные фичи Амазона изменяют некоторые архитектурные элементы.

• Bastion выбрасываем - появление #SSM #Session_Manager закрывает его функционал.

• Для #VPC_peering используем #Transit_Gateway.

• В Devops-аккаунте добаляется #Shared_VPC, которая используется для окружений без жёстких требований по безопасности (условно dev-test), хотя, в принципе, можно и для всех окружений.

Также в Devops-аккаунте появился #Jenkins как CI-инструмент - это может быть любой другой вам привычный (я же использую Jenkins, как говорил Портос, потому, что я использую Jenkins).
Дальнейшее усложнение AWS #Organizations происходит по мере увеличения количества проектов, команд, требований и т.д.

===
Расширенная схема
===

• Общие ресурсы (ECR, снэпшоты, AMI и др.) вместе с #Shared_VPC выделяются в Shared аккаунт.

• Централизованный мониторинг и логи (ELK/Prometheus/Grafana/Sentry и т.д.) занимают свой аккаунт Monitoring (логи прода могут отправляться туда же или в отдельные - тут чисто условно).

• Бэкапы переезжают в DR (Disaster Recovery) аккаунты своих проектов.

• Наборы окружений dev-test-stg-prod-dr объединяются в #OU (Organization Units) для возможности применения к ним групповых SCP политик (объединение может быть и как Dev OU, DR OU etc - тоже чисто условно).

• Если ваша контора хочет целиком переехать в AWS, то выделяется отдельный аккаунт Organization для "организационных" вещей (название не самое удачное, речь об организации-фирме-компании, где, видимо, вы работаете :) ) — AD (Active Directory) для юзеров (самих работников), используемые для #SSO как единой точки входа, а также финансы, биллинги и прочие бухгалтерии, которые совсем не про код - всё будет там.

Процесс детализации #multi_account_strategy можно продолжать дальше - например, добавить OU для #HIPAA и прочих #compliance, где посредством #SCP будут отрабатывать их требования. Многие используеют Sandbox и/или личные аккаунты для разработчиков. И так далее и тому подобное — основные типы уже были перечислены и это уже лишь детали.
Не все йогурты одинаково полезны, а потому с Managed #IAM политиками нужно быть на чеку (амазоновцы не парятся и ставят "с запасом" - многие имеют излишние права).
Чтобы знать врага в лицо, добрые люди собрали коллекцию IAM Managed политик и ведут историю их изменений:

https://github.com/SummitRoute/aws_managed_policies/tree/master/policies
В пандан к предыдущему посту - заслуживающая внимания утилита для вычисления минимально нужных #IAM привилегий посредством сравнения имеющихся политик у юзера/роли и тех, что реально запрашиваются через AWS API (определяется с помощью #CloudTrail логов).

Может особенно может быть полезной для адептов #single_account, где такое весьма актуально в каждодневной борьбе с желающими урвать себе прав и побольше.

С помощью утилиты CloudTracker можно чётко контролировать используемое: кто не оценил вашу доброту - отобрать лишнее, а всем остальным выдавать доступ строго по талонам.

https://github.com/duo-labs/cloudtracker
При создании #security_group в #CloudFormation #templates не забывайте (не ленитесь) прописать Description в ингрессах (в каждом) — сами себе скажете спасибо в будущем, не говоря уже про других.

sgInstance:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !ImportValue vpc4
GroupDescription: Std Security Group
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 0
ToPort: 65535
SourceSecurityGroupId: !Ref sgAlb
Description: All TCP trafic - only for ALB
- IpProtocol: tcp
FromPort: 9100
ToPort: 9100
CidrIp: 10.0.0.0/8
Description: node-exporter
- IpProtocol: tcp
FromPort: 8080
ToPort: 8080
CidrIp: 10.0.0.0/8
Description: cadvisor
Поддержка Secrets в Environment для #Fargate появилась в конце 2018-го года (версия Fargate 1.3), но на текущий момент в документации есть только следующее. Получается, это можно реализовать и в #CloudFormation #templates, однако документация, как обычно, отстаёт и хромает, хотя это уже работает.

Предположим, что нужно поднять какой-то Fargate контейнер, создать для него #SSM_Parameters, которые прокидываются в докер Environment, чтобы после можно было поменять нужный параметр без пересоздания всего стэка (для применения, естественно, потребуется пересоздание таски).

Главная часть кода для имплементации такого будет следующая:
...
ssmparamDbEndpoint:
Type: AWS::SSM::Parameter
Properties:
Name: !Ref ParamNameDbEndpoint
Type: String
Value: !Ref DbEndpoint
Description: SSM Parameter for DB endpoint
...
fargateTask:
Type: AWS::ECS::TaskDefinition
Properties:
ContainerDefinitions:
- Name: !Ref ServiceName
Image: !Ref DockerImage
Essential: true
Secrets:
- Name: WORDPRESS_DB_HOST
ValueFrom: !Join ['',['arn:aws:ssm:', !Ref 'AWS::Region', ':', !Ref 'AWS::AccountId', ':parameter/', !Ref ParamNameDbEndpoint]]
- Name: WORDPRESS_DB_USER
ValueFrom: !Join ['',['arn:aws:ssm:', !Ref 'AWS::Region', ':', !Ref 'AWS::AccountId', ':parameter/', !Ref ParamNameDbUser]]
- Name: WORDPRESS_DB_PASSWORD
ValueFrom: !Join ['',['arn:aws:ssm:', !Ref 'AWS::Region', ':', !Ref 'AWS::AccountId', ':parameter/', !Ref ParamNameDbPassword]]
Environment:
- Name: WORDPRESS_DB_NAME
Value: wp-db
...


Т.е. добавляется блок Secrets, куда значения из #ParameterStore попадают благодаря такой конструкции:

arn:aws:ssm:YOUR_AWS_REGION:YOUR_AWS_ACCOUNT:parameter/PARAMETER_NAME

Полный (рабочий) пример тут.

На текущий момент параметры из блока Secrets не отображаются в AWS Console (см. картинку внизу - она из примера), однако точно работают (можно попробовать пример). Хотя с некоторыми регионами могут быть вопросы - точно работает (проверено) для Virginia и Ireland.
Ещё один ресурс для возможности сравнения EC2 инстансов - с некоторыми претензиями на мобильную версию:

https://cloudbanshee.com/ec2

Кстати, кто активно пользуется https://ec2instances.info и кому чего-то там не хватает — может вполне такое сделать сам:

https://github.com/powdahound/ec2instances.info

#info #comparison
Если у вас годами себе мирно жили тучи файлов на #s3 и вдруг выясняется, что по #compliance причинам теперь их всех нужно зашифровать либо по требованиями аудита требуется всем проставить (переставить) тэги или ещё какая-то глобально-массовая напасть — для всех таких работ теперь есть нативный инструмент #s3_batch_operations:

https://aws.amazon.com/blogs/aws/new-amazon-s3-batch-operations/
Просто оставлю это здесь - интересная утилита, реализующая traffic mirroring:

https://github.com/buger/goreplay

Кому интересно, чуть расшифрую (не про Амазон).

Тестирование почти всегда проводится какими-то искусственными паттернами, которые должны при это дать некую гарантию, что на проде при реальной нагрузке оно не поломается. А метод traffic mirroring (или shadow traffic) дублирует реальный трафик, пришедший на прод в нужное вам (тестовое) окружение.

Это очень круто - иметь возможность тестировать "живым" трафиком. Модная тема, особенно легко реализуемая с помощью #kubernetes, так что советую как минимум знать про это - сие есть следующая инкарнация подходов Blue/Green или Canary Deployment.
Безопасности пост.
Nested Stacks

Не один год используя Nested Stacks , могу посоветовать - никогда не используйте #nested_stacks. Хуже #nested_stacks может быть лишь #nested_stacks на JSON.

Когда-то давно появление #nested_stacks казалось серьёзным шагом вперёд в попытке получения хоть какой-то модульности в #CloudFormation #templates, где до этого приходилось постоянно дублировать повторяющиеся части кода в шаблонах, отличающихся лишь малой частью ресурсов. Однако реальная эксплуатация показала, что с ростом сложности проекта, глубины и количества Nested Stacks, разрабатываться, сопровождать и обновлять его становится от сложно до невозможно.

Это потому, что для передачи параметров используется главный стэк, а запуская его на обновление, если у тебя отвалится что-то на энном обновляемом по уровню стэке, то сработает откат, который должен будет вернуть к предыдущему состоянию (успешно) обновившиеся до этого стэки, что банально не всегда возможно. Т.е. с постоянным усложнением проекта вам приходится быть как на картинке внизу.

Другая важная проблема, что из-за передачи переменных в низлежащие стэки через главный стэк, вы очень скоро можете попасть в ограничение на количество переменных, которое равно 60. Это для одного стэка кажется достаточным, но когда у вас даже пять-шесть вложенных стэков, то десяток переменных на каждого может сразу же исчерпают этот лимит.

Потому рекомендация одна - избегайте #nested_stacks. Они применимы лишь в примитивных случаях. Появление Import/Export функционала в CloudFormation практически убило какие-то реальные кейсы использования #nested_stacks. Если же вам досталась это чудо по наследству и вы попали на ограничение по количеству параметров (а вам нужно добавить новые) - используйте SSM параметры, передавая переменные через них.
Если потребуется скопировать код из этого канала, а на компе телеграм не стоит, то можно использовать доступный веб-адрес:

https://t.iss.one/s/aws_notes