はじめに
前回の記事:はじめてのAWS CloudFormation -S3バケット作成編-
前回に引き続きCloudFormationを学ぼうという試みと取り組んだ内容の記録です。
今回はCloudFormationでIAMユーザー、グループ、ポリシーを作成してみます。
IAMユーザーのパラメータ設計
作成するIAMユーザーを考えます。
社内でアカウントを払い出す時にありがちなユーザーと権限を想定して以下のようにしました。
-
方針
- IAMポリシーは権限管理を容易にするため、原則IAMグループに対してポリシーをアタッチする(個々のユーザーに対して直接ポリシーをアタッチしない)。
- 運用ユーザー相当のOpeUserはec2インスタンスの起動・停止のみ操作可能とし、その他のサービスについては読み取りのみ可能とする。
- 各IAMユーザーのパスワードは、共通のものをデプロイ時にパラメーターとして指定。初回ログイン時に変更させる。
IAMグループ
IAMグループ名 | マネージドポリシー | カスタムポリシー |
---|---|---|
CFn-test-AdminGroup | AdministratorAccess | - |
CFn-test-PowerUserGroup | PowerUserAccess | - |
CFn-test-OpeGroup | ReadOnlyAccess | CFn-test-ec2-OpePolicy |
- IAMユーザー
IAMユーザー名 | 所属グループ |
---|---|
CFn-test-AdminUser | CFn-test-AdminGroup |
CFn-test-PowerUser | CFn-test-PowerUserGroup |
CFn-test-OpeUser | CFn-test-OpeGroup |
- カスタムポリシー:CFn-test-ec2-OpePolicy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ActionInstances",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:StartInstances",
"ec2:StopInstances"
],
"Resource": "*"
}
]
}
テンプレート用パラメータの確認
公式ドキュメントから各リソースで指定可能なPropertiesを確認します。
IAMグループ
Type: AWS::IAM::Group
Properties:
#グループ名を指定
GroupName: String
#付与するマネージドポリシーのARNを指定
ManagedPolicyArns:
- String
#パスを指定
Path: String
#インラインポリシーを記載
Policies:
- Policy
IAMユーザー
Type: AWS::IAM::User
Properties:
#所属グループ名を指定
Groups:
- String
#パスワードに関する設定を指定
LoginProfile:
LoginProfile
#付与するマネージドポリシーのARNを指定
ManagedPolicyArns:
- String
#パスを指定
Path: String
#PermissionsBoundaryを指定
PermissionsBoundary: String
#インラインポリシーを記載
Policies:
- Policy
#タグを指定
Tags:
- Tag
#ユーザー名を指定
UserName: String
IAMポリシー
AWS公式ドキュメント - AWS::IAM::ManagedPolicy
IAMポリシー作成時に指定するリソースタイプとしては、「AWS::IAM::ManagedPolicy」と「AWS::IAM::Policy」が存在します。
紛らわしいのですがカスタムポリシー(カスタマー管理ポリシー)を作成する場合は「AWS::IAM::ManagedPolicy」を指定します。
「AWS::IAM::Policy」で作成するとインラインポリシーの作成になってしまいます。
Type: AWS::IAM::ManagedPolicy
Properties:
#説明を記載
Description: String
#アタッチするIAMグループを指定
Groups:
- String
#ポリシー名を指定
ManagedPolicyName: String
#パスを指定
Path: String
#ポリシーの内容を記載
PolicyDocument: Json
#アタッチするIAMロールを指定
Roles:
- String
#アタッチするIAMユーザーを指定
Users:
- String
Propertiesを記載
リソースごとにPropertiesを記載します。以下のようになりました。
IAMグループ
#"CFn-test-AdminGroup"
AdminUserGroup:
Type: AWS::IAM::Group
Properties:
GroupName: !Ref AdminUserGroupName
#マネージドポリシーのアタッチ
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AdministratorAccess
#"CFn-test-PowerGroup"
PowerUserGroup:
Type: AWS::IAM::Group
Properties:
GroupName: !Ref PowerUserGroupName
#マネージドポリシーのアタッチ
ManagedPolicyArns:
- arn:aws:iam::aws:policy/PowerUserAccess
#"CFn-test-OpeGroup"
OpeUserGroup:
Type: AWS::IAM::Group
Properties:
GroupName: !Ref OpeUserGroupName
#マネージドポリシーのアタッチ
ManagedPolicyArns:
- arn:aws:iam::aws:policy/ReadOnlyAccess
#AWS :: IAM :: ManagedPolicyリソースは戻り値としてARNを返すため、!RefでARNを取得
- !Ref OpePolicy
IAMユーザー
#CFn-test-AdminUser
AdminUser:
Type: AWS::IAM::User
Properties:
UserName: !Ref AdminUserName
Groups:
- !Ref AdminUserGroupName
#初期パスワードとリセット設定
LoginProfile:
Password: !Ref Passwd
PasswordResetRequired: true
#CFn-test-PowerUser
PowerUser:
Type: AWS::IAM::User
Properties:
UserName: !Ref PowerUserName
Groups:
- !Ref PowerUserGroupName
#初期パスワードとリセット設定
LoginProfile:
Password: !Ref Passwd
PasswordResetRequired: true
#CFn-test-OpeUser
OpeUser:
Type: AWS::IAM::User
Properties:
UserName: !Ref OpeUserName
Groups:
- !Ref OpeUserGroupName
#初期パスワードとリセット設定
LoginProfile:
Password: !Ref Passwd
PasswordResetRequired: true
IAMポリシー
OpePolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: "CFn-test-ec2-OpePolicy"
PolicyDocument:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ActionInstances",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:StartInstances",
"ec2:StopInstances"
],
"Resource": "*"
}
]
}
完成したCloudFormationテンプレート
AWSTemplateFormatVersion: 2010-09-09
Description: Create IAM Users
Parameters:
AdminUserGroupName:
Type: String
Default: CFn-test-AdminGroup
Description: AdminUserGroupName
PowerUserGroupName:
Type: String
Default: CFn-test-PowerUserGroup
Description: PowerUserGroupName
OpeUserGroupName:
Type: String
Default: CFn-test-OpeGroup
Description: OperationUserGroupName
AdminUserName:
Type: String
Default: CFn-test-AdminUser
Description: AdminUserName
PowerUserName:
Type: String
Default: CFn-test-PowerUser
Description: PowerUserName
OpeUserName:
Type: String
Default: CFn-test-OpeUser
Description: OpeUserName
Passwd:
Type: String
Description: Password
NoEcho: True
Resources:
AdminUserGroup:
Type: AWS::IAM::Group
Properties:
GroupName: !Ref AdminUserGroupName
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AdministratorAccess
PowerUserGroup:
Type: AWS::IAM::Group
Properties:
GroupName: !Ref PowerUserGroupName
ManagedPolicyArns:
- arn:aws:iam::aws:policy/PowerUserAccess
OpeUserGroup:
Type: AWS::IAM::Group
Properties:
GroupName: !Ref OpeUserGroupName
ManagedPolicyArns:
- arn:aws:iam::aws:policy/ReadOnlyAccess
- !Ref OpePolicy
AdminUser:
Type: AWS::IAM::User
Properties:
UserName: !Ref AdminUserName
Groups:
- !Ref AdminUserGroupName
LoginProfile:
Password: !Ref Passwd
PasswordResetRequired: true
PowerUser:
Type: AWS::IAM::User
Properties:
UserName: !Ref PowerUserName
Groups:
- !Ref PowerUserGroupName
LoginProfile:
Password: !Ref Passwd
PasswordResetRequired: true
OpeUser:
Type: AWS::IAM::User
Properties:
UserName: !Ref OpeUserName
Groups:
- !Ref OpeUserGroupName
LoginProfile:
Password: !Ref Passwd
PasswordResetRequired: true
OpePolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: "CFn-test-ec2-OpePolicy"
PolicyDocument:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ActionInstances",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:StartInstances",
"ec2:StopInstances"
],
"Resource": "*"
}
]
}
Outputs:
UserName:
Description: UserName
Value: !Join [",", [!Ref AdminUserName, !Ref PowerUserName, !Ref OpeUserName]]
LoginURL:
Description: LoginURL
Value: !Join ["", ["https://", !Ref AWS::AccountId, ".signin.aws.amazon.com/console"]]
実行後の確認
考慮した点や途中発生したエラーについて
Parametersセクション
グループ/ユーザー名は固定値でも良かったのですが、Parametersセクションでデプロイ時に指定可能にしています。
Default:
の値として「IAMユーザーのパラメータ設計」で決めた値を記載しているため、最初から入力された状態になっています。
Outputsセクション
Outputsセクションで、作成されたIAMユーザー名の表示とログインURLの生成を行いデプロイ完了後に「出力」タブで確認できるようにしています。
機能的にはなくても良いのですが、前回のS3バケット作成で使うことがなかったOutputsセクションを使ってみたかっただけです。
NoEcho属性
Parametersセクションのパスワードを指定するPasswd:
について、NoEcho: True
を指定しています。
最初はNoEcho属性を記載していなかったのですがVSCode上で[cfn-lint]: Parameter Passwd used as Password, therefore NoEcho should be True
という警告が表示されていました。
NoEcho属性を記載しない場合、以下のように「パラメータ」タブに指定した値がマスクされずに表示さるため、NoEcho: True
を記載した方が良い旨の警告でした。
NoEcho属性を記載した場合以下のようになります。
CloudFormationに対して読み取り権限があればパラメータとして渡したパスワード情報を見ることができてしまうので、
ログインパスワード等の重要情報をパラメータとして渡す場合はNoEcho: True
を指定してマスクした方が安全性が高まります。
おわりに
CloudFormationを使ってIAMユーザー、グループ、ポリシーを作成してみました。
今回は自分のAWSアカウント内で完結していますが、
AWS Organizationsを利用している場合、Organizations管理アカウントからCloudFormationのStackSetsを利用することで、
OU単位で簡単に複数のAWSアカウントに対して同じリソースをデプロイすることもできるようです。
(Organizations環境でなくても、StackSetsを利用することで別アカウントに対してのClodFormation実行は可能)
会社で検証やプロジェクトごとのアカウント払い出し時に、標準化されたIAMユーザーや権限のセットがあればテンプレート化することで払い出しにかかる時間を短縮できそうですね。