AWSのAPIにアクセスするには、APIへのリクエストに署名する必要があり、署名するための秘密鍵が必要である。IAM Userのアクセス・キーを割り当てることもできるが、AWSのサービス、例えばEC2インスタンスからAPIにアクセスする場合は、IAM Roleを使用すると、秘密情報をホスト内に保存することなく、安全にAPIへのリクエストを行うことができる。
この記事では、AWSの、あるアカウントのEC2インスタンスから、別のアカウントのAWSサービスのAPIをコールする場合を例として、どのようにアクセス権限を委任しているかを順に説明する。
この記事では、以下のリソースを作成するとする。
- アカウントA
- アカウントA内のEC2インスタンスC
- アカウントA内のIAM Role Role_D
- アカウントA内のIAM Policy Policy_E
- アカウントB
- アカウントB内のIAM Role Role_F
EC2インスタンスAにIAM Roleをアタッチする
EC2インスタンスには、一つだけ IAM Roleをアタッチできる。
EC2インスタンスにアタッチするIAM Role Role_Dの「信頼関係」のポリシー・ドキュメントは、以下のように PrincipalにEC2サービスを指定し、ActionにSTSサービスのAssumeRoleを指定する。AWSコンソールでIAM Roleを作成する場合は、ウィザードで簡単にポリシー・ドキュメントを作成できる。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
PrincipalがEC2サービスの場合、インスタンス内から以下の仮想的なネットワークのエンドポイントにアクセスすることでActionのサービスを呼び出すことができる。
http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name>
{
"Code" : "Success",
"LastUpdated" : "yyyy-mm-ddThh:mm:ssZ",
"Type" : "AWS-HMAC",
"AccessKeyId" : "ASIAW7##############",
"SecretAccessKey" : "G5sCiFYmltsyiHV#########################",
"Token" : "IQoJb3###########################################################################################",
"Expiration" : "yyyy-mm-ddThh:mm:ssZ"
}
IAM Role Role_DのActionに指定した STSサービスのAssumeRole APIが、アクセス・キーを作成する。このアクセス・キーは、IAM Userに割り当てたアクセス・キーと同様に、AWSのサービスのAPIへのリクエストの署名の鍵として使用できる。IAM Userのアクセス・キーとは異なり、STSサービスが生成するアクセス・キーには有効期限が設定されていて、保存することなく、都度生成して使用する。
このIAM Roleのアクセス権限に、例えば、CloudWatchReadOnlyポリシーをアタッチすると、EC2インスタンスからCloud WatchのAPIにアクセスできるようになる。
アカウントBに、アカウントAへ権限を委任するRoleを設置する
アカウントBのIAM Roleのポリシー・ドキュメントに、PrincipalがアカウントAを指すARNを指定し、ActionにSTSサービスのAssumeRoleを指定したRole_Fを作成する。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<アカウントAのID>:root"
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}
このRoleは、AWSコンソールでは、ウィザードを使用して、アカウントIDを指定するだけで作成できる。
このRoleが存在することで、アカウントAからこのIAM Roleにアタッチしたポリシーの権限の委任を受けることができる。
アカウントAのRole_Dに、アカウントBのRole_Fを要求する権限を与える
Role_Dのアクセス権限に、以下のIAM Policy Policy_Eをアタッチする。Actionに指定した、STSサービスのAssumeRoleにより、Resouceに指定したARNが示すアカウントBのRole_Fにアクセスする権限をこのIAM Roleに与える。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::<アカウントBのID>:role/Role_F"
}
]
}
EC2インスタンスAから、アカウントBのIAM Role Role_Fの権限の委任を受ける
EC2インスタンスAから、アカウントBのIAM Role Role_Fを使って、アカウントBのサービスの権限の委任を受けるには、Role_Dの委任により、アカウントAのSTSサービスのAssumeRole APIに、RoleArnパラメータにRole_FのARNを指定してアクセスすることでアクセス・キーを作成し、アカウントBのAWSサービスのAPIへのリクエストの署名の鍵とする。
AWS SDK for Rubyの場合、「AWS STS アクセストークンの作成」のように、Role_FのARNを指定して、アクセスキーを取得する。
role_credentials = Aws::AssumeRoleCredentials.new(
client: Aws::STS::Client.new,
role_arn: "arn:aws:iam::<アカウントBのID>:role/Role_F",
role_session_name: "<任意の名前>"
)
s3 = Aws::S3::Client.new(credentials: role_credentials)
上記のコードは、STSサービス、S3サービスにアクセスするリージョンをデフォルト設定から取得していることに注意。必要に応じて、regionオプションを指定する。
まとめ
EC2インスタンスAは、Role_Dにより、Role_DにアタッチされたIAM Policyによる権限の委任を受け、Policy_Eの権限とアカウントBのRole_FによりRole_FにアタッチされたIAM Policyによる権限の委任を受けることで、アカウントBのサービスにアクセスすることができる。
おつかれさまでした。