16

I created CodeBuild project in a custom VPC and in private subnet. Private subnet has internet access, also AWS console confirms that internet connection is for this code build project. I keep getting VPC_CLIENT_ERROR: Unexpected EC2 error: UnauthorizedOperation error in "Provisioning" phase of the build. There must be something missing in my service role policy but cant figure out what.

Here is CodeBuild project (terraform):

resource "aws_codebuild_project" "frontend" {
  name          = "frontend"
  build_timeout = "5"
  service_role  = "${aws_iam_role.frontend_build.arn}"

  artifacts {
    type = "S3"
    location = "frontend.myapp.com"
    namespace_type = "NONE"
    packaging = "NONE"
    path = "public"
  }

  environment {
    compute_type                = "BUILD_GENERAL1_SMALL"
    image                       = "aws/codebuild/standard:1.0"
    type                        = "LINUX_CONTAINER"
    image_pull_credentials_type = "CODEBUILD"

    environment_variable {
      name  = "SOME_KEY1"
      value = "SOME_VALUE1"
    }
  }

  logs_config {
    cloudwatch_logs {
      group_name = "build"
      stream_name = "frontend-build"
    }
  }

  source {
    type            = "GITHUB"
    location        = "https://github.com/MyOrg/my-repo.git"
    git_clone_depth = 1
    report_build_status = true
    auth {
      type = "OAUTH"
    }
  }

  vpc_config {
    vpc_id = module.vpc.vpc_id
    subnets = module.vpc.private_subnets
    security_group_ids = [aws_security_group.build.id]
  }
}

Here is service_role for this CodeBuild project:

resource "aws_iam_role" "frontend_build" {
  name = "frontend-build"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "codebuild.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF
}

And here is policy for that role:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "ec2:CreateNetworkInterfacePermission",
            "Resource": "arn:aws:ec2:us-east-1:371508653482:network-interface/*",
            "Condition": {
                "StringEquals": {
                    "ec2:AuthorizedService": "codebuild.amazonaws.com",
                    "ec2:Subnet": "subnet-124641af7a83bf872"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:CreateNetworkInterface",
                "ec2:DescribeDhcpOptions",
                "ec2:DescribeNetworkInterfaces",
                "ec2:DeleteNetworkInterface",
                "ec2:DescribeSubnets",
                "ec2:DescribeSecurityGroups",
                "ec2:DescribeVpcs",
                "ecr:BatchCheckLayerAvailability",
                "ecr:CompleteLayerUpload",
                "ecr:GetAuthorizationToken",
                "ecr:InitiateLayerUpload",
                "ecr:PutImage",
                "ecr:UploadLayerPart",
                "ecs:RunTask",
                "iam:PassRole",
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "ssm:GetParameters"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "ecr:GetDownloadUrlForLayer",
                "ecr:BatchGetImage",
                "ecr:GetAuthorizationToken",
                "s3:GetBucketAcl",
                "s3:GetBucketLocation",
                "logs:CreateLogGroup",
                "logs:PutLogEvents",
                "ecr:BatchCheckLayerAvailability"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor2",
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::xxx-frontend-build-logs",
                "arn:aws:s3:::xxx-frontend-build-logs/*"
            ]
        }
    ]
}

Here is security group for CodeBuild project:

resource "aws_security_group" "build" {
  name   = "build"
  vpc_id = module.vpc.vpc_id
}

resource "aws_security_group_rule" "build_egress" {
  type              = "egress"
  from_port         = 0
  to_port           = 0
  protocol          = "-1"
  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = aws_security_group.build.id
}
user606521
  • 14,486
  • 30
  • 113
  • 204

2 Answers2

20

It looks to me that CodeBuild service role is unable to create the ENI in VPC. The problem seems to be with this line in the CodeBuild role policy:

{
    "Sid": "VisualEditor0",
    "Effect": "Allow",
    "Action": "ec2:CreateNetworkInterfacePermission",
    "Resource": "arn:aws:ec2:us-east-1:371508653482:network-interface/*",
    "Condition": {
        "StringEquals": {
            "ec2:AuthorizedService": "codebuild.amazonaws.com",
            "ec2:Subnet": "subnet-124641af7a83bf872"     <================= Need full ARN here
        }
    }
},

Instead of:

"Condition": {
        "StringEquals": {
            "ec2:AuthorizedService": "codebuild.amazonaws.com",
            "ec2:Subnet": "subnet-124641af7a83bf872"
        }
}

try...

"Condition": {
    "StringEquals": {
    "ec2:Subnet": [
        "arn:aws:ec2:region:account-id:subnet/subnet-124641af7a83bf872"
    ],
    "ec2:AuthorizedService": "codebuild.amazonaws.com"
}

Details here: [1]

Ref: [1] Using Identity-Based Policies for CodeBuild - Allow CodeBuild Access to AWS Services Required to Create a VPC Network Interface - https://docs.aws.amazon.com/codebuild/latest/userguide/auth-and-access-control-iam-identity-based-access-control.html#customer-managed-policies-example-create-vpc-network-interface

shariqmaws
  • 8,152
  • 1
  • 16
  • 35
  • True, adding a full format for subnet fixed the issue. Thanks! – Vladyslav Didenko May 26 '20 at 10:51
  • 5
    Worth to mention that it also mandatory to have `"ec2:CreateNetworkInterface",` permission in addition to `"ec2:CreateNetworkInterfacePermission"`. I've spent two hours, hope someone save time. – FelikZ Dec 22 '20 at 23:13
  • I did not need 'ec2:CreateNetworkInterface'. I had an error in my arn, forgot the ':ec2:' component... – Fried Hoeben Mar 15 '23 at 11:20
4

You can also use StringLike in case it's not convenient for you to provide subnet id within the policy

{
  "Effect": "Allow",
  "Action": [
    "ec2:CreateNetworkInterfacePermission"
  ],
  "Resource": "arn:aws:ec2:*:*:network-interface/*",
  "Condition": {
    "StringLike": {
      "ec2:Subnet": [
        "arn:aws:ec2:*:*:subnet/*"
      ],
      "ec2:AuthorizedService": "codebuild.amazonaws.com"
    }
  }
}
Most Wanted
  • 6,254
  • 5
  • 53
  • 70