【AWS】CloudFormation ~ 認証情報の扱い ~

■ はじめに

 Github の OAuthToken などの認証情報が
AWS Systems Manager パラメータストアで管理されていて、
それをAWS CloudFormation から取得する際に
色々とトラブルあり、勉強になることがあったので、
AWS CloudFormationでの認証情報の扱いについて、メモっておく

目次

【0】認証情報について
 1)認証情報の扱い
 2)AWS内の動的なリファレンス
【1】SSM パラメータ
 1)構文
 2)サンプル
【2】SSM Secure String パラメータ
 1)構文
 2)サンプル
 3)使用上の注意
 4)補足:実際にあったトラブル
【3】Secrets Manager のシークレット
 1)構文
 2)サンプル

【0】認証情報について

1)認証情報の扱い

公式サイトの「AWS CloudFormation ベストプラクティス」より抜粋

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/security-best-practices.html#creds

テンプレートに認証情報を埋め込まない
~~~~~~
AWS CloudFormation テンプレートに機密情報を埋め込むのではなく、
スタックテンプレートで 動的なリファレンス を使用することをお勧めします。
動的なリファレンスにより、

AWS Systems Manager パラメータストアや AWS Secrets Manager など
の他のサービスで保存、管理されている外部値を参照するための
シンプルで強力な方法が提供されます。
~~~~~~

 なお、AWS Systems Manager パラメータストア、
AWS Secrets Manager の詳細は、以下の関連記事を参照のこと。

機密データの管理 ~ パラメータストア 編 ~
https://dk521123.hatenablog.com/entry/2020/01/31/231636
機密データの管理 ~ Secrets Manager 編 ~
https://dk521123.hatenablog.com/entry/2020/03/12/220717

2)AWS内の動的なリファレンス

* AWSサービス 内の動的なリファレンスについては、以下の通り。

[1] SSM パラメータ
[2] SSM Secure String パラメータ
[3] Secrets Manager のシークレット

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/dynamic-references.html

※SSM について

* SSM = Simple Systems Manager(現 Systems Manager)

【1】SSM パラメータ

* AWS Systems Manager パラメータストアに格納されている
 プレーンテキスト値を取得する

1)構文

{{resolve:ssm:<parameter-name>:<version>}}

パラメータの説明

* parameter-name
 => パラメータ名
* version
 => パラメータストアのバージョン (任意)

補足:「バージョン (任意)」について

* 2021/12/28現在、日本語訳だとversion は「必須」となっているが
 英語だと「Optional(任意)」になっている

2)サンプル

  MyS3Bucket:
    Type: 'AWS::S3::Bucket'
    Properties:
      AccessControl: '{{resolve:ssm:S3AccessControl}}' 

【2】SSM Secure String パラメータ

* AWS Systems Manager パラメータストアに格納されている
 安全な文字列を取得する

1)構文

{{resolve:ssm-secure:<parameter-name>:<version>}}

パラメータの説明

* parameter-name
 => パラメータ名
* version
 => パラメータストアのバージョン (任意)

2)サンプル

  MyIAMUser:
    Type: AWS::IAM::User
    Properties:
      UserName: 'MyUserName'
      LoginProfile:
        Password: '{{resolve:ssm-secure:IamUserPassword}}'

3)使用上の注意

* サポートしているリソースがある
 => 逆に言うと、サポートされていないリソースでは使えない...

SSM Secure String パラメータをサポートしているリソース

Resource Property Type Properties
AWS::DirectoryService::MicrosoftAD - Password
AWS::DirectoryService::SimpleAD - Password
AWS::ElastiCache::ReplicationGroup - AuthToken
AWS::IAM::User LoginProfile Password
AWS::KinesisFirehose::DeliveryStream RedshiftDestinationConfiguration Password
AWS::OpsWorks::App 送信元 Password
AWS::OpsWorks::Stack CustomCookbooksSource Password
AWS::OpsWorks::Stack RdsDbInstances DbPassword
AWS::RDS::DBCluster - MasterUserPassword
AWS::RDS::DBInstance - MasterUserPassword
AWS::Redshift::Cluster - MasterUserPassword

