title: Execute Terraform apply with AWS assume role
body: <p>I need to execute a Terraform template to provision infrastructure for an AWS account which I can access by assuming a role.</p>
  
  <p>The problem I have now is I do not have an IAM user in that AWS account so I do not have an <code>aws_access_key_id</code> or an <code>aws_secret_access_key</code> to set up another named profile in my <code>~/.aws/credentials</code>. When I run command <code>terraform apply</code>, the template creates the infrastructure for my account, not the other account.</p>
  
  <p>How to run Terraform template using your account which has a role to access services of another AWS account?</p>
  
  <p>Here's my Terraform file:</p>
  
  <pre><code># 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::&lt;AWS-ACCOUNT-ID&gt;: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 = &lt;&lt;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 = &lt;&lt;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 = &lt;&lt;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}"
              }
          }
      }
  }
  </code></pre>
  
  <blockquote>
    <p>Update:</p>
  </blockquote>
  
  <p>Following Darren's answer (it makes a lot of sense) below, I added:</p>
  
  <pre><code>provider "aws" {
    region                  = "us-east-1"
    shared_credentials_file = "${pathexpand("~/.aws/credentials")}"
    profile                 = "default"
  
    assume_role {
      role_arn = "arn:aws:iam::&lt;OTHER-ACCOUNT&gt;:role/&lt;ROLE-NAME&gt;"
    }
  }
  </code></pre>
  
  <p>However, I ran into this error:</p>
  
  <blockquote>
    <ul>
    <li><p>provider.aws: The role "arn:aws:iam:::role/" cannot be assumed.</p>
    
    <p>There are a number of possible causes of this - the most common are:</p>
    
    <ul>
    <li>The credentials used in order to assume the role are invalid</li>
    <li>The credentials do not have appropriate permission to assume the role</li>
    <li>The role ARN is not valid</li>
    </ul></li>
    </ul>
  </blockquote>
  
  <p>I've checked the role in the other account and I can switch to that role using the AWS Console from my account. I've also checked AWS guide <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html" rel="noreferrer">here</a></p>
  
  <p>So: that role ARN is valid, I do have credentials to assume the role and all the permissions I need to run the stack.</p>
  
  <blockquote>
    <p>Update</p>
  </blockquote>
  
  <p>I've also tried with a <strong>new role that has all access to services</strong>. However, I ran into this error:</p>
  
  <blockquote>
    <p>Error: Error refreshing state: 2 error(s) occurred:</p>
  
  <pre><code>    * aws_codebuild_project.build_project: 1 error(s) occurred:
  
      * aws_codebuild_project.build_project: aws_codebuild_project.build_project: Error retreiving Projects:
  </code></pre>
    
    <p>"InvalidInputException: Invalid project ARN: account ID does not match
    caller's account\n\tstatus code: 400, request id: ..."
            * aws_s3_bucket.build_artifact_bucket: 1 error(s) occurred:</p>
  
  <pre><code>    * aws_s3_bucket.build_artifact_bucket: aws_s3_bucket.build_artifact_bucket: error getting S3 Bucket CORS
  </code></pre>
    
    <p>configuration: AccessDenied: Access Denied
                status code: 403, request id: ..., host id: ...</p>
  </blockquote>
  
  <p>=====</p>
  
  <blockquote>
    <p>UPDATE 29 Apr 2019:</p>
  </blockquote>
  
  <p>Following @Rolando's suggestion, I've added this policy to the user of the MAIN ACCOUNT that I'm trying to use to assume the role of the OTHER ACCOUNT where I'm planning to execute <code>terraform apply</code>.</p>
  
  <pre><code>{
      "Version": "2012-10-17",
      "Statement": {
          "Effect": "Allow",
          "Action": "sts:AssumeRole",
          "Resource": "arn:aws:iam::&lt;OTHER-ACCOUNT-ID&gt;:role/admin"
      }
  }
  </code></pre>
  
  <p>This is the <code>Trust Relationship</code> of the role <code>admin</code> belongs to the OTHER ACCOUNT:</p>
  
  <pre><code>{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Principal": {
          "AWS": "arn:aws:iam::&lt;MAIN_ACCOUNT_ID&gt;:root"
        },
        "Action": "sts:AssumeRole",
        "Condition": {
          "Bool": {
            "aws:MultiFactorAuthPresent": "true"
          }
        }
      }
    ]
  }
  </code></pre>
  
  <p>However, when I ran this command:</p>
  
  <pre><code>aws sts assume-role --role-arn arn:aws:iam::&lt;OTHER-ACCOUNT-ID&gt;:role/admin --role-session-name "RoleSession1" --profile default &gt; assume-role-output.txt
  </code></pre>
  
  <p>I have this error:</p>
  
  <pre><code>An error occurred (AccessDenied) when calling the AssumeRole operation: Access denied
  </code></pre>