こちらの記事は、以下の記事の続きとなります。
「Active Directory」と「IAM Identity Center」の連携方法などは以下をご覧ください。
背景
以前、プロジェクトで AWS を使用したいという社員にアクセス権を付与しました。
今回、別のプロジェクトでも AWS の利用を検討しているとのことで、今後、業務環境だけでなく、各プロジェクトでも AWS の利用が広まることが予想されます。
既に「Active Directory」と「IAM Identity Center」は連携済みで、以前同様にアクセスの必要な社員に対して、権限を付与することになりました。
課題
前回は特に権限を制限したりせず、既存の AWS で事前に定義された PowerUserAccess ポリシーを使用しました。
PowerUserAccess は強い権限を付与することになるので、これを機にしっかりと各ユーザーのアクセス権を最小限に制限し、以下のような運用とすることにしました。
- 別プロジェクトで使用している VPC に変更・削除や、リソースの配置ができないようにする
- VPC がどのプロジェクトで使用されているのか判断できるようにする
- 不要な AWS サービスの使用を制限する
方法
前回は、IAM Identity Center で AWS アカウントへのアクセス権を許可セットで定義し、ユーザーに割り当てました。
今回は、プロジェクトごとに割り当てる許可セットを定義し、所属するユーザーに割り当てます。
各許可セットではタグをもとに、使用可能な VPC を制限します。
これにより、プロジェクトごとに、アクセス権限を分けることが可能です。
ざっくり以下のようなイメージです。
ただ、ポイントとしては、User 2 のように複数のプロジェクトに所属する社員もいるということです。
IAM Identity Center では、1つのユーザーに対して、複数の許可セットを割り当てることも可能です。
そのため、今回は複数のプロジェクトに参加するユーザーに対しては、複数のアクセス権を付与します。
管理者側の手順
既に Active Directory でグループは作成済みで、現状の IAM Identity Center のユーザーやグループは以下のような感じです。
なお、前回設定した許可セット(PowerUserAccess)は削除して、再度割り当てる許可セットを作成する形で進めます。
画像
ProjectB に所属するユーザーに付与するアクセス権を設定していきます。
作成・更新・削除は特定の VPC に対してのみに限定し、参照などはすべてのリソースに対してできるようにします。
許可セットの作成
カスタムポリシーと AWS で定義されている ReadOnlyAccess と AmazonEC2FullAccess を付与します。
前回はマネジメントコンソールから作成したので、今回は AWS CLI を使います。
説明 : AWS サービスとリソースへの読み取り専用アクセスを提供します。
https://docs.aws.amazon.com/ja_jp/aws-managed-policy/latest/reference/ReadOnlyAccess.html
説明: AWS Management Console 経由で Amazon EC2 へのフルアクセスを提供します。
https://docs.aws.amazon.com/ja_jp/aws-managed-policy/latest/reference/AmazonEC2FullAccess.html
- 以下の AWS CLI コマンドを実行し、許可セットを作成します。
INSTNACE_ARN=$(aws sso-admin list-instances \
--query "Instances[].InstanceArn" \
--output text)
aws sso-admin create-permission-set \
--instance-arn $INSTNACE_ARN \
--name "ProjectB" \
--session-duration "PT1H"
- 以下の AWS CLI コマンドを実行し、AWS で事前に定義された ReadOnlyAccess ポリシーとAmazonEC2FullAccess ポリシーをアタッチします。
PERMISSIONSET_ARN=$(aws sso-admin list-permission-sets \
--instance-arn $INSTNACE_ARN \
--query "PermissionSets" \
--output text | tr "\t" "\n" |
while read line
do
aws sso-admin describe-permission-set \
--instance-arn $INSTNACE_ARN \
--permission-set-arn ${line} \
--query "PermissionSet.[Name,PermissionSetArn]" \
--output text
done | grep -w "ProjectB" | awk '{print $2}')
aws sso-admin attach-managed-policy-to-permission-set \
--instance-arn $INSTNACE_ARN \
--permission-set-arn $PERMISSIONSET_ARN \
--managed-policy-arn "arn:aws:iam::aws:policy/ReadOnlyAccess"
aws sso-admin attach-managed-policy-to-permission-set \
--instance-arn $INSTNACE_ARN \
--permission-set-arn $PERMISSIONSET_ARN \
--managed-policy-arn "arn:aws:iam::aws:policy/AmazonEC2FullAccess"
- 以下の AWS CLI コマンドを実行し、インラインポリシーをアタッチします。
cat << EOF > inline-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyCreateVpc",
"Effect": "Deny",
"Action": [
"ec2:CreateVpc"
],
"Resource": "*",
"Condition": {
"StringNotEqualsIfExists": {
"aws:RequestTag/Project": "ProjectB"
}
}
},
{
"Sid": "DenyChangeTag",
"Effect": "Deny",
"Action": [
"ec2:CreateTags"
],
"Resource": "*",
"Condition": {
"Null": {
"ec2:ResourceTag/Project": "false"
},
"StringNotEquals": {
"ec2:ResourceTag/Project": "ProjectB"
}
}
},
{
"Sid": "DenyModifyAndDelete",
"Effect": "Deny",
"Action": [
"ec2:Delete*",
"ec2:ModifyVpcAttribute"
],
"Resource": "*",
"Condition": {
"StringNotEquals": {
"ec2:ResourceTag/Project": "ProjectB"
}
}
}
]
}
EOF
aws sso-admin put-inline-policy-to-permission-set \
--instance-arn $INSTNACE_ARN \
--permission-set-arn $PERMISSIONSET_ARN \
--inline-policy file://inline-policy.json
- DenyCreateVpc ステートメントでは、以下の条件いずれかを満たすときに VPC の作成を拒否します。
- Project タブの指定がないとき†
- 指定された Project タブの値が ProjectB 以外のとき
- DenyChangeTag ステートメントでは、以下の条件すべてを満たすときにタグの作成を拒否します。
- リソースの Project タブが Null ではないとき
(リソースに Project タブが存在しているとき)
※ この条件がないとタグを指定した VPC の作成も拒否されます。 - リソースの Project タブの値が ProjectB 以外のとき
- リソースの Project タブが Null ではないとき
- DenyModifyAndDelete ステートメントでは、Project タブの値が ProjectB 以外のリソースに対する操作を制限します。
- VPC 属性の変更を拒否
- タグの削除 / VPC の削除 / etc. を拒否
グループを割り当て
- 以下の AWS CLI コマンドを実行し、許可セットをグループに割り当てます。
IDENTITYSTORE_ID=$(aws sso-admin list-instances \
--query "Instances[].IdentityStoreId" \
--output text)
GROUP_ID=$(aws identitystore list-groups \
--identity-store-id $IDENTITYSTORE_ID \
--query "Groups[?DisplayName=='ProjectB@corp.awsexample.com'].GroupId" \
--output text)
ACCOUNT_ID=$(aws sso-admin list-instances \
--query "Instances[].OwnerAccountId" \
--output text)
aws sso-admin create-account-assignment \
--instance-arn $INSTNACE_ARN \
--target-id $ACCOUNT_ID \
--target-type AWS_ACCOUNT \
--permission-set-arn $PERMISSIONSET_ARN \
--principal-type GROUP \
--principal-id $GROUP_ID
追加の作業
ほかのプロジェクトについても同様に進めます。
先ほどと同じような、以下の AWS CLI コマンドを実行して ProjectA 用の許可セットを作成し割り当てます。
AWS CLI コマンド
# Step1
INSTNACE_ARN=$(aws sso-admin list-instances \
--query "Instances[].InstanceArn" \
--output text)
aws sso-admin create-permission-set \
--instance-arn $INSTNACE_ARN \
--name "ProjectA" \
--session-duration "PT1H"
# Step2
PERMISSIONSET_ARN=$(aws sso-admin list-permission-sets \
--instance-arn $INSTNACE_ARN \
--query "PermissionSets" \
--output text | tr "\t" "\n" |
while read line
do
aws sso-admin describe-permission-set \
--instance-arn $INSTNACE_ARN \
--permission-set-arn ${line} \
--query "PermissionSet.[Name,PermissionSetArn]" \
--output text
done | grep -w "ProjectA" | awk '{print $2}')
aws sso-admin attach-managed-policy-to-permission-set \
--instance-arn $INSTNACE_ARN \
--permission-set-arn $PERMISSIONSET_ARN \
--managed-policy-arn "arn:aws:iam::aws:policy/ReadOnlyAccess"
aws sso-admin attach-managed-policy-to-permission-set \
--instance-arn $INSTNACE_ARN \
--permission-set-arn $PERMISSIONSET_ARN \
--managed-policy-arn "arn:aws:iam::aws:policy/AmazonEC2FullAccess"
# Step3
cat << EOF > inline-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyCreateVpc",
"Effect": "Deny",
"Action": [
"ec2:CreateVpc"
],
"Resource": "*",
"Condition": {
"StringNotEqualsIfExists": {
"aws:RequestTag/Project": "ProjectA"
}
}
},
{
"Sid": "DenyChangeTag",
"Effect": "Deny",
"Action": [
"ec2:CreateTags"
],
"Resource": "*",
"Condition": {
"Null": {
"ec2:ResourceTag/Project": "false"
},
"StringNotEquals": {
"ec2:ResourceTag/Project": "ProjectA"
}
}
},
{
"Sid": "DenyModifyAndDelete",
"Effect": "Deny",
"Action": [
"ec2:Delete*",
"ec2:ModifyVpcAttribute"
],
"Resource": "*",
"Condition": {
"StringNotEquals": {
"ec2:ResourceTag/Project": "ProjectA"
}
}
}
]
}
EOF
aws sso-admin put-inline-policy-to-permission-set \
--instance-arn $INSTNACE_ARN \
--permission-set-arn $PERMISSIONSET_ARN \
--inline-policy file://inline-policy.json
# Step4
IDENTITYSTORE_ID=$(aws sso-admin list-instances \
--query "Instances[].IdentityStoreId" \
--output text)
GROUP_ID=$(aws identitystore list-groups \
--identity-store-id $IDENTITYSTORE_ID \
--query "Groups[?DisplayName=='ProjectA@corp.awsexample.com'].GroupId" \
--output text)
ACCOUNT_ID=$(aws sso-admin list-instances \
--query "Instances[].OwnerAccountId" \
--output text)
aws sso-admin create-account-assignment \
--instance-arn $INSTNACE_ARN \
--target-id $ACCOUNT_ID \
--target-type AWS_ACCOUNT \
--permission-set-arn $PERMISSIONSET_ARN \
--principal-type GROUP \
--principal-id $GROUP_ID
タグポリシーの設定
こちらの手順は必須ではないですが、やっておくと有益な設定となります。
タグポリシーを設定すると、大文字や小文字のみが異なる、重複したタグの作成を防ぐことができます。
なお、タグを強制する設定ではないのでご注意下さい。
aws:TagKeys 条件をインラインポリシーに組み込んでも実現できるようですが、インラインポリシーが長くなり煩雑になることを防ぐため、タグポリシーを採用しました。
大文字小文字のみが異なるキーを使用したタグの重複を防ぐには、
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_tags.htmlaws:TagKeys
条件を使用して、ユーザーが適用できるタグキーを定義するか、AWS Organizations で利用できるタグポリシーを使用します。
- 以下の URL から組織内でのタグポリシーを有効化します。
https://us-east-1.console.aws.amazon.com/organizations/v2/home/policies/tag-policy
画像
- 以下の URL からタグポリシーを作成します。
https://us-east-1.console.aws.amazon.com/organizations/v2/home/policies/tag-policy/create- ポリシー名:Project
- タグキー:Project
- コンプライアンスオプション:
- ☑ タグキーに上記で指定した大文字を使用します。
- ☑ このタグキーに許可される値を指定します。
- ProjectA
- ProjectB
- 強制するリソースタイプ:
- ☑ このタグの非準拠操作を防止します。
- すべて選択
- ☑ このタグの非準拠操作を防止します。
画像
- ポリシーを選択します。
画像
- [ターゲット] タブからアカウントにアタッチします。
画像
このタグポリシーによって、タグの作成に以下のように、大文字と小文字が厳密に確認され、値も指定されたもののみに制限されます。
Key | Value | Allowed? |
---|---|---|
Project | ProjectC | ❌ No |
ProjecT | ProjectA | ❌ No |
project | ProjectA | ❌ No |
Project | projecta | ❌ No |
Project | ProjectA | ✅ Yes |
Project | ProjectB | ✅ Yes |
ユーザー側の手順
※ MFA が既に登録済みならば手順1と手順3は不要です。
- 自前のスマートフォンに Google Authenticator(MFA 認証アプリ)をインストールしてもらいます。[Google Play / App Store]
- 以下の URL からポータルにアクセスし、ユーザー名とパスワードを入力します。
適宜<Directory ID>
の箇所を、運用しているディレクトリ ID に置き換えてください。
https://<Directory ID>
.awsapps.com/start - MFA デバイスの登録 で認証アプリを選択し以下を進めます。
- QR コードを表示
- スマートフォンで Google Authenticator を起動
- アプリ右下の + から QR コードをスキャン
- アプリに追加された AWS SSO 欄の6桁の認証コードを入力
- ポータルの [アカウント] タブからプロジェクトに合わせた許可セットをクリックしログインします。
画像
社員にはその時作業するプロジェクトに合わせて、どの権限でログインするか分けてもらう運用とします。
プロジェクトを切り替えるのが煩雑ですが、ブラウザのシークレットタブやプライベートウィンドウなどを使えば同時にログインも可能です。
ひとまずは VPC を制限して社員のユーザーにアクセス権限を付与しました。
ただ、今後使用する AWS サービス範囲が広がれば、もっとたくさんの制限が必要になりそうです。
ちょっと大変そうですが、随時インラインポリシーを更新していこうと思います。
補足
公式ドキュメントに記載の IAM ユーザーや IAM Identity Center での ABAC (Attribute-based access control) では、ユーザーの属性をもとにするため、1つの IAM ポリシーで動的に制限をかけることが可能です。
しかし、上記の方法だと、複数のプロジェクトに所属する社員に対して、複数のアクセス権限を付与することはできなさそうでした。
なので、今回は面倒ではありますが、許可セットを複数作ることで対応しました。
引き続き良い方法を模索していこうと思います。