4)補足:実際にあったトラブル

冒頭「■ はじめに」で触れているが、
Github の OAuthToken を
AWS Systems Manager パラメータストアで管理されていて、
それをAWS CloudFormation から取得しようとした際に
以下の「エラー内容」が表示されてしまった

エラー内容

SSM Secure reference is not supported in: [AWS::CodePipeline::Pipeline/Properties/Stages]

エラーになる例

Stages:
  -
    Name: Source
    Actions:
      - 
        Name: SourceAction
        ActionTypeId:
          Category: Source
          Owner: ThirdParty
          Provider: GitHub
          Version: 1
        Configuration:
          Owner: !Ref GithubOwner
          Repo: !Ref GithubRepository
          Branch: !Ref GithubBranch
          # ★ここ★
          OAuthToken: {{resolve:ssm-secure:GithubAccessToken}}

原因

リソース「AWS::CodePipeline::Pipeline」では、
SSM Secure String パラメータをサポートしていないため

解決案

SSM Secure String パラメータではなく
Secrets Manager のシークレットで管理するように置き換える

https://eoins.medium.com/securing-github-tokens-in-a-serverless-codepipeline-dc3a24ddc356

【3】Secrets Manager のシークレット

*  AWS Secrets Manager に保存されている
 シークレットの値を取得する

1)構文

{{resolve:secretsmanager:<secret-id>:<secret-string>:<json-key>:<version-stage>:<version-id>}}

パラメータの説明

* secret-id
 => シークレットの一意の識別子(必須)
* secret-string
 => 現在、サポートされている値は SecretString のみ(任意)
 => デフォルトも「SecretString」
* json-key
 => 値を取得するキーと値のペアのキー名を指定(任意)
 => json-key を指定しない場合、シークレットテキスト全体を取得
* version-stage
 => シークレットのバージョン(任意)
 => 使用する場合は、version-id を指定できない
* version-id
 => シークレットのバージョンの固有 ID (任意)

2)サンプル

  MyRDSInstance:
    Type: 'AWS::RDS::DBInstance'
    Properties:
      DBName: MyRDSInstance
      AllocatedStorage: '20'
      DBInstanceClass: db.t2.micro
      Engine: mysql
      MasterUsername: '{{resolve:secretsmanager:MyRDSSecret:SecretString:username}}'
      MasterUserPassword: '{{resolve:secretsmanager:MyRDSSecret:SecretString:password}}'

参考文献

https://techblog.nhn-techorus.com/archives/17674

関連記事

AWS CloudFormation ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2021/10/26/224812
AWS CloudFormation ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2021/12/01/170326
AWS CloudFormation ~ 組み込み関数 ~
https://dk521123.hatenablog.com/entry/2021/12/04/202519
AWS CloudFormation ~ 疑似パラメータ ~
https://dk521123.hatenablog.com/entry/2021/12/05/134313
AWS CloudFormation ~ DeletionPolicy 属性 ~
https://dk521123.hatenablog.com/entry/2021/12/27/211328
CloudFormation で Github/CodePipeline/CodeBuild を構築する
https://dk521123.hatenablog.com/entry/2021/12/26/155956
機密データの管理 ~ パラメータストア 編 ~
https://dk521123.hatenablog.com/entry/2020/01/31/231636
機密データの管理 ~ Secrets Manager 編 ~
https://dk521123.hatenablog.com/entry/2020/03/12/220717

【AWS】CloudFormation ~ DeletionPolicy 属性 ~

■ はじめに

 CloudFormation スタックを削除した際に、
生成したリソースを削除したい場合や残しておきたいなどを
どのようにコントロールするのかを調べたので、メモする。

目次

【0】リソース属性
【1】DeletionPolicy 属性
【2】DeletionPolicy属性のオプション
 1)Delete
 2)Retain
 3)Snapshot

【0】リソース属性

* CloudFormation では、作成したリソースに対して、
 ルール(ポリシー)を設定することができる。
