CodeBuildの環境変数をSecretsManagerから取得する

# はじめに
CodeBuildの環境変数の設定についてのメモです。

# 実装例

* `GITHUB_PAT`: SecretesManagerから取得する環境変数
* `SECRETS_NAME` : CodeBuildに設定する環境変数
* `REPOSITORY_URI`: 同上
* `IMAGE_URI`: 同上
* `CONTAINER_NAME`: 同上
* `CODEBUILD_RESOLVED_SOURCE_VERSION`: CodeBuildにデフォルトで設定されている環境変数

```buildspec.yml
version: 0.2

env:
  secrets-manager:
    GITHUB_PAT: ${SECRETS_NAME}:GITHUB_PAT #key: secret-id:json-key:version-stage:version-id

phases:
  pre_build:
    commands:
      - IMAGE_URI="${REPOSITORY_URI}:$(echo ${CODEBUILD_RESOLVED_SOURCE_VERSION} | head -c 7)"
      - $(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email)
  build:
    commands:
      - echo Build started on $(date)
      - docker build --tag ${IMAGE_URI} ./ --build-arg GITHUB_PAT=${GITHUB_PAT}
      - docker push ${IMAGE_URI}
  post_build:
    commands:
      - echo Build completed on $(date)
      - printf '[{"name":"%s","imageUri":"%s"}]' "${CONTAINER_NAME}" "$IMAGE_URI" > artifact.json

artifacts:
  files: artifact.json
```

```CodeBuild.yml
AWSTemplateFormatVersion: '2010-09-09'

Parameters:
  EnvironmentName:
    Type: String
    Default: example
  CodeBuildVpcDefaultSG:
    Type: String
    Default: sg-xxxxxxxxxxxxxx
  CodeBuildVpcId:
    Type: String
    Default: <input-your-VPC-id>
  CodeBuildVpcSubnetId:
    Type: String
    Default: <input-your-Private-Subnet-Id-which-is-associated-with-NAT-GW>
  EcrRepoName:
    Type: String
    Default: <input-your-ER-repo-name>
  ContainerName:
    Type: String
    Default: example-container
  ArtifactFileName:
    Type: String
    Default: artifact.json
  SecretsName:
    Type: String
    Default: <input-your-secrets-name-of-secerts-manager>
    NoEcho: true

Resources:
  CodeBuild:
    Type: AWS::CodeBuild::Project
    Properties:
      Name: !Sub ${EnvironmentName}-codebuild-${ServiceName}
      ServiceRole:
        Fn::ImportValue: !Sub ${EnvironmentName}:CodeBuildServiceRole
      Environment:
        ComputeType: BUILD_GENERAL1_SMALL
        Type: LINUX_CONTAINER
        Image: aws/codebuild/docker:18.09.0-1.7.0
        PrivilegedMode: true
        EnvironmentVariables:
          - Name: REPOSITORY_URI
            Value: !Sub
              - ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${Repository}
              - Repository: !Ref EcrRepoName
          - Name: CONTAINER_NAME
            Value: !Ref ContainerName
          - Name: SECRETS_NAME
            Value: !Ref SecretsName
      Artifacts:
        Type: CODEPIPELINE
      Source:
        Type: CODEPIPELINE
        BuildSpec: buildspec.yml
      VpcConfig:
        VpcId: !Ref CodeBuildVpcId
        Subnets: 
          - !Ref CodeBuildVpcSubnetId
        SecurityGroupIds:
          - !Ref CodeBuildVpcDefaultSG
```

```IamRole.yml
AWSTemplateFormatVersion: '2010-09-09'

Parameters:
  EnvironmentName:
    Type: String
    Default: example
  GithubConnectionArn:
    Type: String
    Default: <input-your-codestar-connections-arn>
    NoEcho: true
  SecretsManagerArn:
    Type: String
    Default: <input-your-secetsmanager-arn>
    NoEcho: true

Resources:
  CodeBuildServiceRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service: codebuild.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser
      Policies:
        - PolicyName: code-build-service
          PolicyDocument:
            Statement:
              - Resource: #ここだけ注目。SecretsManagerからの値の取得を許可する
                  - !Ref SecretsManagerArn
                Effect: Allow
                Action:
                  - secretsmanager:GetSecretValue
                  - secretsmanager:ListSecrets
              - Resource: '*'
                Effect: Allow
                Action:
                  - cloudformation:ValidateTemplate
              - Resource: '*'
                Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                  - ecr:GetAuthorizationToken
                  - s3:GetObject
                  - s3:PutObject
                  - s3:GetObjectVersion
                  - s3:GetBucketAcl
                  - s3:GetBucketLocation
              - Resource: !Ref GithubConnectionArn
                Effect: Allow
                Action:
                  - codestar-connections:UseConnection
                  - codestar-connections:GetConnection
                  - codestar-connections:ListConnections
              - Resource: '*'
                Effect: Allow
                Action:
                  - ec2:CreateNetworkInterface
                  - ec2:DescribeDhcpOptions
                  - ec2:DescribeNetworkInterfaces
                  - ec2:DeleteNetworkInterface
                  - ec2:DescribeSubnets
                  - ec2:DescribeSecurityGroups
                  - ec2:DescribeVpcs
              - Resource: 'arn:aws:ec2:ap-northeast-1:<account-number>:network-interface/*'
                Effect: Allow
                Action:
                  - 'ec2:CreateNetworkInterfacePermission'

Outputs:
  CodeBuildServiceRole:
    Description: The ARN of the CodeBuildServiceRole
    Value: !GetAtt CodeBuildServiceRole.Arn
    Export:
      Name: !Sub ${EnvironmentName}:CodeBuildServiceRole
```

# 参照

https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html#build-spec.env.secrets-manager