AWS Notes
Бывает, что, казалось бы, банальное копирование файлов в #s3 бакет: aws s3 cp ./ s3://some-bucket/files --recursive Когда это происходит из другого аккаунта, когда бакет расположен в другом регионе или с локального компьютера (между бакетами и т.п. не самые…
Спасительный флажок bucket-owner-full-control, решающий вопросы доступа в #s3 бакет для двух аккаунтов, не поможет для ситуации с тремя и более аккаунтами. Это когда файл копируется из аккаунта A в бакет аккаунта B, а после нужно расшарить это для аккаунта C (также имеющего доступ в бакет аккаунта B).
Использование
An error occurred (AccessDenied) when calling the GetObjectAcl operation: Access Denied
Хотя точно у всех есть нужные #IAM #permissions и прописаны правильные #bucket_policy в #shared_bucket.
Дело в тех же owner-ах, как и для "двух-аккаунтной" схемы, только решается много сложней. Объекты в shared-bucket имеют лишь права для этих двух аккаутов A и B, аккаунт C имеет доступ в бакет, но его нет среди owner-ов объектов, потому ничего с ними сделать не может.
Решается ситуация лишь из аккаута owner-а, т.е. из аккаунта A — при копировании нужно добавить в список owner-ов сразу все аккаунты (т.е. в т.ч. C). Обычная #aws_cli команда
my-shared-bucket — бакет в аккаунте B
--key — путь к файлу в этом бакете
--body — локальный путь к файлу (на виртуалке)
--grant-full-control id=s3-canonical-A,id=s3-canonical-B,id=s3-canonical-C — #s3_canonical аккаунтов A, B и C (именно в таком виде - через запятую без пробела, чего нет в доке, враги)
Не нужно путать S3 Сanonical ID с тем, что используется для CloudFront при доступе в непубличный бакет (S3 canonical user ID). Это уникальный ID для аккаунта, который идёт в паре с AWS ID и может быть получен с помощью
"Owner": {
"DisplayName": "my-account-A",
"ID": "d0cecf42b8a1bed065b8a1b2fdbf76c1b6acda99e0338822e3cece21a8c71058"
},
"Buckets": []
...
Это
Потому если нужно раздавать (непубличные) файлы для переменного количества аккаунтов, то #s3 не лучший способ при таком сценарии. В рекомендациях от Амазона это решается с помощью роли в аккаунте A или B, в которую должен переключиться юзер из аккаунта C для получения файла, однако такое (переключение в роль) не всегда возможно сделать в уже имеющемся ПО и библиотеках.
Использование
--acl bucket-owner-full-control не поможет и получим #error:An error occurred (AccessDenied) when calling the GetObjectAcl operation: Access Denied
Хотя точно у всех есть нужные #IAM #permissions и прописаны правильные #bucket_policy в #shared_bucket.
Дело в тех же owner-ах, как и для "двух-аккаунтной" схемы, только решается много сложней. Объекты в shared-bucket имеют лишь права для этих двух аккаутов A и B, аккаунт C имеет доступ в бакет, но его нет среди owner-ов объектов, потому ничего с ними сделать не может.
Решается ситуация лишь из аккаута owner-а, т.е. из аккаунта A — при копировании нужно добавить в список owner-ов сразу все аккаунты (т.е. в т.ч. C). Обычная #aws_cli команда
s3 cp так не умеет — нужно использовать #s3api:aws --region=us-east-1 s3api put-object --bucket my-shared-bucket --key my-bucket-dir/conf.tar.gz --body my-local-dir/conf.tar.gz --grant-full-control id=d0cecf42b8a1bed065b8a1b2fdbf76c1b6acda99e0338822e3cece21a8c71058,id=1208ecf5e61d2b67a525edee13f7667ab45d2be85b1fdb11a9338a60609ee5f9,id=780e8bdf2b68d6cc2da2cfcaa6192fac4f437190322277db24ce81ce9aa698f9Очень непростая и плохо документированная, но рабочая конструкция.
my-shared-bucket — бакет в аккаунте B
--key — путь к файлу в этом бакете
--body — локальный путь к файлу (на виртуалке)
--grant-full-control id=s3-canonical-A,id=s3-canonical-B,id=s3-canonical-C — #s3_canonical аккаунтов A, B и C (именно в таком виде - через запятую без пробела, чего нет в доке, враги)
Не нужно путать S3 Сanonical ID с тем, что используется для CloudFront при доступе в непубличный бакет (S3 canonical user ID). Это уникальный ID для аккаунта, который идёт в паре с AWS ID и может быть получен с помощью
aws s3api list-buckets
{"Owner": {
"DisplayName": "my-account-A",
"ID": "d0cecf42b8a1bed065b8a1b2fdbf76c1b6acda99e0338822e3cece21a8c71058"
},
"Buckets": []
...
Это
ID значение получаем для каждого аккаунта, который должен иметь доступ к данному файлу в shared-bucket. Если потребуется расшарить к новому аккаунту - придётся повторить процедуру для каждого файла (объекта).Потому если нужно раздавать (непубличные) файлы для переменного количества аккаунтов, то #s3 не лучший способ при таком сценарии. В рекомендациях от Амазона это решается с помощью роли в аккаунте A или B, в которую должен переключиться юзер из аккаунта C для получения файла, однако такое (переключение в роль) не всегда возможно сделать в уже имеющемся ПО и библиотеках.
Лучшие из известных мне мест для обсуждения темы #AWS (по условному личному рейтингу предпочтения):
===
og-aws (Slack) — инвайт можно получить на https://og-aws-slack.lexikon.io/
Хорошие каналы:
#announcements
#awsannoyances
#cloudformation
#ecs
#general
#mistakes
#security
и другие (#terraform #kubernetes и т.д.)
===
Reddit - https://www.reddit.com
Хорошие комьюнити:
https://www.reddit.com/r/AWS_cloud/
https://www.reddit.com/r/aws/
https://www.reddit.com/r/AWS_Certified_Experts/
===
hangops (Slack) — инвайт можно получить на https://signup.hangops.com/
Хорошие каналы:
#aws
плюс также, конечно, #kubernetes, #terraform, #docker и т.д.
===
===
Русскоязычные:
AWS_ru
AWS Minsk Community
Ну, и данный канал aws_notes (срочно подписываемся, если ещё нет), который веду я, Roman Sevko — пытаясь каталогизировать собственные заметки по Амазону, чтобы и самому не забыть, и другим полезно.
#info
===
og-aws (Slack) — инвайт можно получить на https://og-aws-slack.lexikon.io/
Хорошие каналы:
#announcements
#awsannoyances
#cloudformation
#ecs
#general
#mistakes
#security
и другие (#terraform #kubernetes и т.д.)
===
Reddit - https://www.reddit.com
Хорошие комьюнити:
https://www.reddit.com/r/AWS_cloud/
https://www.reddit.com/r/aws/
https://www.reddit.com/r/AWS_Certified_Experts/
===
hangops (Slack) — инвайт можно получить на https://signup.hangops.com/
Хорошие каналы:
#aws
плюс также, конечно, #kubernetes, #terraform, #docker и т.д.
===
===
Русскоязычные:
AWS_ru
AWS Minsk Community
Ну, и данный канал aws_notes (срочно подписываемся, если ещё нет), который веду я, Roman Sevko — пытаясь каталогизировать собственные заметки по Амазону, чтобы и самому не забыть, и другим полезно.
#info
reddit
Amazon cloud: guides, blogs and all the rest • r/AWS_cloud
Sharing information about the Amazon cloud - how-tos, povs, experts blogs..
Если у вас активно используется #AWS_Organizations, то стоит задуматься над тем, чтобы прописать пароли у root-юзеров в созданных суб-аккаунтах (что не часто делается, особенно если они создаются автоматически).
Указание фейковой почты для #root_user уязвимо с точки зрения безопасности. Лучшей практикой является установка пароля для рута и включение #MFA на какое-то условно защищённое устройство (и, к примеру, помещённое в сейф).
Кроме того не стоит забывать, что Амазон шлёт некоторые важные (в т.ч. критические - взлом и т.п.) #notifications на почту root-юзера. Это можно в некоторой мере решить, указав Alternate Contacts в настройках аккаунта, однако некоторые сервисы (если не ошибаюсь, #SES), могут слать notifications лишь на рут-почту.
#security #best_practices
Указание фейковой почты для #root_user уязвимо с точки зрения безопасности. Лучшей практикой является установка пароля для рута и включение #MFA на какое-то условно защищённое устройство (и, к примеру, помещённое в сейф).
Кроме того не стоит забывать, что Амазон шлёт некоторые важные (в т.ч. критические - взлом и т.п.) #notifications на почту root-юзера. Это можно в некоторой мере решить, указав Alternate Contacts в настройках аккаунта, однако некоторые сервисы (если не ошибаюсь, #SES), могут слать notifications лишь на рут-почту.
#security #best_practices
В продолжение темы защиты #root_user — для особо опасливых можно посоветовать накрыть всё это дело сверху #SCP политикой для #AWS_Organizations, запрещающей работу из-под рута.
#paranoid #security
{
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"StringLike": {
"aws:PrincipalARN": "arn:aws:iam::*:root"
}
}
}
Правда некоторые сервисы под капотом используют (требуют) рута, потому стоит протестировать на чём-то неважном (возможно разбанить нужные сервисы, требующие root).#paranoid #security
Чтобы узнать (убедиться) какую #IAM роль имеет виртуалка, на которой вы сейчас что-то делаете — используем команду #aws_cli #sts для получения её #ARN #iam_role:
aws sts get-caller-identity
Тут же и #AWS_ID аккаунта.
aws sts get-caller-identity
{
"Account": "123456789012",
"UserId": "AROAJDDFOVZHPIQJWHGGG:i-012cf7e6be9a23bec",
"Arn": "arn:aws:sts::123456789012:assumed-role/main-roleEc2-12DC86Q5A4VNV/i-012cf7e6be9a23bec"
}
Тут же и #AWS_ID аккаунта.
Хороший пример оформления #documentation для #kubernetes на #AWS (и просто полезно как краткая документация):
https://kubernetes-on-aws.readthedocs.io/en/latest/index.html
https://kubernetes-on-aws.readthedocs.io/en/latest/index.html
При ошибках в работе с #S3 бакетами есть некоторый набор вещей, что требуется проверить, чтобы найти причину и всё исправить. Очевидные проблемы доступа (не настроенные права) не в счёт, как и вопросы шифрования (это отдельная тема). Далее выстраданные болью и болью вещи.
===
Некоторые достаточно очевидные, что нужно перебрать и проверить.
===
• регион бакета - он может отличаться от того, из которого идёт доступ
• в современных регионах - только Signature Version 4
• популярные ошибки в #IAM: не стоит политика на бакет без
===
Некоторые не самые и совсем неочевидные (из серии #magic).
===
• сильно отличается время на инстансе (в любую сторону - несколько минут и больше), что часто даёт #error:
A client error (403) occurred when calling the HeadObject operation: Forbidden
• версия #aws_cli старая (локально на старых виртуалках)
• стоит флажок
• при операциях с https - нужно учитывать заголовки в CORS (что есть
... если получаем ошибку:
An error occurred (AccessDenied) when calling the GetObjectAcl operation: Access Denied
... хотя точно есть все права/роли для бакета (на другой аккаунт, нужные операции и путь), то значит файлы в бакете имеют хозяина, недоступного запрашиваемому — см. выше про #shared_bucket
В нормальной ситуации был бы ответ типа:
#s3_debug
===
Некоторые достаточно очевидные, что нужно перебрать и проверить.
===
• регион бакета - он может отличаться от того, из которого идёт доступ
• в современных регионах - только Signature Version 4
• популярные ошибки в #IAM: не стоит политика на бакет без
* (звёздочки, wildcard):"Action": [... или наоборот (только с
"s3:GetObject",
"s3:ListBucket",
],
"Resource": [
"arn:aws:s3:::my-bucket",
]
*)"Action": [• есть операция с каталогом, а нет политики '
"s3:GetObject",
"s3:ListBucket",
],
"Resource": [
"arn:aws:s3:::my-bucket/*",
]
s3:ListBucket'===
Некоторые не самые и совсем неочевидные (из серии #magic).
===
• сильно отличается время на инстансе (в любую сторону - несколько минут и больше), что часто даёт #error:
A client error (403) occurred when calling the HeadObject operation: Forbidden
• версия #aws_cli старая (локально на старых виртуалках)
• стоит флажок
--recursive, а работа идёт с файлом (может возникнуть после копипаста в скриптах) — в результате ничего не будет - ни ошибки (что самое противное), ни копирования файла• при операциях с https - нужно учитывать заголовки в CORS (что есть
HEAD среди них, который часто по дефолту не стоит)<?xml version="1.0" encoding="UTF-8"?>• проверяем доступ на конкретный файл с помощью
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>GET</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
aws s3api get-object-acl --bucket my-bucket --key my-path/some.file... если получаем ошибку:
An error occurred (AccessDenied) when calling the GetObjectAcl operation: Access Denied
... хотя точно есть все права/роли для бакета (на другой аккаунт, нужные операции и путь), то значит файлы в бакете имеют хозяина, недоступного запрашиваемому — см. выше про #shared_bucket
В нормальной ситуации был бы ответ типа:
{
"Owner": {
"DisplayName": "my-dev",
"ID": "c0123f42b8a1bed065b8a1b2fdbf76c1b6acda99e0778822e3cece21a8c71058"
},
"Grants": [
{
"Grantee": {
"Type": "CanonicalUser",
"DisplayName": "my-dev",
"ID": "c0123f42b8a1bed065b8a1b2fdbf76c1b6acda99e0778822e3cece21a8c71058"
},
"Permission": "FULL_CONTROL"
},
{
"Grantee": {
"Type": "CanonicalUser",
"DisplayName": "jenkins",
"ID": "8933ecf5e61d2b67a525edee13f7667ab45d2be85b1fdb82a9338a60609ee5f9"
},
"Permission": "FULL_CONTROL"
}
]
}
... где перечислены все owner-ы файла. Итого (при такой ошибке) нужно перезалить файл с owner-ом аккаунта, откуда идёт чтение, либо изменить (добавить) owner-а или же переключаться в роль аккаунта, где есть права для операции чтения.#s3_debug
🔥1
Если вы используете #SES, то проконтролируйте, чтобы email для рутов/админов не был фейковый, иначе сообщения об ошибках и прочая информация, которая стандартно отправляется на такую почту, будет постоянно попадать в недоставленные, увеличивая #bounce_rate, в результате чего SES-аккаунт могут забанить.
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/e-faq.html#e-faq-bn
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/e-faq.html#e-faq-bn
Amazon
What is Amazon SES? - Amazon Simple Email Service
Use Amazon SES to send marketing emails such as special offers, transactional emails such as order confirmations, and other types of correspondence such as newsletters and system notifications. You can also use Amazon SES to receive email. When you use Amazon…
Большинство сервисов для #IAM #policy не допускает использовать пробелы в "Sid", однако #s3 их разрешает, а потому можно (нужно) писать человеческие комментарии к используемым #bucket_policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Full access for Blue, Green",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::123456789012:root",
"arn:aws:iam::234567890123:root"
]
},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*"
]
},
{
"Sid": "ReadOnly access for Dev, Stage",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::345678901234:root",
"arn:aws:iam::456789012345:root"
]
},
"Action": [
"s3:GetObject",
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*"
]
}
]
}Вот уже два года как есть возможность останавливать #RDS инстансы, что, казалось бы, даёт отличную возможность уменьшить расходы без убийства временно ненужных ресурсов.
И вот ты такой довольный собой, что потушил всё лишнее (где моя медаль за экономию??), через месячишко-полгодика заходишь в облагороженный аккаунт — опа, что за враги снова запустили остановленные RDS без спросу?!? И давай устраивать допрос с пристрастием. Но после безуспешных пыток девелоперов установкой им новых строгих паролей начинаешь подозревать неладное...
Читайте написанное мелким текстом перед подписанием договора:
You can stop a DB instance for up to seven days. If you don't manually start your DB instance after seven days, your DB instance is automatically started.
И вот ты такой довольный собой, что потушил всё лишнее (где моя медаль за экономию??), через месячишко-полгодика заходишь в облагороженный аккаунт — опа, что за враги снова запустили остановленные RDS без спросу?!? И давай устраивать допрос с пристрастием. Но после безуспешных пыток девелоперов установкой им новых строгих паролей начинаешь подозревать неладное...
Читайте написанное мелким текстом перед подписанием договора:
You can stop a DB instance for up to seven days. If you don't manually start your DB instance after seven days, your DB instance is automatically started.
В блоке #Outputs #CloudFormation #templates нельзя сделать:
т.к. в #GetAtt нельзя использовать функции. Потому нужно использовать обратную конструкцию:
dns1:
Value: !GetAtt [ !If [ IsPrivate, esDomainVpc, esDomainPublic ], 'DomainEndpoint']т.к. в #GetAtt нельзя использовать функции. Потому нужно использовать обратную конструкцию:
Value: !If [ IsPrivate, !GetAtt [esDomainVpc, 'DomainEndpoint'], !GetAtt [esDomain, 'DomainEndpoint'] ]Amazon
Fn::GetAtt - AWS CloudFormation
Learn how to return the value of an attribute from a resource in your CloudFormation template by using the Fn::GetAtt intrinsic function.
Стэк для VPC peering должен быть в том же регионе (cross-region появился в конце 2017), где находится VpcId:
peerManagementVpc4:
Type: 'AWS::EC2::VPCPeeringConnection'
Properties:
VpcId: !Ref VpcManagement
PeerVpcId: !Ref Vpc4
PeerOwnerId: !Ref AwsAccountVpc4
PeerRoleArn: !Ref RoleInVpc4
т.к. #CloudFormation ищет VpcId именно в этом регионе (аккаунте), а в шаблоне (т.е. в самом CloudFormation #templates) нет возможности задать регион (как минимум - пока).
В результате при попытке это сделать через шаблон будет #error:
VpcPeeringConnection failed to stabilize
А потому #cross_region #vpc_peering пока можно сделать лишь вручную через консоль (где есть возможность задать #aws_region).
peerManagementVpc4:
Type: 'AWS::EC2::VPCPeeringConnection'
Properties:
VpcId: !Ref VpcManagement
PeerVpcId: !Ref Vpc4
PeerOwnerId: !Ref AwsAccountVpc4
PeerRoleArn: !Ref RoleInVpc4
т.к. #CloudFormation ищет VpcId именно в этом регионе (аккаунте), а в шаблоне (т.е. в самом CloudFormation #templates) нет возможности задать регион (как минимум - пока).
В результате при попытке это сделать через шаблон будет #error:
VpcPeeringConnection failed to stabilize
А потому #cross_region #vpc_peering пока можно сделать лишь вручную через консоль (где есть возможность задать #aws_region).
Большая часть материалов этого канала берётся из моих записей, что я веду уже почти десять лет в Google Datasheets. Когда-то это начиналось просто с возможности не зависеть от ОС и используемого устройства, но со временем это вылилось в стиль работы, который особенно актуален для #devops. Хочу поделиться выработанными за годы практиками, которые, думаю, особенно будут полезны #начинающим.
Опуская способ организации документов, который может быть разным (по вкусу-привычке), остановлюсь на принципах.
Поднята новая виртуалка, которую нужно настроить (что-то сделать, просто работать и т.д.). Ей в роль (профиль) добавлены админские права, помчались.
===
Правило КОПИПАСТА. Все команды выполняем только копированием из своего документа.
===
Что это значит? Предположим, что стоит задача поднять на виртуалке Jenkins LTS в Docker. Создаю документ (я буду подразумевать гуглошиты, но это не принципиально) в папке проекта, к которому относится такая задача.
Все команды пишу сначала в документ, после просто их копирую в терминал. Речь о главных командах, относящихся к настройке — всяческие
У меня таких документов много, всё повторяется, потому, конечно же, этого можно было бы и не делать. Да и вообще, память у меня отличная. А что не вспомню – можно быстренько нагуглить. И вообще, зачем лишние телодвижения?!?
Часто (читай – всегда) нужно гуглить, нагугленное вставляю в свой документ и только из него копирую в терминал.
Мало того – сразу добавляю комментарии. Это сейчас понятно, а через месяц – нет. Комментарии выделяю, чтобы после можно было быстро видеть структуру документа, кроме того, при накоплении информации на странице, быстро ориентироваться можно будет только именно по ним.
Если есть важный ответ на команду – добавляю его. Форматирую (в моноширинный), если большой, то уменьшаю шрифт.
Выделяю важные места в ответе. Выделяю важные ключики в команде. Выделяю цветом основные параметры. Разбиваю на логические части. В общем, делаю красиво – #как_для_себя.
===
Да, это занимает время. Без практики (и начинающим) — очень много времени. Однако суть данной рекомендации в том, что #это_работает.
Уже второй подход к этой (или похожей) задаче полностью окупает потраченное время. Накопленный материал, лично переработанный, а не просто увиденный в поиске – повышает вашу квалификацию.
Во многих случаях (и с обеспечением должного уровня безопасности) в ответах команд даже можно хранить важные credentials (на картинках и постах в канале они изменены – можете не стараться :) ) – из контекста понятно для чего они и легко искать.
Удобно шарить другим. При ответственном подходе – считай, готовая документация.
А при накоплении материала – тоже сможете завести свой канал.
Но главное – это постоянное самосовершенствование. Не надейтесь на память и гугл, лишь увеличивая энтропию интернета и просмотры страниц стэковерфлоу. Упорядочивайте знания, пока они не упорядочили вас!
#recomendation #best_practices #continuous_self_improvement
Опуская способ организации документов, который может быть разным (по вкусу-привычке), остановлюсь на принципах.
Поднята новая виртуалка, которую нужно настроить (что-то сделать, просто работать и т.д.). Ей в роль (профиль) добавлены админские права, помчались.
===
Правило КОПИПАСТА. Все команды выполняем только копированием из своего документа.
===
Что это значит? Предположим, что стоит задача поднять на виртуалке Jenkins LTS в Docker. Создаю документ (я буду подразумевать гуглошиты, но это не принципиально) в папке проекта, к которому относится такая задача.
Все команды пишу сначала в документ, после просто их копирую в терминал. Речь о главных командах, относящихся к настройке — всяческие
ls и отладочные не в счёт.У меня таких документов много, всё повторяется, потому, конечно же, этого можно было бы и не делать. Да и вообще, память у меня отличная. А что не вспомню – можно быстренько нагуглить. И вообще, зачем лишние телодвижения?!?
Ответ см. в п.1. (правило копипаста).Часто (читай – всегда) нужно гуглить, нагугленное вставляю в свой документ и только из него копирую в терминал.
Мало того – сразу добавляю комментарии. Это сейчас понятно, а через месяц – нет. Комментарии выделяю, чтобы после можно было быстро видеть структуру документа, кроме того, при накоплении информации на странице, быстро ориентироваться можно будет только именно по ним.
Если есть важный ответ на команду – добавляю его. Форматирую (в моноширинный), если большой, то уменьшаю шрифт.
Выделяю важные места в ответе. Выделяю важные ключики в команде. Выделяю цветом основные параметры. Разбиваю на логические части. В общем, делаю красиво – #как_для_себя.
===
Да, это занимает время. Без практики (и начинающим) — очень много времени. Однако суть данной рекомендации в том, что #это_работает.
Уже второй подход к этой (или похожей) задаче полностью окупает потраченное время. Накопленный материал, лично переработанный, а не просто увиденный в поиске – повышает вашу квалификацию.
Во многих случаях (и с обеспечением должного уровня безопасности) в ответах команд даже можно хранить важные credentials (на картинках и постах в канале они изменены – можете не стараться :) ) – из контекста понятно для чего они и легко искать.
Удобно шарить другим. При ответственном подходе – считай, готовая документация.
А при накоплении материала – тоже сможете завести свой канал.
Но главное – это постоянное самосовершенствование. Не надейтесь на память и гугл, лишь увеличивая энтропию интернета и просмотры страниц стэковерфлоу. Упорядочивайте знания, пока они не упорядочили вас!
#recomendation #best_practices #continuous_self_improvement
Некоторые #читы, полезные на местности (в виртуалке).
===
Получить список имеющихся (в нужном регионе) #KeyPair:
===
Получить список #IAM ролей:
===
Получить список юзеров:
===
Получить детальный отчёт по правам юзеров:
#aws_cli
===
Получить список имеющихся (в нужном регионе) #KeyPair:
aws --region us-east-1 ec2 describe-key-pairs --query KeyPairs[].KeyName[]===
Получить список #IAM ролей:
aws iam list-roles --query Roles[].Arn[]===
Получить список юзеров:
aws iam list-users --query Users[].Arn[]===
Получить детальный отчёт по правам юзеров:
aws iam get-account-authorization-details --query UserDetailList[]#aws_cli
О вреде юзеров.
В грамотно спроектированном окружении нет (не должно быть) #IAM юзеров. Почему? Потому что у юзера есть #credentials и они должны быть где-то явно указаны (в отличие от роли, прикреплённой к инстансу).
Если у вас один аккаунт на всех и всё, значит все пользователи заходят через юзеров, что проблема в степени количества этих юзеров. Обязательно включайте MFA для всех юзеров. А лучше переходите на светлую сторону #multi_account_strategy + #SSO.
В легаси-проектах, где ПО не умеет роль (требует наличия AccessKeyId и SecretAccessKey) - приходится заводить юзера. Включайте ему минимальные права - ровно на то, что он должен делать.
Для некоторых ситуаций, например, доступ в #CodeCommit по SSH или в #ES вне #VPC - тоже требуется наличие юзера. Всё это издержки Амазона (фу, как не стыдно), не придумавшего пока, как реализовать это без юзеров.
Во всех остальных случаях - никаких юзеров. Помните, хороший юзер - это роль.
#recomendation
В грамотно спроектированном окружении нет (не должно быть) #IAM юзеров. Почему? Потому что у юзера есть #credentials и они должны быть где-то явно указаны (в отличие от роли, прикреплённой к инстансу).
Если у вас один аккаунт на всех и всё, значит все пользователи заходят через юзеров, что проблема в степени количества этих юзеров. Обязательно включайте MFA для всех юзеров. А лучше переходите на светлую сторону #multi_account_strategy + #SSO.
В легаси-проектах, где ПО не умеет роль (требует наличия AccessKeyId и SecretAccessKey) - приходится заводить юзера. Включайте ему минимальные права - ровно на то, что он должен делать.
Для некоторых ситуаций, например, доступ в #CodeCommit по SSH или в #ES вне #VPC - тоже требуется наличие юзера. Всё это издержки Амазона (фу, как не стыдно), не придумавшего пока, как реализовать это без юзеров.
Во всех остальных случаях - никаких юзеров. Помните, хороший юзер - это роль.
#recomendation
Чтобы запустить #aws_cli команду для другого аккаунта, нужно сначала добавить в ~/.aws/config профиль типа:
Параметры:
devops-codecommit - просто имя профиля
role_arn - роль в аккаунте, куда нужно переключиться
credential_source = Ec2InstanceMetadata означает, что #IAM из роли инстанса
У codecommit-role должны быть права на переключение "sts:AssumeRole" и остальное нужное (в данном примере - доступ в #CodeCommit).
Теперь для просмотра репозиториев в другом аккаунте отработает следующая команда:
Т.е. благодаря флажку --profile происходит переключение в роль нужного аккаунта.
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html
[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
Amazon
Using an IAM role in the AWS CLI - AWS Command Line Interface
Configure the AWS CLI to use a role defined in AWS Identity and Access Management.
Доступ в #CodeCommit (git репозиторий) можно получить не только через привычные логин-пароль (https) и ключ (ssh), но и с помощью IAM роли. Это удобно и безопасно, т.к. нет #credentials (лишь прикреплённая к инстансу роль). В качестве адреса репозитория при этом используется https-вариант.
Когда CodeCommit-репозиторий в том же аккаунте, то всё работает очевидно. Однако что делать, если согласно #multi_account_strategy какое-то test-окружение, поднятое в своём test-аккаунте, должно загрузить репозиторий из репозитория, расположенного в (другом) devops-аккаунте?
Тут потребуется подправить настройки credential.helper - чтобы #git сам переключался в нужный аккаунт.
То есть для этого используем описанный в предыдущем посте метод.
Вот полный пример кода для #user_data с загрузкой git из другого аккаунта:
https://docs.aws.amazon.com/codecommit/latest/userguide/auth-and-access-control.html
Когда 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
Amazon
Authentication and access control for AWS CodeCommit - AWS CodeCommit
Control user access using IAM policies to specify which CodeCommit actions a user in your Amazon Web Services account can perform.
Если в #user_data переменных нужно получить #ImportValue параметры, то используется следующая конструкция:
Т.е. передаём в Fn::Base64: !Sub массив, где сначала сам код, а потом список используемых в нём переменных (именно в таком порядке - код, затем переменные).
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) и наверняка подойдёт для многих проектов, особенно тех, кто хочет начать использовать мультиаккаунты.
Споры о преимуществах той или иной стратегии ("всё/все в одном" или #мультиаккаунт) бессмысленны. Не буду хохмить про то, что они очень часто ведутся между теми, кто уже давно ест апельсины и теми, кто никогда их не пробовал, но не одобряет. Если максимально коротко - у каждого способа есть набор очевидных и неочевидных плюсов и минусов, однако #multi_account_strategy — суть современный способ работы современного проекта, а потому ориентироваться нужно именно на него.
Объять столь большую и радикально отличающуюся тему быстро невозможно, потому буду разбирать поэтапно, усложняя и объясняя по ходу.
===
Минимальная схема
===
Это классическая и общепринятая пару лет назад схема разделения — простая и понятная, с неё удобно начинать (как и я когда-то), условно для небольшой команды с одним проектом и одним девопсом.
По принципу разбиения схему можно назвать "мухи и котлеты". Всё, что не относится к поднимаемым окружениям - это условный Devops аккаунт. Окружения dev-stg-prod (test, etc) поднимаются единым образом, т.е. условно из одного шаблона и лишь с разными настройками.
Окружения живут в своих VPC и соединяются с Management VPC с помощью VPC peering. Доступ к закрытым ресурсам (без внешних айпишников) происходит через промежуточный Bastion инстанс.
Всё необходимое для поднятия окружений, различные ресурсы и настройки - всё лежит в Devops аккаунте, куда может иметь доступ лишь девопс, а разработчики ходят в dev-окружение и им выделяется доступ (временно, для деплоя) в stage-prod-etc.
Это (относительно) просто в реализации и поддержке, схема удовлетворяет требованиям различных #compliance (например, #NIST) и наверняка подойдёт для многих проектов, особенно тех, кто хочет начать использовать мультиаккаунты.