* リソース属性の種類は、以下の通り。
~~~~~~
1)DeletionPolicy 属性 << 今回のテーマ
2)CreationPolicy 属性
3)DependsOn 属性
4)Metadata 属性
5)UpdatePolicy 属性
6)UpdateReplacePolicy 属性
~~~~~~
* 各属性の詳細は、以下の公式サイトを参照のこと。

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-product-attribute-reference.html

【1】DeletionPolicy 属性

* CloudFormation の スタック(Stack)を削除した際に
 そのスタックで生成したリソースが
 どのような動きをするかを定義する項目

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html

【2】DeletionPolicy属性のオプション

* DeletionPolicy 属性の取りうる値は以下の通り。

1)Delete(削除) << デフォルト(ただし例外あり)
2)Retain(保持)
3)Snapshot(スナップショット)

デフォルト値の例外

* 以下のデフォルト値は、「Snapshot」
 + AWS::RDS::DBCluster リソース
 + DBClusterIdentifier プロパティを
 指定しない AWS::RDS::DBInstance リソース

1)Delete

* スタックが削除された際に、そのリソースが削除

使用上の注意

* Amazon S3 バケットでは、削除を成功させるためには
 バケットのすべてのオブジェクトを削除する必要があります。

2)Retain

* スタックが削除された場合でも、リソースを保持
* cf. Retain = 保持、持ち続ける

公式サイト および その解説動画
https://aws.amazon.com/jp/premiumsupport/knowledge-center/delete-cf-stack-retain-resources/
https://www.youtube.com/watch?v=qwX8UmEb9bQ

例1:S3バケット

AWSTemplateFormatVersion: '2010-09-09'
Resources:
  myS3Bucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain

例2:セキュリティグループおよびインバウンド

Description: AWS CloudFormation DeletionPolicy demo
Resources:
  SGroup1:
    Type: 'AWS::EC2::SecurityGroup'
    DeletionPolicy: Retain
    Properties:
      GroupDescription: EC2 Instance access
  # SecurityGroupIngress : インバウンド
  #(cf. SecurityGroupIngress=アウトバウンド)
  SGroup1Ingress:
    Type: 'AWS::EC2::SecurityGroupIngress'
    DeletionPolicy: Retain
    Properties:
      GroupName: !Ref SGroup1
      IpProtocol: tcp
      ToPort: '80'
      FromPort: '80'
      CidrIp: 0.0.0.0/0

3)Snapshot

* スタックが削除された際に、そのリソースが削除
 ただし、その前に、そのリソースのスナップショットを作成

対応リソース

* AWS::EC2::Volume
* AWS::ElastiCache::CacheCluster
* AWS::ElastiCache::ReplicationGroup
* AWS::Neptune::DBCluster
* AWS::RDS::DBCluster
* AWS::RDS::DBInstance
* AWS::Redshift::Cluster

参考文献

https://dev.classmethod.jp/articles/how-to-keep-datas-when-deleting-stacks/
https://oreout.hatenablog.com/entry/aws/cloudformation/15
https://dev.classmethod.jp/articles/aws-cloudformation-stack-deletion-policy/

関連記事

AWS CloudFormation ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2021/10/26/224812
AWS CloudFormation ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2021/12/01/170326
AWS CloudFormation ~ 組み込み関数 ~
https://dk521123.hatenablog.com/entry/2021/12/04/202519
AWS CloudFormation ~ 疑似パラメータ ~
https://dk521123.hatenablog.com/entry/2021/12/05/134313
AWS CloudFormation ~ 認証情報の扱い ~
https://dk521123.hatenablog.com/entry/2021/12/28/224501
CloudFormation で Github/CodePipeline/CodeBuild を構築する
https://dk521123.hatenablog.com/entry/2021/12/26/155956

【AWS】CloudFormation で Github/CodePipeline/CodeBuild を構築する

■ はじめに

https://dk521123.hatenablog.com/entry/2021/10/26/224812
https://dk521123.hatenablog.com/entry/2021/12/01/170326
https://dk521123.hatenablog.com/entry/2021/12/04/202519
https://dk521123.hatenablog.com/entry/2021/12/05/134313

