ロールを引き受けることでアクセスできるAWSアカウントのインフラストラクチャをプロビジョニングするためにTerraformテンプレートを実行する必要があります。
現在の問題は、そのAWSアカウントにIAMユーザーがいないため、aws_access_key_id
またはaws_secret_access_key
がなく、~/.aws/credentials
に別の名前付きプロファイルを設定できないことです。コマンドterraform apply
を実行すると、テンプレートにより、他のアカウントではなく、私のアカウントのインフラストラクチャが作成されます。
別のAWSアカウントのサービスにアクセスする役割を持つアカウントを使用してTerraformテンプレートを実行するにはどうすればよいですか?
これが私のTerraformファイルです。
# Input variables
variable "aws_region" {
type = "string"
default = "us-east-1"
}
variable "pipeline_name" {
type = "string"
default = "static-website-terraform"
}
variable "github_username" {
type = "string"
default = "COMPANY"
}
variable "github_token" {
type = "string"
}
variable "github_repo" {
type = "string"
}
provider "aws" {
region = "${var.aws_region}"
assume_role {
role_arn = "arn:aws:iam::<AWS-ACCOUNT-ID>:role/admin"
profile = "default"
}
}
# CodePipeline resources
resource "aws_s3_bucket" "build_artifact_bucket" {
bucket = "${var.pipeline_name}-artifact-bucket"
acl = "private"
}
data "aws_iam_policy_document" "codepipeline_assume_policy" {
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["codepipeline.amazonaws.com"]
}
}
}
resource "aws_iam_role" "codepipeline_role" {
name = "${var.pipeline_name}-codepipeline-role"
assume_role_policy = "${data.aws_iam_policy_document.codepipeline_assume_policy.json}"
}
# CodePipeline policy needed to use CodeCommit and CodeBuild
resource "aws_iam_role_policy" "attach_codepipeline_policy" {
name = "${var.pipeline_name}-codepipeline-policy"
role = "${aws_iam_role.codepipeline_role.id}"
policy = <<EOF
{
"Statement": [
{
"Action": [
"s3:GetObject",
"s3:GetObjectVersion",
"s3:GetBucketVersioning",
"s3:PutObject"
],
"Resource": "*",
"Effect": "Allow"
},
{
"Action": [
"cloudwatch:*",
"sns:*",
"sqs:*",
"iam:PassRole"
],
"Resource": "*",
"Effect": "Allow"
},
{
"Action": [
"codebuild:BatchGetBuilds",
"codebuild:StartBuild"
],
"Resource": "*",
"Effect": "Allow"
}
],
"Version": "2012-10-17"
}
EOF
}
# CodeBuild IAM Permissions
resource "aws_iam_role" "codebuild_assume_role" {
name = "${var.pipeline_name}-codebuild-role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "codebuild.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}
resource "aws_iam_role_policy" "codebuild_policy" {
name = "${var.pipeline_name}-codebuild-policy"
role = "${aws_iam_role.codebuild_assume_role.id}"
policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:GetObjectVersion",
"s3:GetBucketVersioning"
],
"Resource": "*",
"Effect": "Allow"
},
{
"Effect": "Allow",
"Resource": [
"${aws_codebuild_project.build_project.id}"
],
"Action": [
"codebuild:*"
]
},
{
"Effect": "Allow",
"Resource": [
"*"
],
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
]
}
]
}
POLICY
}
# CodeBuild Section for the Package stage
resource "aws_codebuild_project" "build_project" {
name = "${var.pipeline_name}-build"
description = "The CodeBuild project for ${var.pipeline_name}"
service_role = "${aws_iam_role.codebuild_assume_role.arn}"
build_timeout = "60"
artifacts {
type = "CODEPIPELINE"
}
environment {
compute_type = "BUILD_GENERAL1_SMALL"
image = "aws/codebuild/nodejs:6.3.1"
type = "LINUX_CONTAINER"
}
source {
type = "CODEPIPELINE"
buildspec = "buildspec.yml"
}
}
# Full CodePipeline
resource "aws_codepipeline" "codepipeline" {
name = "${var.pipeline_name}-codepipeline"
role_arn = "${aws_iam_role.codepipeline_role.arn}"
artifact_store = {
location = "${aws_s3_bucket.build_artifact_bucket.bucket}"
type = "S3"
}
stage {
name = "Source"
action {
name = "Source"
category = "Source"
owner = "ThirdParty"
provider = "GitHub"
version = "1"
output_artifacts = ["SourceArtifact"]
configuration {
Owner = "${var.github_username}"
OAuthToken = "${var.github_token}"
Repo = "${var.github_repo}"
Branch = "master"
PollForSourceChanges = "true"
}
}
}
stage {
name = "Deploy"
action {
name = "DeployToS3"
category = "Test"
owner = "AWS"
provider = "CodeBuild"
input_artifacts = ["SourceArtifact"]
output_artifacts = ["OutputArtifact"]
version = "1"
configuration {
ProjectName = "${aws_codebuild_project.build_project.name}"
}
}
}
}
更新:
以下のダレンの答え(それは非常に理にかなっています)に従って、私は追加しました:
provider "aws" {
region = "us-east-1"
shared_credentials_file = "${pathexpand("~/.aws/credentials")}"
profile = "default"
assume_role {
role_arn = "arn:aws:iam::<OTHER-ACCOUNT>:role/<ROLE-NAME>"
}
}
しかし、私はこのエラーに遭遇しました:
provider.aws:「arn:aws:iam ::: role /」という役割は想定できません。
これにはいくつかの原因が考えられます。最も一般的な原因は次のとおりです。
- 役割を引き受けるために使用される資格情報が無効です
- 資格情報に、役割を引き受ける適切な権限がありません
- ロールARNが無効です
他のアカウントのロールを確認しました。自分のアカウントからAWSコンソールを使用してそのロールに切り替えることができます。 AWSガイドもチェックしました こちら
つまり、そのロールARNは有効です。私には、そのロールを引き受ける資格情報と、スタックを実行するために必要なすべての権限があります。
更新
また、サービスへのすべてのアクセス権を持つ新しい役割を試しました。しかし、私はこのエラーに遭遇しました:
エラー:状態の更新中にエラーが発生しました:2つのエラーが発生しました:
* aws_codebuild_project.build_project: 1 error(s) occurred: * aws_codebuild_project.build_project: aws_codebuild_project.build_project: Error retreiving Projects:
"InvalidInputException:無効なプロジェクトARN:アカウントIDが呼び出し元のアカウントと一致しません\ n\tステータスコード:400、リクエストID:..." * aws_s3_bucket.build_artifact_bucket:1エラーが発生しました:
* aws_s3_bucket.build_artifact_bucket: aws_s3_bucket.build_artifact_bucket: error getting S3 Bucket CORS
構成:AccessDenied:アクセス拒否ステータスコード:403、リクエストID:...、ホストID:...
=====
更新2019年4月29日:
@Rolandoの提案に従って、私がterraform apply
を実行する予定のOTHER ACCOUNTの役割を引き受けるために使用しようとしているMAIN ACCOUNTのユーザーにこのポリシーを追加しました。
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::<OTHER-ACCOUNT-ID>:role/admin"
}
}
これはadmin
のTrust Relationship
がOTHER ACCOUNTに属しています:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<MAIN_ACCOUNT_ID>:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "true"
}
}
}
]
}
ただし、このコマンドを実行したとき:
aws sts assume-role --role-arn arn:aws:iam::<OTHER-ACCOUNT-ID>:role/admin --role-session-name "RoleSession1" --profile default > assume-role-output.txt
私はこのエラーがあります:
An error occurred (AccessDenied) when calling the AssumeRole operation: Access denied
特定のロール(他のアカウントを含む)としてコマンドを実行したい場合はいつでも、防弾ソリューションがあります。 AWS CLIツールがインストールされていると思います。また、jq(jsonからデータを解析および抽出する簡単なツール)もインストールする必要がありますが、データは任意の方法で解析できます。
aws_credentials=$(aws sts assume-role --role-arn arn:aws:iam::1234567890:role/nameOfMyrole --role-session-name "RoleSession1")
export AWS_ACCESS_KEY_ID=$(echo $aws_credentials|jq '.Credentials.AccessKeyId'|tr -d '"')
export AWS_SECRET_ACCESS_KEY=$(echo $aws_credentials|jq '.Credentials.SecretAccessKey'|tr -d '"')
export AWS_SESSION_TOKEN=$(echo $aws_credentials|jq '.Credentials.SessionToken'|tr -d '"')
1行目はaws sts
コマンドからの応答を割り当て、それを変数に入れます。最後の3行は、最初のコマンドから値を選択し、aws
cliが使用する変数に割り当てます。
考慮事項:
Bashスクリプトを作成する場合は、そこにもterraformコマンドを追加します。上記の行でbashを作成し、「。」で実行することもできます。前(つまり:. ./get-creds.sh
)。これにより、現在のbashシェルに変数が作成されます。
ロールの有効期限。ロールには通常1時間の有効期限があることに注意してください。
これで、シェルに3つの変数AWS_ACCESS_KEY_ID
、AWS_SECRET_ACCESS_KEY
、AWS_SESSION_TOKEN
が設定されます。これは、~/.aws/credentials
をオーバーライドすることを意味します。これをクリアする最も簡単な方法は、新しいbashセッションを開始することです。
これを理解するためのソースとしてこの記事を使用しました: https://docs.aws.Amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html
他のアカウントの信頼関係のポリシーを見ると、条件が適用されています多要素認証以下が強調表示されています。したがって、ユーザーは、役割を引き受ける前に認証された2つの要素を使用する必要があります。この条件を削除して、コードを実行してみてください。
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "true"
}
}
次のように実行できるはずです。Terraformで、awsプロバイダーを設定して、ローカルのshared_credentials_fileを使用します。
provider "aws" {
region = "us-east-1"
shared_credentials_file = "${pathexpand("~/.aws/credentials")}"
profile = "default"
assume_role {
role_arn = "arn:aws:iam::1234567890:role/OrganizationAccountAccessRole"
}
}
「プロファイル」は、AWSアクセスキーを持つ〜/ .aws/credentials内の名前付きプロファイルです。例えば。
[default]
region = us-east-1
aws_access_key_id = AKIAJXXXXXXXXXXXX
aws_secret_access_key = Aadxxxxxxxxxxxxxxxxxxxxxxxxxxxx
これは、アクセスするアカウントのIAMユーザーではありません。 「ソース」アカウントにあります(AWS cliにアクセスするには、ある時点でキーが必要になります)。
「assume_role.role_arn」は、引き受けたいアカウントのロールです。 「プロファイル」のIAMユーザーは、その役割を引き受けることが許可されている必要があります。
一般的に言えば、bootstrapターゲットアカウントです。最低限、これは、パイプラインの役割から引き継がれる役割を作成することを意味しますが、他のリソースを含めることができます。