この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
EC2インスタンスに「特定IAMロール」を必ず割り当てる仕組みを作ってみました。
作ったもの(構成図)
構成要素は以下のとおりです。
EC2ロール(インスタンスプロファイル)
自動アタッチさせたい EC2ロール(インスタンスプロファイル)です。
後述するテンプレートには以下権限を割り当てています。 SSMを活用する上である程度必要になってくる権限を付与しました。
- CloudWatchAgentServerPolicy(AWS管理ポリシー)
- AmazonSSMManagedInstanceCore(AWS管理ポリシー)
- AmazonSSMPatchAssociation(AWS管理ポリシー)
Session Managerログ保管用バケット
への PutObject/PutObjectAcl 権限
SSM State Manager 関連付け
Systems Manager(SSM) State Manager はインスタンスのあるべき状態を定義するものです。 この定義は 関連付け(Association) と言います。 関連付けには以下のような設定パラメータがあります。
- 対象: どのインスタンスの状態を定義するか
- 実行ドキュメント: どのドキュメントを実行するか
- スケジュール: どの頻度で実行するか(or 1回のみの実施か)
今回は以下のような関連付け(および実行のためのSSMロール)を作りました。
- 対象: すべてのインスタンス
- 実行ドキュメント: AWS-AttachIAMToInstance
- スケジュール: 1時間ごと
作ったもの(コード)
テンプレートがこちら。
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
# #####
# Parameters for EC2 Role, Instance Profile
# #####
EC2RoleName:
Type: String
Default: "EC2DefaultRole"
SSMSessionManagerLogBucketName:
Type: String
Default: "DOC-EXAMPLE-BUCKET"
# #####
# Parameters for SSM Role
# #####
SSMRoleName:
Type: String
Default: "SSMAutomationRole-AMIAttachToEC2"
# #####
# Parameters for SSM Association
# #####
AssociationName:
Type: String
Default: "auto-ec2-role-attach"
ForceReplace:
Type: String
Default: "true"
AllowedValues:
- "true"
- "false"
Resources:
# #####
# EC2 Role, Instance Profile
# #####
EC2Role:
Type: AWS::IAM::Role
Properties:
RoleName: !Ref EC2RoleName
Description: "This role must be attached all EC2 instances."
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service: "ec2.amazonaws.com"
Action: "sts:AssumeRole"
ManagedPolicyArns:
- "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"
- "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
- "arn:aws:iam::aws:policy/AmazonSSMPatchAssociation"
Policies:
- PolicyName: S3Logging
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- "s3:PutObject"
- "s3:PutObjectAcl"
Resource: !Sub "arn:aws:s3:::${SSMSessionManagerLogBucketName}/*"
EC2InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
InstanceProfileName: !Ref EC2Role
Roles:
- !Ref EC2Role
# #####
# SSM Role for automation
# #####
SSMRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Ref SSMRoleName
Description: "role for SSM automation: EC2 role attach"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service: "ssm.amazonaws.com"
Action: "sts:AssumeRole"
Policies:
- PolicyName: AWS-AttachIAMToInstance
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- "ec2:DescribeIamInstanceProfileAssociations"
- "ec2:DisassociateIamInstanceProfile"
- "ec2:AssociateIamInstanceProfile"
- "iam:ListInstanceProfilesForRole"
- "iam:GetInstanceProfile"
Resource: "*"
- Effect: "Allow"
Action: "iam:PassRole"
Resource: !GetAtt EC2Role.Arn
# #####
# SSM Association
# #####
SSMAssociation:
Type: AWS::SSM::Association
Properties:
AssociationName: !Ref AssociationName
Name: AWS-AttachIAMToInstance
ApplyOnlyAtCronInterval: true
ScheduleExpression: "cron(0 0/1 * * ? *)"
Targets:
- Key: InstanceIds
Values:
- "*"
# Targets:
# - Key: "tag:CCoEManaged"
# Values:
# - "true"
AutomationTargetParameterName: InstanceId
Parameters:
AutomationAssumeRole:
- !GetAtt SSMRole.Arn
ForceReplace:
- !Ref ForceReplace
RoleName:
- !Ref EC2Role
パラメータには以下を指定します。
パラメータ名 | 説明 |
---|---|
EC2RoleName | EC2ロールの名前 |
SSMSessionManagerLogBucketName | Session Manager のログ格納用バケットの名前 |
SSMRoleName | SSMロールの名前 |
AssociationName | SSM State Manager 関連付けの名前 |
ForceReplace | 既存のEC2ロールを強制的に置換するか |
試してみる
CFnテンプレートの展開
パラメータを入力してスタックを作成します。 (SSM Session Manager ログ用バケットは事前に準備必要です)
以下リソースが作られました。
EC2インスタンスを作成してみた
ロールを付与せずにEC2インスタンスを1つ作成しました。
時間を置いて見てみると、以下のようにロールが付与されていました。
次に「他のロール」をアタッチしてみました。
しばらくすると、以下のようにロールが付け替えられていました。
(もしロールの付替えを防ぎたい場合は CFnパラメータの ForceReplace
を変えることで実現できるはずです。)
(参考) SSMのログ
SSM State Manager の関連付けからは実行履歴を見られます。
内部で実行している AWS-AttachIAMToInstance
Automation のログは以下のようになります。
おわりに
「EC2インスタンスにIAMロールを自動アタッチする」仕組みを作ってみました。
ちなみに、EC2ロールの自動アタッチ自体は SSM高速セットアップで可能です。 そこでアタッチされるEC2ロールの権限が不足していて、カスタマイズしたい要件 がある場合に、この方法を試してみると良いと思います。
また、もし対象インスタンスを絞りたい場合は、 SSMAssociation の以下コメントしている部分に置き換えます。タグのキー/値に相当するインスタンスが対象になります。
Targets:
- Key: InstanceIds
Values:
- "*"
# Targets:
# - Key: "tag:CCoEManaged"
# Values:
# - "true"