の続き。

AWS CloudFormation (CFn) で学んだことを実践してみる。

目次

【0】今回で学べた教訓
【1】今回の仕様 - やりたいこと
【2】設計方針
 1)Security Layer
 2)Application Layer
【3】API仕様
 1)Security Layer
 2)Application Layer
【4】サンプル
 1)Security Layer
 2)Application Layer

【0】今回で学べた教訓

* 書き始めるのは、
 Application Layer (CodePipeline/CodeBuild)で
 後から、Security Layer(IAM Role/Policy)を
 書いた方がいい。
* Input(入力値。例えば、Githubの情報) を考えて、
 Parameters に書き込んでいく

【1】今回の仕様 - やりたいこと

1)以下「全体構成」のような作りをする
2)環境 EnviromemtType を定義する
 + dev (開発環境)
 + stage (検証環境)
 + prod (本番環境)
3)Githubブランチ
 「${GithubBranch(e.g. release)}/${EnviromemtType}」が
  Pushした場合、CodePiplineで関知して発火する
4)環境「stage/prod」の場合は、
  承認アクション(approval actions) が必要にする
 => dev はスルー

全体構成

Github
↓ <webhook>
CodePipline
↓ <stage/prod の場合は、承認アクションが必要>
CodeBuild

【2】設計方針

https://dk521123.hatenablog.com/entry/2021/12/01/170326

の「テンプレート管理 - スタック分割」で扱った
スタック分割で作ってみる。
 => 今回は、ネットワーク(VPCなど)は考えないものとする

1)Security Layer

* 以下のAWSサービスのIAM role および  policy を設定する
 [1] CodePipeline
 [2] CodeBuild 
 => Outputs で 2つのAWSサービスの RoleArn を出力し、
  Application Layerに渡すようにする

2)Application Layer

* 以下を作成する
 [1] CodePipeline
 [2] CodeBuild の プロジェクト
 =>  RoleArn は、「1)Security Layer」で生成された値を
  Fn::ImportValueを使って取得し設定する

【3】API仕様

1)Security Layer

Type: AWS::IAM::Role
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html

Type: AWS::IAM::Policy
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html

2)Application Layer

Type: AWS::CodePipeline::Pipeline
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-codepipeline-pipeline.html

Type: AWS::CodeBuild::Project
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-codebuild-project.html

【4】サンプル

1)Security Layer

sample-security-layer-template.yaml

AWSTemplateFormatVersion: "2010-09-09"
Description: "Security layer for Github/CodePipeline/CodeBuild"
Parameters:
  EnvironmentType:
    Description: Enter environment type
    Type: String
    Default: dev
    AllowedValues:
      - dev
      - stage
      - prod
  ArtifactStoreBucket:
    Description: Enter s3 bucket name for ArtifactStore location
    Type: String
    Default: your-s3-bucket-name
Conditions:
  IsStageOrProd:
    !Or [!Equals [stage, !Ref EnvironmentType], !Equals [prod, !Ref EnvironmentType]]
Resources:
  # For CodeBuild
  CodeBuildServiceRole:
    Type: AWS::IAM::Role
    Properties:
      Description: 'IAM Role for CodeBuild'
      RoleName: CodeBuildServiceIamRole
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service: codebuild.amazonaws.com
      Policies:
        - PolicyName: CodeBuildServiceIamPolicy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Sid: codebuild-logs
                Resource:
                  - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/*
                  - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/*:*
                Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
              - Sid: codebuild-s3
                Resource:
                  - !Sub arn:aws:s3:::${ArtifactStoreBucket}/*
                Effect: Allow
                Action:
                  - s3:GetObject
                  - s3:PutObject
                  - s3:GetBucketLocation
                  - s3:GetObjectVersion
                  - s3:GetBucketVersioning
                  - s3:GetBucketAcl
              - Sid: codebuild-codebuild
                Resource: "*"
                Effect: Allow
                Action:
                  - codebuild:BatchGet*
                  - codebuild:Get*
                  - codebuild:List*
                  - codebuild:CreateReportGroup
                  - codebuild:CreateReport
                  - codebuild:UpdateReport
                  - codebuild:BatchPutTestCases
                  - codebuild:BatchPutCodeCoverages
                  - secretsmanager:DescribeSecret
                  - secretsmanager:ListSecretVersionIds
                  - secretsmanager:GetResourcePolicy
                  - secretsmanager:GetSecretValue
              - Sid: codebuild-ssm
                Resource: "arn:aws:ssm:*:*:parameter/CodeBuild/*"
                Effect: Allow
                Action:
                  - ssm:PutParameter
  # CodePipeline
  CodePipelineServiceRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: codepipeline.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: CodePipelineServiceRole
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Resource:
                - !Sub arn:aws:s3:::${ArtifactStoreBucket}/*
                Action:
                  - s3:PutObject
                  - s3:GetObject
                  - s3:GetObjectVersion
                  - s3:GetBucketVersioning
              - Effect: Allow
                Resource: "*"
                Action:
                  - codebuild:StartBuild
                  - codebuild:StopBuild
                  - codebuild:BatchGet*
                  - codebuild:Get*
                  - codebuild:List*
                  - s3:GetBucketLocation
                  - s3:ListAllMyBuckets
                  - iam:PassRole
        - !If
          - IsStageOrProd
          -
            # See https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/approvals-iam-permissions.html
            PolicyName: Approval-CodePipelineServiceRole
            PolicyDocument:
              Version: 2012-10-17
              Statement:
                - Effect: Allow
                  Action:
                    - "codepipeline:ListPipelines"
                  Resource: "*"
                - Effect: Allow
                  Action:
                    - "codepipeline:GetPipeline"
                    - "codepipeline:GetPipelineState"
                    - "codepipeline:GetPipelineExecution"
                  # TODO: Need to modify
                  Resource: !Sub arn:aws:codepipeline:${AWS::Region}:80398EXAMPLE:MyFirstPipeline
                - Effect: Allow
                    - "codepipeline:PutApprovalResult"
                  # TODO: Need to modify
                  Resource: !Sub arn:aws:codepipeline:${AWS::Region}:80398EXAMPLE:MyFirstPipeline
          - !Ref AWS::NoValue
Outputs:
  CodePipelineRoleArn:
    Description: ARN for Role of Code Pipeline.
    Value: !GetAtt CodePipelineServiceRole.Arn
    Export:
      Name: "CodePipelineRoleArn"
  CodeBuildRoleArn:
    Description: ARN for Role of Code Build.
    Value: !GetAtt CodeBuildServiceRole.Arn
    Export:
      Name: "CodeBuildRoleArn"

2)Application Layer

sample-application-layer-template.yaml

AWSTemplateFormatVersion: "2010-09-09"
Description: "Application Layer For Github/CodePipeline/CodeBuild"

Parameters:
  EnvironmentType:
    Description: Enter environment type
    Type: String
    Default: dev
    AllowedValues:
      - dev
      - stage
      - prod
  GithubOwner:
    Description: Enter your Github Owner
    Type: String
    Default: owner-name
  GithubRepository:
    Description: Enter Github Repository
    Type: String
    Default: your-github-repository-name
  GithubBranch:
    Description: Enter Github branch
    Type: String
    Default: release
  GithubToken:
      Description: Enter Github Token
      Type: String
  ArtifactStoreBucket:
    Description: Enter s3 bucket name for ArtifactStore location
    Type: String
    Default: your-s3-bucket-name
  CodeBuildProjectName:
    Description: Enter target CodeBuild Project name
    Type: String
    Default: CodeBuild-Project-Demo
Conditions:
  IsStageOrProd:
    !Or [!Equals [stage, !Ref EnvironmentType], !Equals [prod, !Ref EnvironmentType]]
Resources:
  # CodePipeline
  # https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-codepipeline-pipeline.html
  CodePipeline:
    Type: AWS::CodePipeline::Pipeline
    Properties:
      Name: CodePipelineDemo
      ArtifactStore:
        Type: S3
        Location: !Ref ArtifactStoreBucket
      RoleArn: !ImportValue CodePipelineRoleArn
      RestartExecutionOnUpdate: false
      Stages:
        -
          Name: Source
          Actions:
            - 
              Name: SourceAction
              RunOrder: 1
              ActionTypeId:
                Category: Source
                Owner: ThirdParty
                Provider: GitHub
                Version: 1
              OutputArtifacts:
                - 
                  Name: SourceOutput
              Configuration:
                Owner: !Ref GithubOwner
                Repo: !Ref GithubRepository
                Branch: !Ref GithubBranch
                OAuthToken: !Ref GithubToken
        - !If
          - IsStageOrProd
          -
            Name: Approval
            Actions:
              -
                Name: Approval
                RunOrder: 2
                ActionTypeId:
                  Category: Approval
                  Owner: AWS
                  Provider: Manual
                  Version: 1
          - !Ref AWS::NoValue
        -
          Name: Build
          Actions:
            -
              Name: CodeBuild
              RunOrder: 3
              InputArtifacts:
                -
                  Name: SourceOutput
              ActionTypeId:
                Category: Build
                Owner: AWS
                Version: 1
                Provider: CodeBuild
              Configuration:
                ProjectName: !Ref CodeBuildProjectName
              OutputArtifacts:
                -
                  Name: CodebuildOutput
      Tags:
        - Key: Name
          Value: CodePipelineDemo
        - Key: Env
          Value: !Ref EnvironmentType
  # CodeBuild
  # https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-codebuild-project.html
  CodeBuildProject:
    Type: AWS::CodeBuild::Project
    Properties:
      Name: !Ref CodeBuildProjectName
      Description: !Sub Building stage for ${GithubBranch} in ${EnvironmentType}.
      Artifacts:
        Type: CODEPIPELINE
      Source:
        Type: CODEPIPELINE
      Environment:
        Type: LINUX_CONTAINER
        ComputeType: BUILD_GENERAL1_SMALL
        Image: aws/codebuild/standard:1.0
        # https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-codebuild-project-environmentvariable.html
        EnvironmentVariables:
          - Name: varName1
            Value: varValue1
            Type: PLAINTEXT
          - Name: varName2
            Value: /CodeBuild/testSecretParameter
            Type: SECRETS_MANAGER
          - Name: varName3
            Value: /CodeBuild/testParameter
            Type: PARAMETER_STORE
      ServiceRole: !ImportValue CodeBuildRoleArn
      ResourceAccessRole: String
      TimeoutInMinutes: 5
      Tags:
        - Key: Name
          Value: !Ref CodeBuildProjectName
        - Key: Env
          Value: !Ref EnvironmentType
      LogsConfig:
        CloudWatchLogs:
          Status: 'ENABLED'
Outputs:
  CodeBuildProjectArn:
    Description: ARN for Code Build
    Value: !GetAtt CodeBuildProject.Arn
    Export:
      Name: "CodeBuildProjectArn"

参考文献

https://dev.classmethod.jp/articles/create_codepipeline_in_cloudformation/
https://dev.classmethod.jp/articles/developing-cloudformation-ci-cd-pipeline-with-github-codebuild-codepipeline/
https://qiita.com/neruneruo/items/70f06323de44b901918d

関連記事

AWS CloudFormation ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2021/10/26/224812
AWS CloudFormation ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2021/12/01/170326
AWS CloudFormation ~ 組み込み関数 ~
https://dk521123.hatenablog.com/entry/2021/12/04/202519
AWS CloudFormation ~ 疑似パラメータ ~
https://dk521123.hatenablog.com/entry/2021/12/05/134313
AWS CloudFormation ~ DeletionPolicy 属性 ~
https://dk521123.hatenablog.com/entry/2021/12/27/211328
AWS CloudFormation ~ 認証情報の扱い ~
https://dk521123.hatenablog.com/entry/2021/12/28/224501
CodePipeline ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2020/01/23/231827
CodeBuild ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2020/01/21/221122
各開発フェーズにおける環境の呼び方
https://dk521123.hatenablog.com/entry/2020/04/16/113816