「AWS Hands-on for Beginners AWS Code サービス群を活用して、CI/CD のための構成を構築しよう！」をAWS CLIでやってみる

https://pages.awscloud.com/JAPAN-event-OE-Hands-on-for-Beginners-cicd-2022-reg-event.html?trk=aws_introduction_page

上記、「AWS Hands-on for Beginners AWS Code サービス群を活用して、CI/CD のための構成を構築しよう！」 をAWS CLIでやってみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3297641/e8252e7d-2c22-44ed-e12a-fcd59f031906.png)
ハンズオンから引用

:::note alert
Cloud9とCodeCommitは新規利用できなくなりました。
今まで利用したことがあるアカウントはまだ利用できるようです。
:::
# 02 S3 をデプロイ先とした、CI/CD 環境を構築する【事前準備 + CodeCommit編】
## S3バケット
### 変数
```bash:コマンド
# 変数
date_var=$(date +%Y%m%d) \
&& echo ${date_var}
S3_BUCKET_NAME="h4b-handson-${date_var}-bucket" \
&& echo ${S3_BUCKET_NAME}
REGION="ap-northeast-1" \
&& echo ${REGION}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # 変数
[cloudshell-user@ip-10-132-76-170 ~]$ date_var=$(date +%Y%m%d) \
> && echo ${date_var}
20240914
[cloudshell-user@ip-10-132-76-170 ~]$ S3_BUCKET_NAME="h4b-handson-${date_var}-bucket" \
> && echo ${S3_BUCKET_NAME}
h4b-handson-20240914-bucket
[cloudshell-user@ip-10-132-76-170 ~]$ REGION="ap-northeast-1" \
> && echo ${REGION}
ap-northeast-1
```
### 作成
```bash:コマンド
# バケット作成
aws s3api create-bucket \
    --bucket ${S3_BUCKET_NAME} \
    --create-bucket-configuration LocationConstraint=${REGION}

# パブリックアクセスをすべてブロック：オフ
aws s3api put-public-access-block \
    --bucket ${S3_BUCKET_NAME} \
    --public-access-block-configuration 'BlockPublicAcls=false,IgnorePublicAcls=false,BlockPublicPolicy=false,RestrictPublicBuckets=false'

# バケットの静的ウェブサイトホスティングを有効にする
aws s3 website s3://${S3_BUCKET_NAME}/ \
    --index-document index.html

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # バケット作成
[cloudshell-user@ip-10-132-76-170 ~]$ aws s3api create-bucket \
>     --bucket ${S3_BUCKET_NAME} \
>     --create-bucket-configuration LocationConstraint=${REGION}
{
    "Location": "http://h4b-handson-20240914-bucket.s3.amazonaws.com/"
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # パブリックアクセスをすべてブロック：オフ
[cloudshell-user@ip-10-132-76-170 ~]$ aws s3api put-public-access-block \
>     --bucket ${S3_BUCKET_NAME} \
>     --public-access-block-configuration 'BlockPublicAcls=false,IgnorePublicAcls=false,BlockPublicPolicy=false,RestrictPublicBuckets=false'
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # バケットの静的ウェブサイトホスティングを有効にする
[cloudshell-user@ip-10-132-76-170 ~]$ aws s3 website s3://${S3_BUCKET_NAME}/ \
>     --index-document index.html
```
### バケットポリシー適用
```bash:コマンド
# バケットポリシー(JSON)
BACKET_POLICY=$(cat << EOF
{
  "Version": "2012-10-17",
  "Statement": [
      {
          "Sid": "PublicReadGetObject",
          "Effect": "Allow",
          "Principal": "*",
          "Action": [
              "s3:GetObject"
          ],
          "Resource": [
              "arn:aws:s3:::${S3_BUCKET_NAME}/*"
          ]
      }
  ]
}
EOF
) \
&& echo ${BACKET_POLICY}

# JSONフォーマットの確認
echo ${BACKET_POLICY} | python -m json.tool

# バケットポリシー
aws s3api put-bucket-policy \
    --bucket ${S3_BUCKET_NAME} \
    --policy "${BACKET_POLICY}"

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # バケットポリシー(JSON)
[cloudshell-user@ip-10-132-76-170 ~]$ BACKET_POLICY=$(cat << EOF
> {
>   "Version": "2012-10-17",
>   "Statement": [
>       {
>           "Sid": "PublicReadGetObject",
>           "Effect": "Allow",
>           "Principal": "*",
>           "Action": [
>               "s3:GetObject"
>           ],
>           "Resource": [
>               "arn:aws:s3:::${S3_BUCKET_NAME}/*"
>           ]
>       }
>   ]
> }
> EOF
> ) \
> && echo ${BACKET_POLICY}
{ "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadGetObject", "Effect": "Allow", "Principal": "*", "Action": [ "s3:GetObject" ], "Resource": [ "arn:aws:s3:::h4b-handson-20240914-bucket/*" ] } ] }
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-76-170 ~]$ echo ${BACKET_POLICY} | python -m json.tool
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::h4b-handson-20240914-bucket/*"
            ]
        }
    ]
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # バケットポリシー
[cloudshell-user@ip-10-132-76-170 ~]$ aws s3api put-bucket-policy \
>     --bucket ${S3_BUCKET_NAME} \
>     --policy "${BACKET_POLICY}"
```
### ファイルのアップロード
```bash:コマンド
aws s3 cp index.html s3://${S3_BUCKET_NAME}/

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ aws s3 cp index.html s3://${S3_BUCKET_NAME}/
upload: ./index.html to s3://h4b-handson-20240914-bucket/index.html
```
### アクセス確認
```bash:コマンド
curl http://${S3_BUCKET_NAME}.s3-website-${REGION}.amazonaws.com

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ curl http://${S3_BUCKET_NAME}.s3-website-${REGION}.amazonaws.com
<!DOCTYPE html>

<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>S3 Static Web Hosting</title>
</head>
<body>
  Hello, AWS World!!
</body>
</html>
```
## CodeCommit
### 変数
```bash:コマンド
REPOSITORY_NAME="h4b-hands-on" \
&& echo ${REPOSITORY_NAME}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ REPOSITORY_NAME="h4b-hands-on" \
> && echo ${REPOSITORY_NAME}
h4b-hands-on
```
### 作成
```bash:コマンド
# 作成
aws codecommit create-repository \
    --repository-name ${REPOSITORY_NAME}

# ARN取得
CODECOMMIT_ARN=$(
    aws codecommit get-repository \
        --repository-name ${REPOSITORY_NAME} \
        --query repositoryMetadata.Arn\
        --output text
) \
&& echo ${CODECOMMIT_ARN}

# クローンURL取得
CLONEURLHTTP=$(
    aws codecommit get-repository \
        --repository-name ${REPOSITORY_NAME} \
        --query repositoryMetadata.cloneUrlHttp \
        --output text
) \
&& echo ${CLONEURLHTTP}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # 作成
[cloudshell-user@ip-10-132-76-170 ~]$ aws codecommit create-repository \
>     --repository-name ${REPOSITORY_NAME}
{
    "repositoryMetadata": {
        "accountId": "999999999999",
        "repositoryId": "944f7933-79af-41e8-a9af-35db1f7d0324",
        "repositoryName": "h4b-hands-on",
        "lastModifiedDate": "2024-09-14T06:11:57.395000+00:00",
        "creationDate": "2024-09-14T06:11:57.395000+00:00",
        "cloneUrlHttp": "https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/h4b-hands-on",
        "cloneUrlSsh": "ssh://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/h4b-hands-on",
        "Arn": "arn:aws:codecommit:ap-northeast-1:999999999999:h4b-hands-on",
        "kmsKeyId": "arn:aws:kms:ap-northeast-1:999999999999:key/be6cce38-51e3-4f2b-b1a3-b33b3ace5ca0"
    }
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ARN取得
[cloudshell-user@ip-10-132-76-170 ~]$ CODECOMMIT_ARN=$(
>     aws codecommit get-repository \
>         --repository-name ${REPOSITORY_NAME} \
>         --query repositoryMetadata.Arn\
>         --output text
> ) \
> && echo ${CODECOMMIT_ARN}
arn:aws:codecommit:ap-northeast-1:999999999999:h4b-hands-on
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # クローンURL取得
[cloudshell-user@ip-10-132-76-170 ~]$ CLONEURLHTTP=$(
>     aws codecommit get-repository \
>         --repository-name ${REPOSITORY_NAME} \
>         --query repositoryMetadata.cloneUrlHttp \
>         --output text
> ) \
> && echo ${CLONEURLHTTP}
https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/h4b-hands-on
```
## Cloud9
### 変数
```bash:コマンド
# Cloud9環境名
CLOUD9_ENVIRONMENT_NAME="aws-code-hands-on" \
&& echo ${CLOUD9_ENVIRONMENT_NAME}

# インスタンスタイプ
CLOUD9_INSTANCE_TYPE="t2.micro" \
&& echo ${CLOUD9_INSTANCE_TYPE}

# プラットフォーム
CLOUD9_IMAGE_ID="resolve:ssm:/aws/service/cloud9/amis/amazonlinux-2-x86_64" \
&& echo ${CLOUD9_IMAGE_ID}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # Cloud9環境名
[cloudshell-user@ip-10-132-76-170 ~]$ CLOUD9_ENVIRONMENT_NAME="aws-code-hands-on" \
> && echo ${CLOUD9_ENVIRONMENT_NAME}
aws-code-hands-on
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # インスタンスタイプ
[cloudshell-user@ip-10-132-76-170 ~]$ CLOUD9_INSTANCE_TYPE="t2.micro" \
> && echo ${CLOUD9_INSTANCE_TYPE}
t2.micro
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # プラットフォーム
[cloudshell-user@ip-10-132-76-170 ~]$ CLOUD9_IMAGE_ID="resolve:ssm:/aws/service/cloud9/amis/amazonlinux-2-x86_64" \
> && echo ${CLOUD9_IMAGE_ID}
resolve:ssm:/aws/service/cloud9/amis/amazonlinux-2-x86_64
```
### 作成
```bash:コマンド
# Cloud9環境作成
CLOUD9_ENVIRONMENT_ID=$(
    aws cloud9 create-environment-ec2 \
        --name ${CLOUD9_ENVIRONMENT_NAME} \
        --instance-type ${CLOUD9_INSTANCE_TYPE} \
        --image-id ${CLOUD9_IMAGE_ID} \
        --connection-type CONNECT_SSM \
        --automatic-stop-time-minutes 30 \
        --query environmentId \
        --output text
) \
&& echo ${CLOUD9_ENVIRONMENT_ID}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # Cloud9環境作成
[cloudshell-user@ip-10-132-76-170 ~]$ CLOUD9_ENVIRONMENT_ID=$(
>     aws cloud9 create-environment-ec2 \
>         --name ${CLOUD9_ENVIRONMENT_NAME} \
>         --instance-type ${CLOUD9_INSTANCE_TYPE} \
>         --image-id ${CLOUD9_IMAGE_ID} \
>         --connection-type CONNECT_SSM \
>         --automatic-stop-time-minutes 30 \
>         --query environmentId \
>         --output text
> ) \
> && echo ${CLOUD9_ENVIRONMENT_ID}
ed3b1f77024c4af9a55a94214b74ff54
```
:::note info
以降、Cloud9で実施
:::
## 認証ヘルパー
```bash:コマンド
git config --global credential.helper '!aws codecommit credential-helper $@'
git config --global credential.UseHttpPath true
git config --global user.name "username"
git config --global user.email "username@example.com"

```
```bash:出力
admin:~/environment $ git config --global credential.helper '!aws codecommit credential-helper $@'
admin:~/environment $ git config --global credential.UseHttpPath true
admin:~/environment $ git config --global user.name "username"
admin:~/environment $ git config --global user.email "username@example.com"
```
:::note warn
CLONEURLHTTPは適宜変更
:::
```bash:コマンド
CLONEURLHTTP="https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/h4b-hands-on"
git clone ${CLONEURLHTTP}
cd h4b-hands-on/

```
```bash:出力
admin:~/environment $ CLONEURLHTTP="https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/h4b-hands-on"
admin:~/environment $ git clone ${CLONEURLHTTP}
Cloning into 'h4b-hands-on'...
warning: You appear to have cloned an empty repository.
admin:~/environment $ cd h4b-hands-on/
admin:~/environment/h4b-hands-on (master) $ 
```
:::note warn
WebUIで/home/ec2-user/environment/h4b-hands-onにindex.htmlをアップロード後に以下を実施
:::
```bash:コマンド
git add -A
git commit -m "init."
git push origin master

```
```bash:出力
admin:~/environment/h4b-hands-on (master) $ git add -A
admin:~/environment/h4b-hands-on (master) $ git commit -m "init."
[master (root-commit) 1c189c5] init.
 1 file changed, 11 insertions(+)
 create mode 100644 index.html
admin:~/environment/h4b-hands-on (master) $ git push origin master
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 335 bytes | 335.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote: Validating objects: 100%
To https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/h4b-hands-on
 * [new branch]      master -> master
```
:::note info
以降、CloudShellで実施
:::
## リポジトリの確認
```bash:コマンド
aws codecommit get-folder \
    --repository-name ${REPOSITORY_NAME} \
    --folder-path /

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ aws codecommit get-folder \
>     --repository-name ${REPOSITORY_NAME} \
>     --folder-path /
{
    "commitId": "1c189c5b91ee7b0685e7cc3855f7685fb651f114",
    "folderPath": "",
    "treeId": "7a6801edd926242e01e4ab62c9aecbb63946bb05",
    "subFolders": [],
    "files": [
        {
            "blobId": "c5f146332875b0c706ce665a2fd8f2be55859a25",
            "absolutePath": "index.html",
            "relativePath": "index.html",
            "fileMode": "NORMAL"
        }
    ],
    "symbolicLinks": [],
    "subModules": []
}
```
# 03 S3 をデプロイ先とした、CI/CD 環境を構築する【CodePipeline 編】
## 変数
```bash:コマンド
# パイプライン名
PIPELINE_NAME="h4b-hands-on-s3" \
&& echo ${PIPELINE_NAME}

# ポリシー名
PIPELINE_IAM_POLICY_NAME="AWSCodePipelineServiceRole-ap-northeast-1" \
&& echo ${PIPELINE_IAM_POLICY_NAME}

# ロール名
PIPELINE_IAM_ROLE_NAME="AWSCodePipelineServiceRole-ap-northeast-1" \
&& echo ${PIPELINE_IAM_ROLE_NAME}

# IAMパス
IAM_PATH="/service-role/" \
&& echo ${IAM_PATH}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # パイプライン名
[cloudshell-user@ip-10-132-76-170 ~]$ PIPELINE_NAME="h4b-hands-on-s3" \
> && echo ${PIPELINE_NAME}
h4b-hands-on-s3
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ポリシー名
[cloudshell-user@ip-10-132-76-170 ~]$ PIPELINE_IAM_POLICY_NAME="AWSCodePipelineServiceRole-ap-northeast-1" \
> && echo ${PIPELINE_IAM_POLICY_NAME}
AWSCodePipelineServiceRole-ap-northeast-1
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ロール名
[cloudshell-user@ip-10-132-76-170 ~]$ PIPELINE_IAM_ROLE_NAME="AWSCodePipelineServiceRole-ap-northeast-1" \
> && echo ${PIPELINE_IAM_ROLE_NAME}
AWSCodePipelineServiceRole-ap-northeast-1
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMパス
[cloudshell-user@ip-10-132-76-170 ~]$ IAM_PATH="/service-role/" \
> && echo ${IAM_PATH}
/service-role/
```
## IAM
### IAMポリシー
```bash:コマンド
# IAMポリシー
POLICY_DOCUMENT_JSON=$(cat << EOF
{
    "Statement": [
        {
            "Action": [
                "iam:PassRole"
            ],
            "Resource": "*",
            "Effect": "Allow",
            "Condition": {
                "StringEqualsIfExists": {
                    "iam:PassedToService": [
                        "cloudformation.amazonaws.com",
                        "elasticbeanstalk.amazonaws.com",
                        "ec2.amazonaws.com",
                        "ecs-tasks.amazonaws.com"
                    ]
                }
            }
        },
        {
            "Action": [
                "codecommit:CancelUploadArchive",
                "codecommit:GetBranch",
                "codecommit:GetCommit",
                "codecommit:GetRepository",
                "codecommit:GetUploadArchiveStatus",
                "codecommit:UploadArchive"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "codedeploy:CreateDeployment",
                "codedeploy:GetApplication",
                "codedeploy:GetApplicationRevision",
                "codedeploy:GetDeployment",
                "codedeploy:GetDeploymentConfig",
                "codedeploy:RegisterApplicationRevision"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "codestar-connections:UseConnection"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "elasticbeanstalk:*",
                "ec2:*",
                "elasticloadbalancing:*",
                "autoscaling:*",
                "cloudwatch:*",
                "s3:*",
                "sns:*",
                "cloudformation:*",
                "rds:*",
                "sqs:*",
                "ecs:*"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "lambda:InvokeFunction",
                "lambda:ListFunctions"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "opsworks:CreateDeployment",
                "opsworks:DescribeApps",
                "opsworks:DescribeCommands",
                "opsworks:DescribeDeployments",
                "opsworks:DescribeInstances",
                "opsworks:DescribeStacks",
                "opsworks:UpdateApp",
                "opsworks:UpdateStack"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "cloudformation:CreateStack",
                "cloudformation:DeleteStack",
                "cloudformation:DescribeStacks",
                "cloudformation:UpdateStack",
                "cloudformation:CreateChangeSet",
                "cloudformation:DeleteChangeSet",
                "cloudformation:DescribeChangeSet",
                "cloudformation:ExecuteChangeSet",
                "cloudformation:SetStackPolicy",
                "cloudformation:ValidateTemplate"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "codebuild:BatchGetBuilds",
                "codebuild:StartBuild",
                "codebuild:BatchGetBuildBatches",
                "codebuild:StartBuildBatch"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Effect": "Allow",
            "Action": [
                "devicefarm:ListProjects",
                "devicefarm:ListDevicePools",
                "devicefarm:GetRun",
                "devicefarm:GetUpload",
                "devicefarm:CreateUpload",
                "devicefarm:ScheduleRun"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "servicecatalog:ListProvisioningArtifacts",
                "servicecatalog:CreateProvisioningArtifact",
                "servicecatalog:DescribeProvisioningArtifact",
                "servicecatalog:DeleteProvisioningArtifact",
                "servicecatalog:UpdateProduct"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "cloudformation:ValidateTemplate"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ecr:DescribeImages"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "states:DescribeExecution",
                "states:DescribeStateMachine",
                "states:StartExecution"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "appconfig:StartDeployment",
                "appconfig:StopDeployment",
                "appconfig:GetDeployment"
            ],
            "Resource": "*"
        }
    ],
    "Version": "2012-10-17"
}
EOF
) \
&& echo ${POLICY_DOCUMENT_JSON}

# JSONフォーマットの確認
echo ${POLICY_DOCUMENT_JSON} | python -m json.tool

# ポリシーの作成
aws iam create-policy \
    --policy-name ${PIPELINE_IAM_POLICY_NAME} \
    --path ${IAM_PATH} \
    --policy-document "${POLICY_DOCUMENT_JSON}"

# ARN取得
PIPELINE_IAM_POLICY_ARN=$(
    aws iam list-policies \
        --query "Policies[?PolicyName=='${PIPELINE_IAM_POLICY_NAME}'].Arn" \
        --output text
) \
&& echo ${PIPELINE_IAM_POLICY_ARN}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMポリシー
[cloudshell-user@ip-10-132-76-170 ~]$ POLICY_DOCUMENT_JSON=$(cat << EOF
> {
>     "Statement": [
>         {
>             "Action": [
>                 "iam:PassRole"
>             ],
>             "Resource": "*",
>             "Effect": "Allow",
>             "Condition": {
>                 "StringEqualsIfExists": {
>                     "iam:PassedToService": [
>                         "cloudformation.amazonaws.com",
>                         "elasticbeanstalk.amazonaws.com",
>                         "ec2.amazonaws.com",
>                         "ecs-tasks.amazonaws.com"
>                     ]
>                 }
>             }
>         },
>         {
>             "Action": [
>                 "codecommit:CancelUploadArchive",
>                 "codecommit:GetBranch",
>                 "codecommit:GetCommit",
>                 "codecommit:GetRepository",
>                 "codecommit:GetUploadArchiveStatus",
>                 "codecommit:UploadArchive"
>             ],
>             "Resource": "*",
>             "Effect": "Allow"
>         },
>         {
>             "Action": [
>                 "codedeploy:CreateDeployment",
>                 "codedeploy:GetApplication",
>                 "codedeploy:GetApplicationRevision",
>                 "codedeploy:GetDeployment",
>                 "codedeploy:GetDeploymentConfig",
>                 "codedeploy:RegisterApplicationRevision"
>             ],
>             "Resource": "*",
>             "Effect": "Allow"
>         },
>         {
>             "Action": [
>                 "codestar-connections:UseConnection"
>             ],
>             "Resource": "*",
>             "Effect": "Allow"
>         },
>         {
>             "Action": [
>                 "elasticbeanstalk:*",
>                 "ec2:*",
>                 "elasticloadbalancing:*",
>                 "autoscaling:*",
>                 "cloudwatch:*",
>                 "s3:*",
>                 "sns:*",
>                 "cloudformation:*",
>                 "rds:*",
>                 "sqs:*",
>                 "ecs:*"
>             ],
>             "Resource": "*",
>             "Effect": "Allow"
>         },
>         {
>             "Action": [
>                 "lambda:InvokeFunction",
>                 "lambda:ListFunctions"
>             ],
>             "Resource": "*",
>             "Effect": "Allow"
>         },
>         {
>             "Action": [
>                 "opsworks:CreateDeployment",
>                 "opsworks:DescribeApps",
>                 "opsworks:DescribeCommands",
>                 "opsworks:DescribeDeployments",
>                 "opsworks:DescribeInstances",
>                 "opsworks:DescribeStacks",
>                 "opsworks:UpdateApp",
>                 "opsworks:UpdateStack"
>             ],
>             "Resource": "*",
>             "Effect": "Allow"
>         },
>         {
>             "Action": [
>                 "cloudformation:CreateStack",
>                 "cloudformation:DeleteStack",
>                 "cloudformation:DescribeStacks",
>                 "cloudformation:UpdateStack",
>                 "cloudformation:CreateChangeSet",
>                 "cloudformation:DeleteChangeSet",
>                 "cloudformation:DescribeChangeSet",
>                 "cloudformation:ExecuteChangeSet",
>                 "cloudformation:SetStackPolicy",
>                 "cloudformation:ValidateTemplate"
>             ],
>             "Resource": "*",
>             "Effect": "Allow"
>         },
>         {
>             "Action": [
>                 "codebuild:BatchGetBuilds",
>                 "codebuild:StartBuild",
>                 "codebuild:BatchGetBuildBatches",
>                 "codebuild:StartBuildBatch"
>             ],
>             "Resource": "*",
>             "Effect": "Allow"
>         },
>         {
>             "Effect": "Allow",
>             "Action": [
>                 "devicefarm:ListProjects",
>                 "devicefarm:ListDevicePools",
>                 "devicefarm:GetRun",
>                 "devicefarm:GetUpload",
>                 "devicefarm:CreateUpload",
>                 "devicefarm:ScheduleRun"
>             ],
>             "Resource": "*"
>         },
>         {
>             "Effect": "Allow",
>             "Action": [
>                 "servicecatalog:ListProvisioningArtifacts",
>                 "servicecatalog:CreateProvisioningArtifact",
>                 "servicecatalog:DescribeProvisioningArtifact",
>                 "servicecatalog:DeleteProvisioningArtifact",
>                 "servicecatalog:UpdateProduct"
>             ],
>             "Resource": "*"
>         },
>         {
>             "Effect": "Allow",
>             "Action": [
>                 "cloudformation:ValidateTemplate"
>             ],
>             "Resource": "*"
>         },
>         {
>             "Effect": "Allow",
>             "Action": [
>                 "ecr:DescribeImages"
>             ],
>             "Resource": "*"
>         },
>         {
>             "Effect": "Allow",
>             "Action": [
>                 "states:DescribeExecution",
>                 "states:DescribeStateMachine",
>                 "states:StartExecution"
>             ],
>             "Resource": "*"
>         },
>         {
>             "Effect": "Allow",
>             "Action": [
>                 "appconfig:StartDeployment",
>                 "appconfig:StopDeployment",
>                 "appconfig:GetDeployment"
>             ],
>             "Resource": "*"
>         }
>     ],
>     "Version": "2012-10-17"
> }
> EOF
> ) \
> && echo ${POLICY_DOCUMENT_JSON}
{ "Statement": [ { "Action": [ "iam:PassRole" ], "Resource": "*", "Effect": "Allow", "Condition": { "StringEqualsIfExists": { "iam:PassedToService": [ "cloudformation.amazonaws.com", "elasticbeanstalk.amazonaws.com", "ec2.amazonaws.com", "ecs-tasks.amazonaws.com" ] } } }, { "Action": [ "codecommit:CancelUploadArchive", "codecommit:GetBranch", "codecommit:GetCommit", "codecommit:GetRepository", "codecommit:GetUploadArchiveStatus", "codecommit:UploadArchive" ], "Resource": "*", "Effect": "Allow" }, { "Action": [ "codedeploy:CreateDeployment", "codedeploy:GetApplication", "codedeploy:GetApplicationRevision", "codedeploy:GetDeployment", "codedeploy:GetDeploymentConfig", "codedeploy:RegisterApplicationRevision" ], "Resource": "*", "Effect": "Allow" }, { "Action": [ "codestar-connections:UseConnection" ], "Resource": "*", "Effect": "Allow" }, { "Action": [ "elasticbeanstalk:*", "ec2:*", "elasticloadbalancing:*", "autoscaling:*", "cloudwatch:*", "s3:*", "sns:*", "cloudformation:*", "rds:*", "sqs:*", "ecs:*" ], "Resource": "*", "Effect": "Allow" }, { "Action": [ "lambda:InvokeFunction", "lambda:ListFunctions" ], "Resource": "*", "Effect": "Allow" }, { "Action": [ "opsworks:CreateDeployment", "opsworks:DescribeApps", "opsworks:DescribeCommands", "opsworks:DescribeDeployments", "opsworks:DescribeInstances", "opsworks:DescribeStacks", "opsworks:UpdateApp", "opsworks:UpdateStack" ], "Resource": "*", "Effect": "Allow" }, { "Action": [ "cloudformation:CreateStack", "cloudformation:DeleteStack", "cloudformation:DescribeStacks", "cloudformation:UpdateStack", "cloudformation:CreateChangeSet", "cloudformation:DeleteChangeSet", "cloudformation:DescribeChangeSet", "cloudformation:ExecuteChangeSet", "cloudformation:SetStackPolicy", "cloudformation:ValidateTemplate" ], "Resource": "*", "Effect": "Allow" }, { "Action": [ "codebuild:BatchGetBuilds", "codebuild:StartBuild", "codebuild:BatchGetBuildBatches", "codebuild:StartBuildBatch" ], "Resource": "*", "Effect": "Allow" }, { "Effect": "Allow", "Action": [ "devicefarm:ListProjects", "devicefarm:ListDevicePools", "devicefarm:GetRun", "devicefarm:GetUpload", "devicefarm:CreateUpload", "devicefarm:ScheduleRun" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "servicecatalog:ListProvisioningArtifacts", "servicecatalog:CreateProvisioningArtifact", "servicecatalog:DescribeProvisioningArtifact", "servicecatalog:DeleteProvisioningArtifact", "servicecatalog:UpdateProduct" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "cloudformation:ValidateTemplate" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "ecr:DescribeImages" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "states:DescribeExecution", "states:DescribeStateMachine", "states:StartExecution" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "appconfig:StartDeployment", "appconfig:StopDeployment", "appconfig:GetDeployment" ], "Resource": "*" } ], "Version": "2012-10-17" }
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-76-170 ~]$ echo ${POLICY_DOCUMENT_JSON} | python -m json.tool
{
    "Statement": [
        {
            "Action": [
                "iam:PassRole"
            ],
            "Resource": "*",
            "Effect": "Allow",
            "Condition": {
                "StringEqualsIfExists": {
                    "iam:PassedToService": [
                        "cloudformation.amazonaws.com",
                        "elasticbeanstalk.amazonaws.com",
                        "ec2.amazonaws.com",
                        "ecs-tasks.amazonaws.com"
                    ]
                }
            }
        },
        {
            "Action": [
                "codecommit:CancelUploadArchive",
                "codecommit:GetBranch",
                "codecommit:GetCommit",
                "codecommit:GetRepository",
                "codecommit:GetUploadArchiveStatus",
                "codecommit:UploadArchive"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "codedeploy:CreateDeployment",
                "codedeploy:GetApplication",
                "codedeploy:GetApplicationRevision",
                "codedeploy:GetDeployment",
                "codedeploy:GetDeploymentConfig",
                "codedeploy:RegisterApplicationRevision"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "codestar-connections:UseConnection"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "elasticbeanstalk:*",
                "ec2:*",
                "elasticloadbalancing:*",
                "autoscaling:*",
                "cloudwatch:*",
                "s3:*",
                "sns:*",
                "cloudformation:*",
                "rds:*",
                "sqs:*",
                "ecs:*"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "lambda:InvokeFunction",
                "lambda:ListFunctions"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "opsworks:CreateDeployment",
                "opsworks:DescribeApps",
                "opsworks:DescribeCommands",
                "opsworks:DescribeDeployments",
                "opsworks:DescribeInstances",
                "opsworks:DescribeStacks",
                "opsworks:UpdateApp",
                "opsworks:UpdateStack"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "cloudformation:CreateStack",
                "cloudformation:DeleteStack",
                "cloudformation:DescribeStacks",
                "cloudformation:UpdateStack",
                "cloudformation:CreateChangeSet",
                "cloudformation:DeleteChangeSet",
                "cloudformation:DescribeChangeSet",
                "cloudformation:ExecuteChangeSet",
                "cloudformation:SetStackPolicy",
                "cloudformation:ValidateTemplate"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "codebuild:BatchGetBuilds",
                "codebuild:StartBuild",
                "codebuild:BatchGetBuildBatches",
                "codebuild:StartBuildBatch"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Effect": "Allow",
            "Action": [
                "devicefarm:ListProjects",
                "devicefarm:ListDevicePools",
                "devicefarm:GetRun",
                "devicefarm:GetUpload",
                "devicefarm:CreateUpload",
                "devicefarm:ScheduleRun"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "servicecatalog:ListProvisioningArtifacts",
                "servicecatalog:CreateProvisioningArtifact",
                "servicecatalog:DescribeProvisioningArtifact",
                "servicecatalog:DeleteProvisioningArtifact",
                "servicecatalog:UpdateProduct"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "cloudformation:ValidateTemplate"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ecr:DescribeImages"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "states:DescribeExecution",
                "states:DescribeStateMachine",
                "states:StartExecution"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "appconfig:StartDeployment",
                "appconfig:StopDeployment",
                "appconfig:GetDeployment"
            ],
            "Resource": "*"
        }
    ],
    "Version": "2012-10-17"
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ポリシーの作成
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam create-policy \
>     --policy-name ${PIPELINE_IAM_POLICY_NAME} \
>     --path ${IAM_PATH} \
>     --policy-document "${POLICY_DOCUMENT_JSON}"
{
    "Policy": {
        "PolicyName": "AWSCodePipelineServiceRole-ap-northeast-1",
        "PolicyId": "ANPAWFKRCMKOYJIXRZWZM",
        "Arn": "arn:aws:iam::999999999999:policy/service-role/AWSCodePipelineServiceRole-ap-northeast-1",
        "Path": "/service-role/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 0,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "CreateDate": "2024-09-14T06:18:27+00:00",
        "UpdateDate": "2024-09-14T06:18:27+00:00"
    }
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ARN取得
[cloudshell-user@ip-10-132-76-170 ~]$ PIPELINE_IAM_POLICY_ARN=$(
>     aws iam list-policies \
>         --query "Policies[?PolicyName=='${PIPELINE_IAM_POLICY_NAME}'].Arn" \
>         --output text
> ) \
> && echo ${PIPELINE_IAM_POLICY_ARN}
```
### IAMロール
```bash:コマンド
# 信頼関係ポリシードキュメントの作成
ASSUME_ROLE_POLICY_DOCUMENT=$(cat << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "codepipeline.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
EOF
) \
&& echo ${ASSUME_ROLE_POLICY_DOCUMENT}

# JSONフォーマットの確認
echo ${ASSUME_ROLE_POLICY_DOCUMENT} | python -m json.tool

# IAMロールの作成
aws iam create-role \
    --path ${IAM_PATH} \
    --role-name ${PIPELINE_IAM_ROLE_NAME} \
    --assume-role-policy-document "${ASSUME_ROLE_POLICY_DOCUMENT}"

# ARN取得
PIPELINE_IAM_ROLE_ARN=$(
    aws iam get-role \
        --role-name ${PIPELINE_IAM_ROLE_NAME} \
        --query 'Role.Arn' \
        --output text
) \
&& echo ${PIPELINE_IAM_ROLE_ARN}

# IAMロールにポリシーをアタッチ
aws iam attach-role-policy \
    --role-name ${PIPELINE_IAM_ROLE_NAME} \
    --policy-arn ${PIPELINE_IAM_POLICY_ARN}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # 信頼関係ポリシードキュメントの作成
[cloudshell-user@ip-10-132-76-170 ~]$ ASSUME_ROLE_POLICY_DOCUMENT=$(cat << EOF
> {
>     "Version": "2012-10-17",
>     "Statement": [
>         {
>             "Effect": "Allow",
>             "Principal": {
>                 "Service": "codepipeline.amazonaws.com"
>             },
>             "Action": "sts:AssumeRole"
>         }
>     ]
> }
> EOF
> ) \
> && echo ${ASSUME_ROLE_POLICY_DOCUMENT}
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "codepipeline.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-76-170 ~]$ echo ${ASSUME_ROLE_POLICY_DOCUMENT} | python -m json.tool
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "codepipeline.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMロールの作成
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam create-role \
>     --path ${IAM_PATH} \
>     --role-name ${PIPELINE_IAM_ROLE_NAME} \
>     --assume-role-policy-document "${ASSUME_ROLE_POLICY_DOCUMENT}"
{
    "Role": {
        "Path": "/service-role/",
        "RoleName": "AWSCodePipelineServiceRole-ap-northeast-1",
        "RoleId": "AROAWFKRCMKOS5HCI6B76",
        "Arn": "arn:aws:iam::999999999999:role/service-role/AWSCodePipelineServiceRole-ap-northeast-1",
        "CreateDate": "2024-09-14T06:19:04+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "codepipeline.amazonaws.com"
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        }
    }
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ARN取得
[cloudshell-user@ip-10-132-76-170 ~]$ PIPELINE_IAM_ROLE_ARN=$(
>     aws iam get-role \
>         --role-name ${PIPELINE_IAM_ROLE_NAME} \
>         --query 'Role.Arn' \
>         --output text
> ) \
> && echo ${PIPELINE_IAM_ROLE_ARN}
arn:aws:iam::999999999999:role/service-role/AWSCodePipelineServiceRole-ap-northeast-1
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMロールにポリシーをアタッチ
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam attach-role-policy \
>     --role-name ${PIPELINE_IAM_ROLE_NAME} \
>     --policy-arn ${PIPELINE_IAM_POLICY_ARN}
```
## アーティファクト用 S3バケット
```bash:コマンド
# アーティファクト用のS3バケット名
ARTIFACTSTORE_BUCKET_NAME="codepipeline-${REGION}-artifactstore-`date +%Y%m%d`" \
&& echo ${ARTIFACTSTORE_BUCKET_NAME}

# アーティファクト用のS3バケット作成
aws s3api create-bucket \
    --bucket ${ARTIFACTSTORE_BUCKET_NAME} \
    --create-bucket-configuration LocationConstraint=${REGION}
    
# アーティファクト用のS3バケットポリシー(JSON)
ARTIFACTSTORE_BACKET_POLICY=$(cat << EOF
{
    "Version": "2012-10-17",
    "Id": "SSEAndSSLPolicy",
    "Statement": [
        {
            "Sid": "DenyUnEncryptedObjectUploads",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::${ARTIFACTSTORE_BUCKET_NAME}/*",
            "Condition": {
                "StringNotEquals": {
                    "s3:x-amz-server-side-encryption": "aws:kms"
                }
            }
        },
        {
            "Sid": "DenyInsecureConnections",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::${ARTIFACTSTORE_BUCKET_NAME}/*",
            "Condition": {
                "Bool": {
                    "aws:SecureTransport": "false"
                }
            }
        }
    ]
}
EOF
) \
&& echo ${ARTIFACTSTORE_BACKET_POLICY}

# JSONフォーマットの確認
echo ${ARTIFACTSTORE_BACKET_POLICY} | python -m json.tool

# バケットポリシー
aws s3api put-bucket-policy \
    --bucket ${ARTIFACTSTORE_BUCKET_NAME} \
    --policy "${ARTIFACTSTORE_BACKET_POLICY}"

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # アーティファクト用のS3バケット名
[cloudshell-user@ip-10-132-76-170 ~]$ ARTIFACTSTORE_BUCKET_NAME="codepipeline-${REGION}-artifactstore-`date +%Y%m%d`" \
> && echo ${ARTIFACTSTORE_BUCKET_NAME}
codepipeline-ap-northeast-1-artifactstore-20240914
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # アーティファクト用のS3バケット作成
[cloudshell-user@ip-10-132-76-170 ~]$ aws s3api create-bucket \
>     --bucket ${ARTIFACTSTORE_BUCKET_NAME} \
>     --create-bucket-configuration LocationConstraint=${REGION}
{
    "Location": "http://codepipeline-ap-northeast-1-artifactstore-20240914.s3.amazonaws.com/"
}
[cloudshell-user@ip-10-132-76-170 ~]$     
[cloudshell-user@ip-10-132-76-170 ~]$ # アーティファクト用のS3バケットポリシー(JSON)
[cloudshell-user@ip-10-132-76-170 ~]$ ARTIFACTSTORE_BACKET_POLICY=$(cat << EOF
> {
>     "Version": "2012-10-17",
>     "Id": "SSEAndSSLPolicy",
>     "Statement": [
>         {
>             "Sid": "DenyUnEncryptedObjectUploads",
>             "Effect": "Deny",
>             "Principal": "*",
>             "Action": "s3:PutObject",
>             "Resource": "arn:aws:s3:::${ARTIFACTSTORE_BUCKET_NAME}/*",
>             "Condition": {
>                 "StringNotEquals": {
>                     "s3:x-amz-server-side-encryption": "aws:kms"
>                 }
>             }
>         },
>         {
>             "Sid": "DenyInsecureConnections",
>             "Effect": "Deny",
>             "Principal": "*",
>             "Action": "s3:*",
>             "Resource": "arn:aws:s3:::${ARTIFACTSTORE_BUCKET_NAME}/*",
>             "Condition": {
>                 "Bool": {
>                     "aws:SecureTransport": "false"
>                 }
>             }
>         }
>     ]
> }
> EOF
> ) \
> && echo ${ARTIFACTSTORE_BACKET_POLICY}
{ "Version": "2012-10-17", "Id": "SSEAndSSLPolicy", "Statement": [ { "Sid": "DenyUnEncryptedObjectUploads", "Effect": "Deny", "Principal": "*", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::codepipeline-ap-northeast-1-artifactstore-20240914/*", "Condition": { "StringNotEquals": { "s3:x-amz-server-side-encryption": "aws:kms" } } }, { "Sid": "DenyInsecureConnections", "Effect": "Deny", "Principal": "*", "Action": "s3:*", "Resource": "arn:aws:s3:::codepipeline-ap-northeast-1-artifactstore-20240914/*", "Condition": { "Bool": { "aws:SecureTransport": "false" } } } ] }
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-76-170 ~]$ echo ${ARTIFACTSTORE_BACKET_POLICY} | python -m json.tool
{
    "Version": "2012-10-17",
    "Id": "SSEAndSSLPolicy",
    "Statement": [
        {
            "Sid": "DenyUnEncryptedObjectUploads",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::codepipeline-ap-northeast-1-artifactstore-20240914/*",
            "Condition": {
                "StringNotEquals": {
                    "s3:x-amz-server-side-encryption": "aws:kms"
                }
            }
        },
        {
            "Sid": "DenyInsecureConnections",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::codepipeline-ap-northeast-1-artifactstore-20240914/*",
            "Condition": {
                "Bool": {
                    "aws:SecureTransport": "false"
                }
            }
        }
    ]
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # バケットポリシー
[cloudshell-user@ip-10-132-76-170 ~]$ aws s3api put-bucket-policy \
>     --bucket ${ARTIFACTSTORE_BUCKET_NAME} \
>     --policy "${ARTIFACTSTORE_BACKET_POLICY}"
```
## パイプライン定義ファイル
```bash:コマンド
# パイプライン定義ファイル
PIPELINE_JSON=$(cat << EOF
{
    "pipeline": {
        "name": "${PIPELINE_NAME}",
        "roleArn": "${PIPELINE_IAM_ROLE_ARN}",
        "artifactStore": {
            "type": "S3",
            "location": "${ARTIFACTSTORE_BUCKET_NAME}"
        },
        "stages": [
            {
                "name": "Source",
                "actions": [
                    {
                        "name": "Source",
                        "actionTypeId": {
                            "category": "Source",
                            "owner": "AWS",
                            "provider": "CodeCommit",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "BranchName": "master",
                            "OutputArtifactFormat": "CODE_ZIP",
                            "PollForSourceChanges": "false",
                            "RepositoryName": "${REPOSITORY_NAME}"
                        },
                        "outputArtifacts": [
                            {
                                "name": "SourceArtifact"
                            }
                        ],
                        "inputArtifacts": [],
                        "region": "ap-northeast-1",
                        "namespace": "SourceVariables"
                    }
                ]
            },
            {
                "name": "Deploy",
                "actions": [
                    {
                        "name": "Deploy",
                        "actionTypeId": {
                            "category": "Deploy",
                            "owner": "AWS",
                            "provider": "S3",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "BucketName": "${S3_BUCKET_NAME}",
                            "Extract": "true"
                        },
                        "inputArtifacts": [
                            {
                                "name": "SourceArtifact"
                            }
                        ],
                        "region": "ap-northeast-1",
                        "namespace": "DeployVariables"
                    }
                ]
            }
        ],
        "version": 1,
        "executionMode": "QUEUED",
        "pipelineType": "V2"
    }
}
EOF
) \
&& echo ${PIPELINE_JSON}

# JSONフォーマットの確認
echo ${PIPELINE_JSON} | python -m json.tool

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # パイプライン定義ファイル
[cloudshell-user@ip-10-132-76-170 ~]$ PIPELINE_JSON=$(cat << EOF
> {
>     "pipeline": {
>         "name": "${PIPELINE_NAME}",
>         "roleArn": "${PIPELINE_IAM_ROLE_ARN}",
>         "artifactStore": {
>             "type": "S3",
>             "location": "${ARTIFACTSTORE_BUCKET_NAME}"
>         },
>         "stages": [
>             {
>                 "name": "Source",
>                 "actions": [
>                     {
>                         "name": "Source",
>                         "actionTypeId": {
>                             "category": "Source",
>                             "owner": "AWS",
>                             "provider": "CodeCommit",
>                             "version": "1"
>                         },
>                         "runOrder": 1,
>                         "configuration": {
>                             "BranchName": "master",
>                             "OutputArtifactFormat": "CODE_ZIP",
>                             "PollForSourceChanges": "false",
>                             "RepositoryName": "${REPOSITORY_NAME}"
>                         },
>                         "outputArtifacts": [
>                             {
>                                 "name": "SourceArtifact"
>                             }
>                         ],
>                         "inputArtifacts": [],
>                         "region": "ap-northeast-1",
>                         "namespace": "SourceVariables"
>                     }
>                 ]
>             },
>             {
>                 "name": "Deploy",
>                 "actions": [
>                     {
>                         "name": "Deploy",
>                         "actionTypeId": {
>                             "category": "Deploy",
>                             "owner": "AWS",
>                             "provider": "S3",
>                             "version": "1"
>                         },
>                         "runOrder": 1,
>                         "configuration": {
>                             "BucketName": "${S3_BUCKET_NAME}",
>                             "Extract": "true"
>                         },
>                         "inputArtifacts": [
>                             {
>                                 "name": "SourceArtifact"
>                             }
>                         ],
>                         "region": "ap-northeast-1",
>                         "namespace": "DeployVariables"
>                     }
>                 ]
>             }
>         ],
>         "version": 1,
>         "executionMode": "QUEUED",
>         "pipelineType": "V2"
>     }
> }
> EOF
> ) \
> && echo ${PIPELINE_JSON}
{ "pipeline": { "name": "h4b-hands-on-s3", "roleArn": "arn:aws:iam::999999999999:role/service-role/AWSCodePipelineServiceRole-ap-northeast-1", "artifactStore": { "type": "S3", "location": "codepipeline-ap-northeast-1-artifactstore-20240914" }, "stages": [ { "name": "Source", "actions": [ { "name": "Source", "actionTypeId": { "category": "Source", "owner": "AWS", "provider": "CodeCommit", "version": "1" }, "runOrder": 1, "configuration": { "BranchName": "master", "OutputArtifactFormat": "CODE_ZIP", "PollForSourceChanges": "false", "RepositoryName": "h4b-hands-on" }, "outputArtifacts": [ { "name": "SourceArtifact" } ], "inputArtifacts": [], "region": "ap-northeast-1", "namespace": "SourceVariables" } ] }, { "name": "Deploy", "actions": [ { "name": "Deploy", "actionTypeId": { "category": "Deploy", "owner": "AWS", "provider": "S3", "version": "1" }, "runOrder": 1, "configuration": { "BucketName": "h4b-handson-20240914-bucket", "Extract": "true" }, "inputArtifacts": [ { "name": "SourceArtifact" } ], "region": "ap-northeast-1", "namespace": "DeployVariables" } ] } ], "version": 1, "executionMode": "QUEUED", "pipelineType": "V2" } }
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-76-170 ~]$ echo ${PIPELINE_JSON} | python -m json.tool
{
    "pipeline": {
        "name": "h4b-hands-on-s3",
        "roleArn": "arn:aws:iam::999999999999:role/service-role/AWSCodePipelineServiceRole-ap-northeast-1",
        "artifactStore": {
            "type": "S3",
            "location": "codepipeline-ap-northeast-1-artifactstore-20240914"
        },
        "stages": [
            {
                "name": "Source",
                "actions": [
                    {
                        "name": "Source",
                        "actionTypeId": {
                            "category": "Source",
                            "owner": "AWS",
                            "provider": "CodeCommit",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "BranchName": "master",
                            "OutputArtifactFormat": "CODE_ZIP",
                            "PollForSourceChanges": "false",
                            "RepositoryName": "h4b-hands-on"
                        },
                        "outputArtifacts": [
                            {
                                "name": "SourceArtifact"
                            }
                        ],
                        "inputArtifacts": [],
                        "region": "ap-northeast-1",
                        "namespace": "SourceVariables"
                    }
                ]
            },
            {
                "name": "Deploy",
                "actions": [
                    {
                        "name": "Deploy",
                        "actionTypeId": {
                            "category": "Deploy",
                            "owner": "AWS",
                            "provider": "S3",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "BucketName": "h4b-handson-20240914-bucket",
                            "Extract": "true"
                        },
                        "inputArtifacts": [
                            {
                                "name": "SourceArtifact"
                            }
                        ],
                        "region": "ap-northeast-1",
                        "namespace": "DeployVariables"
                    }
                ]
            }
        ],
        "version": 1,
        "executionMode": "QUEUED",
        "pipelineType": "V2"
    }
}
```
## パイプラインの作成
```bash:コマンド
aws codepipeline create-pipeline \
    --cli-input-json "${PIPELINE_JSON}" \
    --no-cli-pager

# ARN取得
PIPELINE_ARN=$(
    aws codepipeline get-pipeline \
        --name ${PIPELINE_NAME} \
        --query metadata.pipelineArn \
        --output text
) \
&& echo ${PIPELINE_ARN}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ aws codepipeline create-pipeline \
>     --cli-input-json "${PIPELINE_JSON}" \
>     --no-cli-pager
{
    "pipeline": {
        "name": "h4b-hands-on-s3",
        "roleArn": "arn:aws:iam::999999999999:role/service-role/AWSCodePipelineServiceRole-ap-northeast-1",
        "artifactStore": {
            "type": "S3",
            "location": "codepipeline-ap-northeast-1-artifactstore-20240914"
        },
        "stages": [
            {
                "name": "Source",
                "actions": [
                    {
                        "name": "Source",
                        "actionTypeId": {
                            "category": "Source",
                            "owner": "AWS",
                            "provider": "CodeCommit",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "BranchName": "master",
                            "OutputArtifactFormat": "CODE_ZIP",
                            "PollForSourceChanges": "false",
                            "RepositoryName": "h4b-hands-on"
                        },
                        "outputArtifacts": [
                            {
                                "name": "SourceArtifact"
                            }
                        ],
                        "inputArtifacts": [],
                        "region": "ap-northeast-1",
                        "namespace": "SourceVariables"
                    }
                ]
            },
            {
                "name": "Deploy",
                "actions": [
                    {
                        "name": "Deploy",
                        "actionTypeId": {
                            "category": "Deploy",
                            "owner": "AWS",
                            "provider": "S3",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "BucketName": "h4b-handson-20240914-bucket",
                            "Extract": "true"
                        },
                        "outputArtifacts": [],
                        "inputArtifacts": [
                            {
                                "name": "SourceArtifact"
                            }
                        ],
                        "region": "ap-northeast-1",
                        "namespace": "DeployVariables"
                    }
                ]
            }
        ],
        "version": 1,
        "executionMode": "QUEUED",
        "pipelineType": "V2"
    }
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ARN取得
[cloudshell-user@ip-10-132-76-170 ~]$ PIPELINE_ARN=$(
>     aws codepipeline get-pipeline \
>         --name ${PIPELINE_NAME} \
>         --query metadata.pipelineArn \
>         --output text
> ) \
> && echo ${PIPELINE_ARN}
arn:aws:codepipeline:ap-northeast-1:999999999999:h4b-hands-on-s3
```
### 確認
```bash:コマンド
# 詳細確認
aws codepipeline get-pipeline \
    --name ${PIPELINE_NAME} \
    --no-cli-pager

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # 詳細確認
[cloudshell-user@ip-10-132-76-170 ~]$ aws codepipeline get-pipeline \
>     --name ${PIPELINE_NAME} \
>     --no-cli-pager
{
    "pipeline": {
        "name": "h4b-hands-on-s3",
        "roleArn": "arn:aws:iam::999999999999:role/service-role/AWSCodePipelineServiceRole-ap-northeast-1",
        "artifactStore": {
            "type": "S3",
            "location": "codepipeline-ap-northeast-1-artifactstore-20240914"
        },
        "stages": [
            {
                "name": "Source",
                "actions": [
                    {
                        "name": "Source",
                        "actionTypeId": {
                            "category": "Source",
                            "owner": "AWS",
                            "provider": "CodeCommit",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "BranchName": "master",
                            "OutputArtifactFormat": "CODE_ZIP",
                            "PollForSourceChanges": "false",
                            "RepositoryName": "h4b-hands-on"
                        },
                        "outputArtifacts": [
                            {
                                "name": "SourceArtifact"
                            }
                        ],
                        "inputArtifacts": [],
                        "region": "ap-northeast-1",
                        "namespace": "SourceVariables"
                    }
                ]
            },
            {
                "name": "Deploy",
                "actions": [
                    {
                        "name": "Deploy",
                        "actionTypeId": {
                            "category": "Deploy",
                            "owner": "AWS",
                            "provider": "S3",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "BucketName": "h4b-handson-20240914-bucket",
                            "Extract": "true"
                        },
                        "outputArtifacts": [],
                        "inputArtifacts": [
                            {
                                "name": "SourceArtifact"
                            }
                        ],
                        "region": "ap-northeast-1",
                        "namespace": "DeployVariables"
                    }
                ]
            }
        ],
        "version": 1,
        "executionMode": "QUEUED",
        "pipelineType": "V2"
    },
    "metadata": {
        "pipelineArn": "arn:aws:codepipeline:ap-northeast-1:999999999999:h4b-hands-on-s3",
        "created": "2024-09-14T06:20:28.718000+00:00",
        "updated": "2024-09-14T06:20:28.718000+00:00"
    }
}
```
## EventBridge
:::note warn
AWS CLIでCodePipelineを作成する場合、EventBridgeを手動で作成する必要がある。管理コンソールでパイプラインを作成した場合は、EventBridgeは自動で作成される
:::
https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/pipelines-trigger-source-repo-changes-cli.html
### IAM
```bash:コマンド
# ポリシー名
EVENT_IAM_POLICY_NAME="start-pipeline-execution-${REGION}-${PIPELINE_NAME}" \
&& echo ${EVENT_IAM_POLICY_NAME}

# ロール名
EVENT_IAM_ROLE_NAME="cwe-role-${REGION}-${PIPELINE_NAME}" \
&& echo ${EVENT_IAM_ROLE_NAME}

# IAMパス
IAM_PATH="/service-role/" \
&& echo ${IAM_PATH}

# IAMポリシー
POLICY_DOCUMENT_JSON=$(cat << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "codepipeline:StartPipelineExecution"
            ],
            "Resource": [
                "${PIPELINE_ARN}"
            ]
        }
    ]
}
EOF
) \
&& echo ${POLICY_DOCUMENT_JSON}

# JSONフォーマットの確認
echo ${POLICY_DOCUMENT_JSON} | python -m json.tool

# ポリシーの作成
aws iam create-policy \
    --policy-name ${EVENT_IAM_POLICY_NAME} \
    --path ${IAM_PATH} \
    --policy-document "${POLICY_DOCUMENT_JSON}"

# ARN取得
EVENT_IAM_POLICY_ARN=$(
    aws iam list-policies \
        --query "Policies[?PolicyName=='${EVENT_IAM_POLICY_NAME}'].Arn" \
        --output text
) \
&& echo ${EVENT_IAM_POLICY_ARN}

# 信頼関係ポリシードキュメントの作成
ASSUME_ROLE_POLICY_DOCUMENT=$(cat << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "events.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
EOF
) \
&& echo ${ASSUME_ROLE_POLICY_DOCUMENT}

# JSONフォーマットの確認
echo ${ASSUME_ROLE_POLICY_DOCUMENT} | python -m json.tool

# IAMロールの作成
aws iam create-role \
    --path ${IAM_PATH} \
    --role-name ${EVENT_IAM_ROLE_NAME} \
    --assume-role-policy-document "${ASSUME_ROLE_POLICY_DOCUMENT}"

# ARN取得
EVENT_IAM_ROLE_ARN=$(
    aws iam get-role \
        --role-name ${EVENT_IAM_ROLE_NAME} \
        --query 'Role.Arn' --output text
) \
&& echo ${EVENT_IAM_ROLE_ARN}

# IAMロールにポリシーをアタッチ
aws iam attach-role-policy \
    --role-name ${EVENT_IAM_ROLE_NAME} \
    --policy-arn ${EVENT_IAM_POLICY_ARN}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # ポリシー名
[cloudshell-user@ip-10-132-76-170 ~]$ EVENT_IAM_POLICY_NAME="start-pipeline-execution-${REGION}-${PIPELINE_NAME}" \
> && echo ${EVENT_IAM_POLICY_NAME}
start-pipeline-execution-ap-northeast-1-h4b-hands-on-s3
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ロール名
[cloudshell-user@ip-10-132-76-170 ~]$ EVENT_IAM_ROLE_NAME="cwe-role-${REGION}-${PIPELINE_NAME}" \
> && echo ${EVENT_IAM_ROLE_NAME}
cwe-role-ap-northeast-1-h4b-hands-on-s3
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMパス
[cloudshell-user@ip-10-132-76-170 ~]$ IAM_PATH="/service-role/" \
> && echo ${IAM_PATH}
/service-role/
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMポリシー
[cloudshell-user@ip-10-132-76-170 ~]$ POLICY_DOCUMENT_JSON=$(cat << EOF
> {
>     "Version": "2012-10-17",
>     "Statement": [
>         {
>             "Effect": "Allow",
>             "Action": [
>                 "codepipeline:StartPipelineExecution"
>             ],
>             "Resource": [
>                 "${PIPELINE_ARN}"
>             ]
>         }
>     ]
> }
> EOF
> ) \
> && echo ${POLICY_DOCUMENT_JSON}
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "codepipeline:StartPipelineExecution" ], "Resource": [ "arn:aws:codepipeline:ap-northeast-1:999999999999:h4b-hands-on-s3" ] } ] }
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-76-170 ~]$ echo ${POLICY_DOCUMENT_JSON} | python -m json.tool
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "codepipeline:StartPipelineExecution"
            ],
            "Resource": [
                "arn:aws:codepipeline:ap-northeast-1:999999999999:h4b-hands-on-s3"
            ]
        }
    ]
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ポリシーの作成
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam create-policy \
>     --policy-name ${EVENT_IAM_POLICY_NAME} \
>     --path ${IAM_PATH} \
>     --policy-document "${POLICY_DOCUMENT_JSON}"
{
    "Policy": {
        "PolicyName": "start-pipeline-execution-ap-northeast-1-h4b-hands-on-s3",
        "PolicyId": "ANPAWFKRCMKOTNWL4S6RT",
        "Arn": "arn:aws:iam::999999999999:policy/service-role/start-pipeline-execution-ap-northeast-1-h4b-hands-on-s3",
        "Path": "/service-role/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 0,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "CreateDate": "2024-09-14T06:21:18+00:00",
        "UpdateDate": "2024-09-14T06:21:18+00:00"
    }
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ARN取得
[cloudshell-user@ip-10-132-76-170 ~]$ EVENT_IAM_POLICY_ARN=$(
>     aws iam list-policies \
>         --query "Policies[?PolicyName=='${EVENT_IAM_POLICY_NAME}'].Arn" \
>         --output text
> ) \
> && echo ${EVENT_IAM_POLICY_ARN}
arn:aws:iam::999999999999:policy/service-role/start-pipeline-execution-ap-northeast-1-h4b-hands-on-s3
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # 信頼関係ポリシードキュメントの作成
[cloudshell-user@ip-10-132-76-170 ~]$ ASSUME_ROLE_POLICY_DOCUMENT=$(cat << EOF
> {
>     "Version": "2012-10-17",
>     "Statement": [
>         {
>             "Effect": "Allow",
>             "Principal": {
>                 "Service": "events.amazonaws.com"
>             },
>             "Action": "sts:AssumeRole"
>         }
>     ]
> }
> EOF
> ) \
> && echo ${ASSUME_ROLE_POLICY_DOCUMENT}
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "events.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-76-170 ~]$ echo ${ASSUME_ROLE_POLICY_DOCUMENT} | python -m json.tool
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "events.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMロールの作成
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam create-role \
>     --path ${IAM_PATH} \
>     --role-name ${EVENT_IAM_ROLE_NAME} \
>     --assume-role-policy-document "${ASSUME_ROLE_POLICY_DOCUMENT}"
{
    "Role": {
        "Path": "/service-role/",
        "RoleName": "cwe-role-ap-northeast-1-h4b-hands-on-s3",
        "RoleId": "AROAWFKRCMKOSYKF4ZBCX",
        "Arn": "arn:aws:iam::999999999999:role/service-role/cwe-role-ap-northeast-1-h4b-hands-on-s3",
        "CreateDate": "2024-09-14T06:21:24+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "events.amazonaws.com"
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        }
    }
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ARN取得
[cloudshell-user@ip-10-132-76-170 ~]$ EVENT_IAM_ROLE_ARN=$(
>     aws iam get-role \
>         --role-name ${EVENT_IAM_ROLE_NAME} \
>         --query 'Role.Arn' --output text
> ) \
> && echo ${EVENT_IAM_ROLE_ARN}
arn:aws:iam::999999999999:role/service-role/cwe-role-ap-northeast-1-h4b-hands-on-s3
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMロールにポリシーをアタッチ
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam attach-role-policy \
>     --role-name ${EVENT_IAM_ROLE_NAME} \
>     --policy-arn ${EVENT_IAM_POLICY_ARN}
```
## イベントパターン
```bash:コマンド
# イベントパターンJSON
EVENT_PATTERN_JSON=$(cat << EOF
{
    "source": [
        "aws.codecommit"
    ],
    "detail-type": [
        "CodeCommit Repository State Change"
    ],
    "resources": [
        "${CODECOMMIT_ARN}"
    ],
    "detail": {
        "event": [
            "referenceCreated",
            "referenceUpdated"
        ],
        "referenceType": [
            "branch"
        ],
        "referenceName": [
            "master"
        ]
    }
}
EOF
) \
&& echo ${EVENT_PATTERN_JSON}

# JSONフォーマットの確認
echo ${EVENT_PATTERN_JSON} | python -m json.tool

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # イベントパターンJSON
[cloudshell-user@ip-10-132-76-170 ~]$ EVENT_PATTERN_JSON=$(cat << EOF
> {
>     "source": [
>         "aws.codecommit"
>     ],
>     "detail-type": [
>         "CodeCommit Repository State Change"
>     ],
>     "resources": [
>         "${CODECOMMIT_ARN}"
>     ],
>     "detail": {
>         "event": [
>             "referenceCreated",
>             "referenceUpdated"
>         ],
>         "referenceType": [
>             "branch"
>         ],
>         "referenceName": [
>             "master"
>         ]
>     }
> }
> EOF
> ) \
> && echo ${EVENT_PATTERN_JSON}
{ "source": [ "aws.codecommit" ], "detail-type": [ "CodeCommit Repository State Change" ], "resources": [ "arn:aws:codecommit:ap-northeast-1:999999999999:h4b-hands-on" ], "detail": { "event": [ "referenceCreated", "referenceUpdated" ], "referenceType": [ "branch" ], "referenceName": [ "master" ] } }
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-76-170 ~]$ echo ${EVENT_PATTERN_JSON} | python -m json.tool
{
    "source": [
        "aws.codecommit"
    ],
    "detail-type": [
        "CodeCommit Repository State Change"
    ],
    "resources": [
        "arn:aws:codecommit:ap-northeast-1:999999999999:h4b-hands-on"
    ],
    "detail": {
        "event": [
            "referenceCreated",
            "referenceUpdated"
        ],
        "referenceType": [
            "branch"
        ],
        "referenceName": [
            "master"
        ]
    }
}
```
### 作成
```bash:コマンド
# ルール名
EVENTS_RULE_NAME="codepipeline-${PIPELINE_NAME}-rule" \
&& echo ${EVENTS_RULE_NAME}

# ルール
aws events put-rule \
    --name "${EVENTS_RULE_NAME}" \
    --event-pattern "${EVENT_PATTERN_JSON}" \
    --role-arn "${EVENT_IAM_ROLE_ARN}"

# ターゲット
aws events put-targets \
    --rule ${EVENTS_RULE_NAME} \
    --targets Id="codepipeline-${PIPELINE_NAME}",Arn="${PIPELINE_ARN}",RoleArn="${EVENT_IAM_ROLE_ARN}"

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # ルール名
[cloudshell-user@ip-10-132-76-170 ~]$ EVENTS_RULE_NAME="codepipeline-${PIPELINE_NAME}-rule" \
> && echo ${EVENTS_RULE_NAME}
codepipeline-h4b-hands-on-s3-rule
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ルール
[cloudshell-user@ip-10-132-76-170 ~]$ aws events put-rule \
>     --name "${EVENTS_RULE_NAME}" \
>     --event-pattern "${EVENT_PATTERN_JSON}" \
>     --role-arn "${EVENT_IAM_ROLE_ARN}"
{
    "RuleArn": "arn:aws:events:ap-northeast-1:999999999999:rule/codepipeline-h4b-hands-on-s3-rule"
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ターゲット
[cloudshell-user@ip-10-132-76-170 ~]$ aws events put-targets \
>     --rule ${EVENTS_RULE_NAME} \
>     --targets Id="codepipeline-${PIPELINE_NAME}",Arn="${PIPELINE_ARN}",RoleArn="${EVENT_IAM_ROLE_ARN}"
{
    "FailedEntryCount": 0,
    "FailedEntries": []
}
```
### 確認
```bash:コマンド
# ルール確認
aws events describe-rule \
    --name ${EVENTS_RULE_NAME}

# ターゲット確認
aws events list-targets-by-rule \
    --rule ${EVENTS_RULE_NAME}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # ルール確認
[cloudshell-user@ip-10-132-76-170 ~]$ aws events describe-rule \
>     --name ${EVENTS_RULE_NAME}
{
    "Name": "codepipeline-h4b-hands-on-s3-rule",
    "Arn": "arn:aws:events:ap-northeast-1:999999999999:rule/codepipeline-h4b-hands-on-s3-rule",
    "EventPattern": "{\n    \"source\": [\n        \"aws.codecommit\"\n    ],\n    \"detail-type\": [\n        \"CodeCommit Repository State Change\"\n    ],\n    \"resources\": [\n        \"arn:aws:codecommit:ap-northeast-1:999999999999:h4b-hands-on\"\n    ],\n    \"detail\": {\n        \"event\": [\n            \"referenceCreated\",\n            \"referenceUpdated\"\n        ],\n        \"referenceType\": [\n            \"branch\"\n        ],\n        \"referenceName\": [\n            \"master\"\n        ]\n    }\n}",
    "State": "ENABLED",
    "RoleArn": "arn:aws:iam::999999999999:role/service-role/cwe-role-ap-northeast-1-h4b-hands-on-s3",
    "EventBusName": "default",
    "CreatedBy": "999999999999"
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ターゲット確認
[cloudshell-user@ip-10-132-76-170 ~]$ aws events list-targets-by-rule \
>     --rule ${EVENTS_RULE_NAME}
{
    "Targets": [
        {
            "Id": "codepipeline-h4b-hands-on-s3",
            "Arn": "arn:aws:codepipeline:ap-northeast-1:999999999999:h4b-hands-on-s3",
            "RoleArn": "arn:aws:iam::999999999999:role/service-role/cwe-role-ap-northeast-1-h4b-hands-on-s3"
        }
    ]
}
```
:::note info
以降、Cloud9で実施
:::
## index.htmlの更新
```bash:コマンド
cat << EOF > index.html
<!DOCTYPE html>

<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>S3 Static Web Hosting</title>
</head>
<body>
  Hello, AWS Code* World!!
</body>
</html>
EOF

```
```bash:出力
admin:~/environment/h4b-hands-on (master) $ cat << EOF > index.html
> <!DOCTYPE html>
> 
> <html lang="ja">
> <head>
>   <meta charset="utf-8">
>   <title>S3 Static Web Hosting</title>
> </head>
> <body>
>   Hello, AWS Code* World!!
> </body>
> </html>
> EOF
```
## リポジトリの更新
```bash:コマンド
git add -A
git commit -m "fix."
git push origin master

```
```bash:出力
admin:~/environment/h4b-hands-on (master) $ git add -A
admin:~/environment/h4b-hands-on (master) $ git commit -m "fix."
[master 8cb8648] fix.
 1 file changed, 1 insertion(+), 1 deletion(-)
admin:~/environment/h4b-hands-on (master) $ git push origin master
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 290 bytes | 290.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Validating objects: 100%
To https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/h4b-hands-on
   1c189c5..8cb8648  master -> master
```
:::note info
以降、CloudShellで実施
:::
## アクセス確認 
```bash:コマンド
curl http://${S3_BUCKET_NAME}.s3-website-${REGION}.amazonaws.com

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ curl http://${S3_BUCKET_NAME}.s3-website-${REGION}.amazonaws.com
<!DOCTYPE html>

<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>S3 Static Web Hosting</title>
</head>
<body>
  Hello, AWS Code* World!!
</body>
</html>
```
# 04 EC2 インスタンスをデプロイ先とした、CI/CD 環境を構築する【事前準備編】
## IAM
```bash:コマンド
# 変数
EC2_IAM_ROLE_NAME="EC2WebRole" \
&& echo ${EC2_IAM_ROLE_NAME}

# AWS管理ポリシー
AWS_POLICY_NAME="AmazonS3FullAccess" \
&& echo ${AWS_POLICY_NAME}

# 信頼関係ポリシードキュメントの作成
ASSUME_ROLE_POLICY_DOCUMENT=$(cat << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "ec2.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
EOF
) \
&& echo ${ASSUME_ROLE_POLICY_DOCUMENT}

# JSONフォーマットの確認
echo ${ASSUME_ROLE_POLICY_DOCUMENT} | python -m json.tool

# IAMロールの作成
aws iam create-role \
    --role-name ${EC2_IAM_ROLE_NAME} \
    --assume-role-policy-document "${ASSUME_ROLE_POLICY_DOCUMENT}"

# ARN取得
EC2_IAM_ROLE_ARN=$(
    aws iam get-role \
        --role-name ${EC2_IAM_ROLE_NAME} \
        --query 'Role.Arn' --output text
) \
&& echo ${EC2_IAM_ROLE_ARN}

# IAMロールにポリシーをアタッチ
aws iam attach-role-policy \
    --role-name ${EC2_IAM_ROLE_NAME} \
    --policy-arn arn:aws:iam::aws:policy/${AWS_POLICY_NAME}

# インスタンスプロファイル作成
aws iam create-instance-profile \
    --instance-profile-name ${EC2_IAM_ROLE_NAME}

# インスタンスプロファイルへのロールのアタッチ
aws iam add-role-to-instance-profile \
    --instance-profile-name ${EC2_IAM_ROLE_NAME} \
    --role-name ${EC2_IAM_ROLE_NAME}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # 変数
[cloudshell-user@ip-10-132-76-170 ~]$ EC2_IAM_ROLE_NAME="EC2WebRole" \
> && echo ${EC2_IAM_ROLE_NAME}
EC2WebRole
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # AWS管理ポリシー
[cloudshell-user@ip-10-132-76-170 ~]$ AWS_POLICY_NAME="AmazonS3FullAccess" \
> && echo ${AWS_POLICY_NAME}
AmazonS3FullAccess
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # 信頼関係ポリシードキュメントの作成
[cloudshell-user@ip-10-132-76-170 ~]$ ASSUME_ROLE_POLICY_DOCUMENT=$(cat << EOF
> {
>     "Version": "2012-10-17",
>     "Statement": [
>         {
>             "Effect": "Allow",
>             "Principal": {
>                 "Service": "ec2.amazonaws.com"
>             },
>             "Action": "sts:AssumeRole"
>         }
>     ]
> }
> EOF
> ) \
> && echo ${ASSUME_ROLE_POLICY_DOCUMENT}
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-76-170 ~]$ echo ${ASSUME_ROLE_POLICY_DOCUMENT} | python -m json.tool
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "ec2.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMロールの作成
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam create-role \
>     --role-name ${EC2_IAM_ROLE_NAME} \
>     --assume-role-policy-document "${ASSUME_ROLE_POLICY_DOCUMENT}"
{
    "Role": {
        "Path": "/",
        "RoleName": "EC2WebRole",
        "RoleId": "AROAWFKRCMKO43YOGO2AX",
        "Arn": "arn:aws:iam::999999999999:role/EC2WebRole",
        "CreateDate": "2024-09-14T06:24:26+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "ec2.amazonaws.com"
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        }
    }
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ARN取得
[cloudshell-user@ip-10-132-76-170 ~]$ EC2_IAM_ROLE_ARN=$(
>     aws iam get-role \
>         --role-name ${EC2_IAM_ROLE_NAME} \
>         --query 'Role.Arn' --output text
> ) \
> && echo ${EC2_IAM_ROLE_ARN}
arn:aws:iam::999999999999:role/EC2WebRole
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMロールにポリシーをアタッチ
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam attach-role-policy \
>     --role-name ${EC2_IAM_ROLE_NAME} \
>     --policy-arn arn:aws:iam::aws:policy/${AWS_POLICY_NAME}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # インスタンスプロファイル作成
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam create-instance-profile \
>     --instance-profile-name ${EC2_IAM_ROLE_NAME}
{
    "InstanceProfile": {
        "Path": "/",
        "InstanceProfileName": "EC2WebRole",
        "InstanceProfileId": "AIPAWFKRCMKO4WKPDIQTM",
        "Arn": "arn:aws:iam::999999999999:instance-profile/EC2WebRole",
        "CreateDate": "2024-09-14T06:24:32+00:00",
        "Roles": []
    }
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # インスタンスプロファイルへのロールのアタッチ
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam add-role-to-instance-profile \
>     --instance-profile-name ${EC2_IAM_ROLE_NAME} \
>     --role-name ${EC2_IAM_ROLE_NAME}
```
## EC2
### セキュリティグループ
```bash:コマンド
# セキュリティグループ名
EC2_SG_NAME='h4b-handson-ec2' \
&& echo ${EC2_SG_NAME}

# セキュリティグループ説明
EC2_SG_DESC='h4b-handson-ec2' \
&& echo ${EC2_SG_DESC}

# デフォルトVPC ID取得
VPC_ID=$( \
  aws ec2 describe-vpcs \
    --region ap-northeast-1 \
    --filters Name=is-default,Values=true \
    --query 'Vpcs[].VpcId' \
    --output text
) \
&& echo ${VPC_ID}

# 作成
aws ec2 create-security-group \
    --group-name ${EC2_SG_NAME} \
    --description "${EC2_SG_DESC}" \
    --vpc-id ${VPC_ID}

# ID取得
EC2_SG_ID=$( \
    aws ec2 describe-security-groups \
        --filters Name=vpc-id,Values=${VPC_ID} \
                  Name=group-name,Values=${EC2_SG_NAME} \
        --query "SecurityGroups[].GroupId" \
        --output text
) \
&& echo ${EC2_SG_ID}

# ルール追加 (SSH)
aws ec2 authorize-security-group-ingress \
    --group-id ${EC2_SG_ID} \
    --protocol tcp \
    --port 22 \
    --cidr 0.0.0.0/0

# ルール追加 (HTTP)
aws ec2 authorize-security-group-ingress \
    --group-id ${EC2_SG_ID} \
    --protocol tcp \
    --port 80 \
    --cidr 0.0.0.0/0

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # セキュリティグループ名
[cloudshell-user@ip-10-132-76-170 ~]$ EC2_SG_NAME='h4b-handson-ec2' \
> && echo ${EC2_SG_NAME}
h4b-handson-ec2
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # セキュリティグループ説明
[cloudshell-user@ip-10-132-76-170 ~]$ EC2_SG_DESC='h4b-handson-ec2' \
> && echo ${EC2_SG_DESC}
h4b-handson-ec2
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # デフォルトVPC ID取得
[cloudshell-user@ip-10-132-76-170 ~]$ VPC_ID=$( \
>   aws ec2 describe-vpcs \
>     --region ap-northeast-1 \
>     --filters Name=is-default,Values=true \
>     --query 'Vpcs[].VpcId' \
>     --output text
> ) \
> && echo ${VPC_ID}
vpc-090c14ab4d18c8e0b
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # 作成
[cloudshell-user@ip-10-132-76-170 ~]$ aws ec2 create-security-group \
>     --group-name ${EC2_SG_NAME} \
>     --description "${EC2_SG_DESC}" \
>     --vpc-id ${VPC_ID}
{
    "GroupId": "sg-08f573a025db109f9"
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ID取得
[cloudshell-user@ip-10-132-76-170 ~]$ EC2_SG_ID=$( \
>     aws ec2 describe-security-groups \
>         --filters Name=vpc-id,Values=${VPC_ID} \
>                   Name=group-name,Values=${EC2_SG_NAME} \
>         --query "SecurityGroups[].GroupId" \
>         --output text
> ) \
> && echo ${EC2_SG_ID}
sg-08f573a025db109f9
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ルール追加 (SSH)
[cloudshell-user@ip-10-132-76-170 ~]$ aws ec2 authorize-security-group-ingress \
>     --group-id ${EC2_SG_ID} \
>     --protocol tcp \
>     --port 22 \
>     --cidr 0.0.0.0/0
{
    "Return": true,
    "SecurityGroupRules": [
        {
            "SecurityGroupRuleId": "sgr-0159dda818117c090",
            "GroupId": "sg-08f573a025db109f9",
            "GroupOwnerId": "999999999999",
            "IsEgress": false,
            "IpProtocol": "tcp",
            "FromPort": 22,
            "ToPort": 22,
            "CidrIpv4": "0.0.0.0/0"
        }
    ]
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ルール追加 (HTTP)
[cloudshell-user@ip-10-132-76-170 ~]$ aws ec2 authorize-security-group-ingress \
>     --group-id ${EC2_SG_ID} \
>     --protocol tcp \
>     --port 80 \
>     --cidr 0.0.0.0/0
{
    "Return": true,
    "SecurityGroupRules": [
        {
            "SecurityGroupRuleId": "sgr-04a20a5b3d410a8aa",
            "GroupId": "sg-08f573a025db109f9",
            "GroupOwnerId": "999999999999",
            "IsEgress": false,
            "IpProtocol": "tcp",
            "FromPort": 80,
            "ToPort": 80,
            "CidrIpv4": "0.0.0.0/0"
        }
    ]
}
```
### インスタンス
```bash:コマンド
# 名前
EC2_NAME="Web" \
&& echo ${EC2_NAME}

# インスタンスタイプ
EC2_INSTANCE_TYPE="t2.micro" \
&& echo ${EC2_INSTANCE_TYPE}

# Amazon マシンイメージ (AMI)
EC2_IMAGE_ID="resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2" \
&& echo ${EC2_IMAGE_ID}

# EC2インスタンス作成
aws ec2 run-instances \
    --image-id ${EC2_IMAGE_ID} \
    --security-group-ids ${EC2_SG_ID} \
    --instance-type ${EC2_INSTANCE_TYPE} \
    --iam-instance-profile Name=${EC2_IAM_ROLE_NAME} \
    --tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=${EC2_NAME}}]" \
    --no-cli-pager

# ID取得
EC2_INSTANCE_ID=$( \
    aws ec2 describe-instances \
        --filters Name=tag:Name,Values=${EC2_NAME}  \
        --query "Reservations[*].Instances[*].[InstanceId]" \
        --output text
) \
&& echo ${EC2_INSTANCE_ID} 

# パブリックIP確認
EC2_PUBLIC_IP=$(
    aws ec2 describe-instances \
        --instance-ids ${EC2_INSTANCE_ID} \
        --query "Reservations[*].Instances[*].PublicIpAddress" \
        --output text
) \
&& echo ${EC2_PUBLIC_IP}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # 名前
[cloudshell-user@ip-10-132-76-170 ~]$ EC2_NAME="Web" \
> && echo ${EC2_NAME}
Web
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # インスタンスタイプ
[cloudshell-user@ip-10-132-76-170 ~]$ EC2_INSTANCE_TYPE="t2.micro" \
> && echo ${EC2_INSTANCE_TYPE}
t2.micro
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # Amazon マシンイメージ (AMI)
[cloudshell-user@ip-10-132-76-170 ~]$ EC2_IMAGE_ID="resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2" \
> && echo ${EC2_IMAGE_ID}
resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # EC2インスタンス作成
[cloudshell-user@ip-10-132-76-170 ~]$ aws ec2 run-instances \
>     --image-id ${EC2_IMAGE_ID} \
>     --security-group-ids ${EC2_SG_ID} \
>     --instance-type ${EC2_INSTANCE_TYPE} \
>     --iam-instance-profile Name=${EC2_IAM_ROLE_NAME} \
>     --tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=${EC2_NAME}}]" \
>     --no-cli-pager
{
    "Groups": [],
    "Instances": [
        {
            "AmiLaunchIndex": 0,
            "ImageId": "ami-06aa91d03bbe9eed7",
            "InstanceId": "i-02a25fbe53f00866b",
            "InstanceType": "t2.micro",
            "LaunchTime": "2024-09-14T06:27:00+00:00",
            "Monitoring": {
                "State": "disabled"
            },
            "Placement": {
                "AvailabilityZone": "ap-northeast-1a",
                "GroupName": "",
                "Tenancy": "default"
            },
            "PrivateDnsName": "ip-172-31-38-107.ap-northeast-1.compute.internal",
            "PrivateIpAddress": "172.31.38.107",
            "ProductCodes": [],
            "PublicDnsName": "",
            "State": {
                "Code": 0,
                "Name": "pending"
            },
            "StateTransitionReason": "",
            "SubnetId": "subnet-0e58505daeffcca69",
            "VpcId": "vpc-090c14ab4d18c8e0b",
            "Architecture": "x86_64",
            "BlockDeviceMappings": [],
            "ClientToken": "f0d2d312-4cab-4d3a-a1ac-fb19114b69d8",
            "EbsOptimized": false,
            "EnaSupport": true,
            "Hypervisor": "xen",
            "IamInstanceProfile": {
                "Arn": "arn:aws:iam::999999999999:instance-profile/EC2WebRole",
                "Id": "AIPAWFKRCMKO4WKPDIQTM"
            },
            "NetworkInterfaces": [
                {
                    "Attachment": {
                        "AttachTime": "2024-09-14T06:27:00+00:00",
                        "AttachmentId": "eni-attach-012f406cae9a111c3",
                        "DeleteOnTermination": true,
                        "DeviceIndex": 0,
                        "Status": "attaching",
                        "NetworkCardIndex": 0
                    },
                    "Description": "",
                    "Groups": [
                        {
                            "GroupName": "h4b-handson-ec2",
                            "GroupId": "sg-08f573a025db109f9"
                        }
                    ],
                    "Ipv6Addresses": [],
                    "MacAddress": "06:b8:da:b5:79:8b",
                    "NetworkInterfaceId": "eni-044acc18ae3c3a08c",
                    "OwnerId": "999999999999",
                    "PrivateDnsName": "ip-172-31-38-107.ap-northeast-1.compute.internal",
                    "PrivateIpAddress": "172.31.38.107",
                    "PrivateIpAddresses": [
                        {
                            "Primary": true,
                            "PrivateDnsName": "ip-172-31-38-107.ap-northeast-1.compute.internal",
                            "PrivateIpAddress": "172.31.38.107"
                        }
                    ],
                    "SourceDestCheck": true,
                    "Status": "in-use",
                    "SubnetId": "subnet-0e58505daeffcca69",
                    "VpcId": "vpc-090c14ab4d18c8e0b",
                    "InterfaceType": "interface"
                }
            ],
            "RootDeviceName": "/dev/xvda",
            "RootDeviceType": "ebs",
            "SecurityGroups": [
                {
                    "GroupName": "h4b-handson-ec2",
                    "GroupId": "sg-08f573a025db109f9"
                }
            ],
            "SourceDestCheck": true,
            "StateReason": {
                "Code": "pending",
                "Message": "pending"
            },
            "Tags": [
                {
                    "Key": "Name",
                    "Value": "Web"
                }
            ],
            "VirtualizationType": "hvm",
            "CpuOptions": {
                "CoreCount": 1,
                "ThreadsPerCore": 1
            },
            "CapacityReservationSpecification": {
                "CapacityReservationPreference": "open"
            },
            "MetadataOptions": {
                "State": "pending",
                "HttpTokens": "optional",
                "HttpPutResponseHopLimit": 1,
                "HttpEndpoint": "enabled",
                "HttpProtocolIpv6": "disabled",
                "InstanceMetadataTags": "disabled"
            },
            "EnclaveOptions": {
                "Enabled": false
            },
            "PrivateDnsNameOptions": {
                "HostnameType": "ip-name",
                "EnableResourceNameDnsARecord": false,
                "EnableResourceNameDnsAAAARecord": false
            },
            "MaintenanceOptions": {
                "AutoRecovery": "default"
            },
            "CurrentInstanceBootMode": "legacy-bios"
        }
    ],
    "OwnerId": "999999999999",
    "ReservationId": "r-0528cf4ab9536c07f"
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ID取得
[cloudshell-user@ip-10-132-76-170 ~]$ EC2_INSTANCE_ID=$( \
>     aws ec2 describe-instances \
>         --filters Name=tag:Name,Values=${EC2_NAME}  \
>         --query "Reservations[*].Instances[*].[InstanceId]" \
>         --output text
> ) \
> && echo ${EC2_INSTANCE_ID} 
i-02a25fbe53f00866b
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # パブリックIP確認
[cloudshell-user@ip-10-132-76-170 ~]$ EC2_PUBLIC_IP=$(
>     aws ec2 describe-instances \
>         --instance-ids ${EC2_INSTANCE_ID} \
>         --query "Reservations[*].Instances[*].PublicIpAddress" \
>         --output text
> ) \
> && echo ${EC2_PUBLIC_IP}
13.113.212.231
```
### EC2 Instance Connect を使用して接続
```bash:コマンド
aws ec2-instance-connect ssh --instance-id ${EC2_INSTANCE_ID}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ aws ec2-instance-connect ssh --instance-id ${EC2_INSTANCE_ID}
The authenticity of host '13.113.212.231 (13.113.212.231)' can't be established.
ED25519 key fingerprint is SHA256:owWbRMWyGWhhNciF1C+XwTI7xfhS6Wn63NfRXT2dRXI.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '13.113.212.231' (ED25519) to the list of known hosts.
   ,     #_
   ~\_  ####_        Amazon Linux 2
  ~~  \_#####\
  ~~     \###|       AL2 End of Life is 2025-06-30.
  ~~       \#/ ___
   ~~       V~' '->
    ~~~         /    A newer version of Amazon Linux is available!
      ~~._.   _/
         _/ _/       Amazon Linux 2023, GA and supported until 2028-03-15.
       _/m/'           https://aws.amazon.com/linux/amazon-linux-2023/

[ec2-user@ip-172-31-38-107 ~]$ 
```
### EC2初期設定
```bash:コマンド
sudo yum update -y
sudo yum install httpd -y
sudo systemctl start httpd.service
sudo systemctl enable httpd.service

```
```bash:出力
[ec2-user@ip-172-31-38-107 ~]$ sudo yum update -y
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
No packages marked for update
[ec2-user@ip-172-31-38-107 ~]$ sudo yum install httpd -y
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
Resolving Dependencies
--> Running transaction check
---> Package httpd.x86_64 0:2.4.62-1.amzn2.0.2 will be installed
--> Processing Dependency: httpd-filesystem = 2.4.62-1.amzn2.0.2 for package: httpd-2.4.62-1.amzn2.0.2.x86_64
--> Processing Dependency: httpd-tools = 2.4.62-1.amzn2.0.2 for package: httpd-2.4.62-1.amzn2.0.2.x86_64
--> Processing Dependency: /etc/mime.types for package: httpd-2.4.62-1.amzn2.0.2.x86_64
--> Processing Dependency: httpd-filesystem for package: httpd-2.4.62-1.amzn2.0.2.x86_64
--> Processing Dependency: mod_http2 for package: httpd-2.4.62-1.amzn2.0.2.x86_64
--> Processing Dependency: system-logos-httpd for package: httpd-2.4.62-1.amzn2.0.2.x86_64
--> Processing Dependency: libapr-1.so.0()(64bit) for package: httpd-2.4.62-1.amzn2.0.2.x86_64
--> Processing Dependency: libaprutil-1.so.0()(64bit) for package: httpd-2.4.62-1.amzn2.0.2.x86_64
--> Running transaction check
---> Package apr.x86_64 0:1.7.2-1.amzn2 will be installed
---> Package apr-util.x86_64 0:1.6.3-1.amzn2.0.1 will be installed
--> Processing Dependency: apr-util-bdb(x86-64) = 1.6.3-1.amzn2.0.1 for package: apr-util-1.6.3-1.amzn2.0.1.x86_64
---> Package generic-logos-httpd.noarch 0:18.0.0-4.amzn2 will be installed
---> Package httpd-filesystem.noarch 0:2.4.62-1.amzn2.0.2 will be installed
---> Package httpd-tools.x86_64 0:2.4.62-1.amzn2.0.2 will be installed
---> Package mailcap.noarch 0:2.1.41-2.amzn2 will be installed
---> Package mod_http2.x86_64 0:1.15.19-1.amzn2.0.2 will be installed
--> Running transaction check
---> Package apr-util-bdb.x86_64 0:1.6.3-1.amzn2.0.1 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

===========================================================================================================================================================================================================================================================================================
 Package                                                                   Arch                                                         Version                                                                     Repository                                                        Size
===========================================================================================================================================================================================================================================================================================
Installing:
 httpd                                                                     x86_64                                                       2.4.62-1.amzn2.0.2                                                          amzn2-core                                                       1.4 M
Installing for dependencies:
 apr                                                                       x86_64                                                       1.7.2-1.amzn2                                                               amzn2-core                                                       130 k
 apr-util                                                                  x86_64                                                       1.6.3-1.amzn2.0.1                                                           amzn2-core                                                       101 k
 apr-util-bdb                                                              x86_64                                                       1.6.3-1.amzn2.0.1                                                           amzn2-core                                                        22 k
 generic-logos-httpd                                                       noarch                                                       18.0.0-4.amzn2                                                              amzn2-core                                                        19 k
 httpd-filesystem                                                          noarch                                                       2.4.62-1.amzn2.0.2                                                          amzn2-core                                                        25 k
 httpd-tools                                                               x86_64                                                       2.4.62-1.amzn2.0.2                                                          amzn2-core                                                        89 k
 mailcap                                                                   noarch                                                       2.1.41-2.amzn2                                                              amzn2-core                                                        31 k
 mod_http2                                                                 x86_64                                                       1.15.19-1.amzn2.0.2                                                         amzn2-core                                                       149 k

Transaction Summary
===========================================================================================================================================================================================================================================================================================
Install  1 Package (+8 Dependent packages)

Total download size: 1.9 M
Installed size: 5.3 M
Downloading packages:
(1/9): apr-1.7.2-1.amzn2.x86_64.rpm                                                                                                                                                                                                                                 | 130 kB  00:00:00     
(2/9): apr-util-1.6.3-1.amzn2.0.1.x86_64.rpm                                                                                                                                                                                                                        | 101 kB  00:00:00     
(3/9): apr-util-bdb-1.6.3-1.amzn2.0.1.x86_64.rpm                                                                                                                                                                                                                    |  22 kB  00:00:00     
(4/9): generic-logos-httpd-18.0.0-4.amzn2.noarch.rpm                                                                                                                                                                                                                |  19 kB  00:00:00     
(5/9): httpd-filesystem-2.4.62-1.amzn2.0.2.noarch.rpm                                                                                                                                                                                                               |  25 kB  00:00:00     
(6/9): httpd-2.4.62-1.amzn2.0.2.x86_64.rpm                                                                                                                                                                                                                          | 1.4 MB  00:00:00     
(7/9): httpd-tools-2.4.62-1.amzn2.0.2.x86_64.rpm                                                                                                                                                                                                                    |  89 kB  00:00:00     
(8/9): mailcap-2.1.41-2.amzn2.noarch.rpm                                                                                                                                                                                                                            |  31 kB  00:00:00     
(9/9): mod_http2-1.15.19-1.amzn2.0.2.x86_64.rpm                                                                                                                                                                                                                     | 149 kB  00:00:00     
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Total                                                                                                                                                                                                                                                      8.5 MB/s | 1.9 MB  00:00:00     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : apr-1.7.2-1.amzn2.x86_64                                                                                                                                                                                                                                                1/9 
  Installing : apr-util-1.6.3-1.amzn2.0.1.x86_64                                                                                                                                                                                                                                       2/9 
  Installing : apr-util-bdb-1.6.3-1.amzn2.0.1.x86_64                                                                                                                                                                                                                                   3/9 
  Installing : httpd-tools-2.4.62-1.amzn2.0.2.x86_64                                                                                                                                                                                                                                   4/9 
  Installing : httpd-filesystem-2.4.62-1.amzn2.0.2.noarch                                                                                                                                                                                                                              5/9 
  Installing : generic-logos-httpd-18.0.0-4.amzn2.noarch                                                                                                                                                                                                                               6/9 
  Installing : mailcap-2.1.41-2.amzn2.noarch                                                                                                                                                                                                                                           7/9 
  Installing : mod_http2-1.15.19-1.amzn2.0.2.x86_64                                                                                                                                                                                                                                    8/9 
  Installing : httpd-2.4.62-1.amzn2.0.2.x86_64                                                                                                                                                                                                                                         9/9 
  Verifying  : apr-util-bdb-1.6.3-1.amzn2.0.1.x86_64                                                                                                                                                                                                                                   1/9 
  Verifying  : httpd-2.4.62-1.amzn2.0.2.x86_64                                                                                                                                                                                                                                         2/9 
  Verifying  : apr-1.7.2-1.amzn2.x86_64                                                                                                                                                                                                                                                3/9 
  Verifying  : mod_http2-1.15.19-1.amzn2.0.2.x86_64                                                                                                                                                                                                                                    4/9 
  Verifying  : apr-util-1.6.3-1.amzn2.0.1.x86_64                                                                                                                                                                                                                                       5/9 
  Verifying  : mailcap-2.1.41-2.amzn2.noarch                                                                                                                                                                                                                                           6/9 
  Verifying  : generic-logos-httpd-18.0.0-4.amzn2.noarch                                                                                                                                                                                                                               7/9 
  Verifying  : httpd-tools-2.4.62-1.amzn2.0.2.x86_64                                                                                                                                                                                                                                   8/9 
  Verifying  : httpd-filesystem-2.4.62-1.amzn2.0.2.noarch                                                                                                                                                                                                                              9/9 

Installed:
  httpd.x86_64 0:2.4.62-1.amzn2.0.2                                                                                                                                                                                                                                                        

Dependency Installed:
  apr.x86_64 0:1.7.2-1.amzn2             apr-util.x86_64 0:1.6.3-1.amzn2.0.1 apr-util-bdb.x86_64 0:1.6.3-1.amzn2.0.1 generic-logos-httpd.noarch 0:18.0.0-4.amzn2 httpd-filesystem.noarch 0:2.4.62-1.amzn2.0.2 httpd-tools.x86_64 0:2.4.62-1.amzn2.0.2 mailcap.noarch 0:2.1.41-2.amzn2
  mod_http2.x86_64 0:1.15.19-1.amzn2.0.2

Complete!
[ec2-user@ip-172-31-38-107 ~]$ sudo systemctl start httpd.service
[ec2-user@ip-172-31-38-107 ~]$ sudo systemctl enable httpd.service
Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service.
```
### アクセス確認
:::note info
EC2_PUBLIC_IPは適宜変更
:::
```bash:コマンド
EC2_PUBLIC_IP="13.113.212.231" \
&& echo ${EC2_PUBLIC_IP}

curl ${EC2_PUBLIC_IP}

```
```bash:出力
[ec2-user@ip-172-31-38-107 ~]$ EC2_PUBLIC_IP="13.113.212.231" \
> && echo ${EC2_PUBLIC_IP}
13.113.212.231
[ec2-user@ip-172-31-38-107 ~]$ 
[ec2-user@ip-172-31-38-107 ~]$ curl ${EC2_PUBLIC_IP}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
        <head>
                <title>Test Page for the Apache HTTP Server</title>
                <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
                <style type="text/css">
                        /*<![CDATA[*/
                        body {
                                background-color: #fff;
                                color: #000;
                                font-size: 0.9em;
                                font-family: sans-serif,helvetica;
                                margin: 0;
                                padding: 0;
                        }
                        :link {
                                color: #c00;
                        }
                        :visited {
                                color: #c00;
                        }
                        a:hover {
                                color: #f50;
                        }
                        h1 {
                                text-align: center;
                                margin: 0;
                                padding: 0.6em 2em 0.4em;
                                background-color: #900;
                                color: #fff;
                                font-weight: normal;
                                font-size: 1.75em;
                                border-bottom: 2px solid #000;
                        }
                        h1 strong {
                                font-weight: bold;
                        }
                        h2 {
                                font-size: 1.1em;
                                font-weight: bold;
                        }
                        hr {
                                display: none;
                        }
                        .content {
                                padding: 1em 5em;
                        }
                        .content-columns {
                                /* Setting relative positioning allows for 
                                absolute positioning for sub-classes */
                                position: relative;
                                padding-top: 1em;
                        }
                        .content-column-left {
                                /* Value for IE/Win; will be overwritten for other browsers */
                                width: 47%;
                                padding-right: 3%;
                                float: left;
                                padding-bottom: 2em;
                        }
                        .content-column-left hr {
                                display: none;
                        }
                        .content-column-right {
                                /* Values for IE/Win; will be overwritten for other browsers */
                                width: 47%;
                                padding-left: 3%;
                                float: left;
                                padding-bottom: 2em;
                        }
                        .content-columns>.content-column-left, .content-columns>.content-column-right {
                                /* Non-IE/Win */
                        }
                        img {
                                border: 2px solid #fff;
                                padding: 2px;
                                margin: 2px;
                        }
                        a:hover img {
                                border: 2px solid #f50;
                        }
                        /*]]>*/
                </style>
        </head>

        <body>
                <h1>Test Page</h1>

                <div class="content">
                        <div class="content-middle">
                                <p>This page is used to test the proper operation of the Apache HTTP server after it has been installed. If you can read this page, it means that the Apache HTTP server installed at this site is working properly.</p>
                        </div>
                        <hr />

                        <div class="content-columns">
                                <div class="content-column-left">
                                        <h2>If you are a member of the general public:</h2>

                                        <p>The fact that you are seeing this page indicates that the website you just visited is either experiencing problems, or is undergoing routine maintenance.</p>

                                        <p>If you would like to let the administrators of this website know that you've seen this page instead of the page you expected, you should send them e-mail. In general, mail sent to the name "webmaster" and directed to the website's domain should reach the appropriate person.</p>

                                        <p>For example, if you experienced problems while visiting www.example.com, you should send e-mail to "webmaster@example.com".</p>

                                        <hr />
                                </div>

                                <div class="content-column-right">
                                        <h2>If you are the website administrator:</h2>

                                        <p>You may now add content to the directory <tt>/var/www/html/</tt>. Note that until you do so, people visiting your website will see this page, and not your content. To prevent this page from ever being used, follow the instructions in the file <tt>/etc/httpd/conf.d/welcome.conf</tt>.</p>

                                        <p>You are free to use the image below on web sites powered by the Apache HTTP Server:</p>

                                        <p align="center"><a href="http://httpd.apache.org/"><img src="/icons/apache_pb2.gif" alt="[ Powered by Apache ]"/></a></p>

                                </div>
                        </div>
                </div>
        </body>
</html>
```
### CodeDeploy エージェントをインストール
```bash:コマンド
sudo yum install ruby -y
sudo yum install wget -y
cd /home/ec2-user
wget https://aws-codedeploy-ap-northeast-1.s3.ap-northeast-1.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto
systemctl status codedeploy-agent

```
```bash:出力
[ec2-user@ip-172-31-38-107 ~]$ sudo yum install ruby -y
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
Resolving Dependencies
--> Running transaction check
---> Package ruby.x86_64 0:2.0.0.648-36.amzn2.0.10 will be installed
--> Processing Dependency: ruby-libs(x86-64) = 2.0.0.648-36.amzn2.0.10 for package: ruby-2.0.0.648-36.amzn2.0.10.x86_64
--> Processing Dependency: ruby(rubygems) >= 2.0.14.1 for package: ruby-2.0.0.648-36.amzn2.0.10.x86_64
--> Processing Dependency: rubygem(bigdecimal) >= 1.2.0 for package: ruby-2.0.0.648-36.amzn2.0.10.x86_64
--> Processing Dependency: libruby.so.2.0()(64bit) for package: ruby-2.0.0.648-36.amzn2.0.10.x86_64
--> Running transaction check
---> Package ruby-libs.x86_64 0:2.0.0.648-36.amzn2.0.10 will be installed
---> Package rubygem-bigdecimal.x86_64 0:1.2.0-36.amzn2.0.10 will be installed
---> Package rubygems.noarch 0:2.0.14.1-36.amzn2.0.10 will be installed
--> Processing Dependency: rubygem(io-console) >= 0.4.2 for package: rubygems-2.0.14.1-36.amzn2.0.10.noarch
--> Processing Dependency: rubygem(psych) >= 2.0.0 for package: rubygems-2.0.14.1-36.amzn2.0.10.noarch
--> Processing Dependency: rubygem(rdoc) >= 4.0.0 for package: rubygems-2.0.14.1-36.amzn2.0.10.noarch
--> Running transaction check
---> Package rubygem-io-console.x86_64 0:0.4.2-36.amzn2.0.10 will be installed
---> Package rubygem-psych.x86_64 0:2.0.0-36.amzn2.0.10 will be installed
---> Package rubygem-rdoc.noarch 0:4.0.0-36.amzn2.0.10 will be installed
--> Processing Dependency: ruby(irb) = 2.0.0.648 for package: rubygem-rdoc-4.0.0-36.amzn2.0.10.noarch
--> Processing Dependency: rubygem(json) >= 1.7.7 for package: rubygem-rdoc-4.0.0-36.amzn2.0.10.noarch
--> Running transaction check
---> Package ruby-irb.noarch 0:2.0.0.648-36.amzn2.0.10 will be installed
---> Package rubygem-json.x86_64 0:1.7.7-36.amzn2.0.10 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

===========================================================================================================================================================================================================================================================================================
 Package                                                                 Arch                                                        Version                                                                         Repository                                                       Size
===========================================================================================================================================================================================================================================================================================
Installing:
 ruby                                                                    x86_64                                                      2.0.0.648-36.amzn2.0.10                                                         amzn2-core                                                       75 k
Installing for dependencies:
 ruby-irb                                                                noarch                                                      2.0.0.648-36.amzn2.0.10                                                         amzn2-core                                                       97 k
 ruby-libs                                                               x86_64                                                      2.0.0.648-36.amzn2.0.10                                                         amzn2-core                                                      2.8 M
 rubygem-bigdecimal                                                      x86_64                                                      1.2.0-36.amzn2.0.10                                                             amzn2-core                                                       87 k
 rubygem-io-console                                                      x86_64                                                      0.4.2-36.amzn2.0.10                                                             amzn2-core                                                       58 k
 rubygem-json                                                            x86_64                                                      1.7.7-36.amzn2.0.10                                                             amzn2-core                                                       83 k
 rubygem-psych                                                           x86_64                                                      2.0.0-36.amzn2.0.10                                                             amzn2-core                                                       87 k
 rubygem-rdoc                                                            noarch                                                      4.0.0-36.amzn2.0.10                                                             amzn2-core                                                      326 k
 rubygems                                                                noarch                                                      2.0.14.1-36.amzn2.0.10                                                          amzn2-core                                                      218 k

Transaction Summary
===========================================================================================================================================================================================================================================================================================
Install  1 Package (+8 Dependent packages)

Total download size: 3.8 M
Installed size: 12 M
Downloading packages:
(1/9): ruby-2.0.0.648-36.amzn2.0.10.x86_64.rpm                                                                                                                                                                                                                      |  75 kB  00:00:00     
(2/9): ruby-irb-2.0.0.648-36.amzn2.0.10.noarch.rpm                                                                                                                                                                                                                  |  97 kB  00:00:00     
(3/9): rubygem-bigdecimal-1.2.0-36.amzn2.0.10.x86_64.rpm                                                                                                                                                                                                            |  87 kB  00:00:00     
(4/9): rubygem-io-console-0.4.2-36.amzn2.0.10.x86_64.rpm                                                                                                                                                                                                            |  58 kB  00:00:00     
(5/9): rubygem-json-1.7.7-36.amzn2.0.10.x86_64.rpm                                                                                                                                                                                                                  |  83 kB  00:00:00     
(6/9): ruby-libs-2.0.0.648-36.amzn2.0.10.x86_64.rpm                                                                                                                                                                                                                 | 2.8 MB  00:00:00     
(7/9): rubygem-psych-2.0.0-36.amzn2.0.10.x86_64.rpm                                                                                                                                                                                                                 |  87 kB  00:00:00     
(8/9): rubygem-rdoc-4.0.0-36.amzn2.0.10.noarch.rpm                                                                                                                                                                                                                  | 326 kB  00:00:00     
(9/9): rubygems-2.0.14.1-36.amzn2.0.10.noarch.rpm                                                                                                                                                                                                                   | 218 kB  00:00:00     
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Total                                                                                                                                                                                                                                                       15 MB/s | 3.8 MB  00:00:00     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : ruby-libs-2.0.0.648-36.amzn2.0.10.x86_64                                                                                                                                                                                                                                1/9 
  Installing : ruby-irb-2.0.0.648-36.amzn2.0.10.noarch                                                                                                                                                                                                                                 2/9 
  Installing : rubygem-json-1.7.7-36.amzn2.0.10.x86_64                                                                                                                                                                                                                                 3/9 
  Installing : rubygem-io-console-0.4.2-36.amzn2.0.10.x86_64                                                                                                                                                                                                                           4/9 
  Installing : rubygem-psych-2.0.0-36.amzn2.0.10.x86_64                                                                                                                                                                                                                                5/9 
  Installing : rubygems-2.0.14.1-36.amzn2.0.10.noarch                                                                                                                                                                                                                                  6/9 
  Installing : rubygem-bigdecimal-1.2.0-36.amzn2.0.10.x86_64                                                                                                                                                                                                                           7/9 
  Installing : ruby-2.0.0.648-36.amzn2.0.10.x86_64                                                                                                                                                                                                                                     8/9 
  Installing : rubygem-rdoc-4.0.0-36.amzn2.0.10.noarch                                                                                                                                                                                                                                 9/9 
  Verifying  : rubygem-bigdecimal-1.2.0-36.amzn2.0.10.x86_64                                                                                                                                                                                                                           1/9 
  Verifying  : ruby-irb-2.0.0.648-36.amzn2.0.10.noarch                                                                                                                                                                                                                                 2/9 
  Verifying  : ruby-libs-2.0.0.648-36.amzn2.0.10.x86_64                                                                                                                                                                                                                                3/9 
  Verifying  : rubygem-json-1.7.7-36.amzn2.0.10.x86_64                                                                                                                                                                                                                                 4/9 
  Verifying  : rubygem-io-console-0.4.2-36.amzn2.0.10.x86_64                                                                                                                                                                                                                           5/9 
  Verifying  : rubygems-2.0.14.1-36.amzn2.0.10.noarch                                                                                                                                                                                                                                  6/9 
  Verifying  : rubygem-rdoc-4.0.0-36.amzn2.0.10.noarch                                                                                                                                                                                                                                 7/9 
  Verifying  : ruby-2.0.0.648-36.amzn2.0.10.x86_64                                                                                                                                                                                                                                     8/9 
  Verifying  : rubygem-psych-2.0.0-36.amzn2.0.10.x86_64                                                                                                                                                                                                                                9/9 

Installed:
  ruby.x86_64 0:2.0.0.648-36.amzn2.0.10                                                                                                                                                                                                                                                    

Dependency Installed:
  ruby-irb.noarch 0:2.0.0.648-36.amzn2.0.10   ruby-libs.x86_64 0:2.0.0.648-36.amzn2.0.10   rubygem-bigdecimal.x86_64 0:1.2.0-36.amzn2.0.10   rubygem-io-console.x86_64 0:0.4.2-36.amzn2.0.10   rubygem-json.x86_64 0:1.7.7-36.amzn2.0.10   rubygem-psych.x86_64 0:2.0.0-36.amzn2.0.10  
  rubygem-rdoc.noarch 0:4.0.0-36.amzn2.0.10   rubygems.noarch 0:2.0.14.1-36.amzn2.0.10    

Complete!
[ec2-user@ip-172-31-38-107 ~]$ sudo yum install wget -y
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
Package wget-1.14-18.amzn2.1.x86_64 already installed and latest version
Nothing to do
[ec2-user@ip-172-31-38-107 ~]$ cd /home/ec2-user
[ec2-user@ip-172-31-38-107 ~]$ wget https://aws-codedeploy-ap-northeast-1.s3.ap-northeast-1.amazonaws.com/latest/install
--2024-09-14 06:32:11--  https://aws-codedeploy-ap-northeast-1.s3.ap-northeast-1.amazonaws.com/latest/install
Resolving aws-codedeploy-ap-northeast-1.s3.ap-northeast-1.amazonaws.com (aws-codedeploy-ap-northeast-1.s3.ap-northeast-1.amazonaws.com)... 52.219.199.26, 52.219.151.66, 52.219.16.191, ...
Connecting to aws-codedeploy-ap-northeast-1.s3.ap-northeast-1.amazonaws.com (aws-codedeploy-ap-northeast-1.s3.ap-northeast-1.amazonaws.com)|52.219.199.26|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 19045 (19K) []
Saving to: ‘install’

100%[=================================================================================================================================================================================================================================================>] 19,045      --.-K/s   in 0.002s  

2024-09-14 06:32:11 (10.9 MB/s) - ‘install’ saved [19045/19045]

[ec2-user@ip-172-31-38-107 ~]$ chmod +x ./install
[ec2-user@ip-172-31-38-107 ~]$ sudo ./install auto
I, [2024-09-14T06:32:11.448807 #3803]  INFO -- : Starting Ruby version check.
I, [2024-09-14T06:32:11.450004 #3803]  INFO -- : Starting update check.
I, [2024-09-14T06:32:11.450101 #3803]  INFO -- : Attempting to automatically detect supported package manager type for system...
I, [2024-09-14T06:32:11.479127 #3803]  INFO -- : Checking AWS_REGION environment variable for region information...
I, [2024-09-14T06:32:11.479176 #3803]  INFO -- : Checking EC2 metadata service for region information...
I, [2024-09-14T06:32:11.493693 #3803]  INFO -- : Checking AWS_DOMAIN environment variable for domain information...
I, [2024-09-14T06:32:11.493846 #3803]  INFO -- : Checking EC2 metadata service for domain information...
I, [2024-09-14T06:32:11.506796 #3803]  INFO -- : Downloading version file from bucket aws-codedeploy-ap-northeast-1 and key latest/LATEST_VERSION...
I, [2024-09-14T06:32:11.507165 #3803]  INFO -- : Endpoint: https://aws-codedeploy-ap-northeast-1.s3.ap-northeast-1.amazonaws.com/latest/LATEST_VERSION
I, [2024-09-14T06:32:11.600389 #3803]  INFO -- : Downloading package from bucket aws-codedeploy-ap-northeast-1 and key releases/codedeploy-agent-1.7.0-92.noarch.rpm...
I, [2024-09-14T06:32:11.600526 #3803]  INFO -- : Endpoint: https://aws-codedeploy-ap-northeast-1.s3.ap-northeast-1.amazonaws.com/releases/codedeploy-agent-1.7.0-92.noarch.rpm
I, [2024-09-14T06:32:11.730397 #3803]  INFO -- : Executing `/usr/bin/yum -y localinstall /tmp/codedeploy-agent-1.7.0-92.noarch.tmp-20240914-3803-depiy5.rpm`...
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
Existing lock /var/run/yum.pid: another copy is running as pid 3798.
Another app is currently holding the yum lock; waiting for it to exit...
  The other application is: yum
    Memory : 123 M RSS (343 MB VSZ)
    Started: Sat Sep 14 06:32:10 2024 - 00:02 ago
    State  : Running, pid: 3798
Another app is currently holding the yum lock; waiting for it to exit...
  The other application is: yum
    Memory : 207 M RSS (428 MB VSZ)
    Started: Sat Sep 14 06:32:10 2024 - 00:04 ago
    State  : Running, pid: 3798
Examining /tmp/codedeploy-agent-1.7.0-92.noarch.tmp-20240914-3803-depiy5.rpm: codedeploy-agent-1.7.0-92.noarch
Marking /tmp/codedeploy-agent-1.7.0-92.noarch.tmp-20240914-3803-depiy5.rpm to be installed
Resolving Dependencies
--> Running transaction check
---> Package codedeploy-agent.noarch 0:1.7.0-92 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

===========================================================================================================================================================================================================================================================================================
 Package                                                        Arch                                                 Version                                                Repository                                                                                                Size
===========================================================================================================================================================================================================================================================================================
Installing:
 codedeploy-agent                                               noarch                                               1.7.0-92                                               /codedeploy-agent-1.7.0-92.noarch.tmp-20240914-3803-depiy5                                                13 M

Transaction Summary
===========================================================================================================================================================================================================================================================================================
Install  1 Package

Total size: 13 M
Installed size: 13 M
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
 
pre hook : 1
Checking if there is already a process named codedeploy-agent running.
  Installing : codedeploy-agent-1.7.0-92.noarch                                                                                                                                                                                                                                        1/1 
 
post hook : 1
Check if there is a codedeployagent config file.
Start codedeploy-agent in post hook if this is a first install.
  Verifying  : codedeploy-agent-1.7.0-92.noarch                                                                                                                                                                                                                                        1/1 

Installed:
  codedeploy-agent.noarch 0:1.7.0-92                                                                                                                                                                                                                                                       

Complete!
I, [2024-09-14T06:32:17.596613 #3803]  INFO -- : Update check complete.
I, [2024-09-14T06:32:17.596657 #3803]  INFO -- : Stopping updater.
[ec2-user@ip-172-31-38-107 ~]$ systemctl status codedeploy-agent
● codedeploy-agent.service - AWS CodeDeploy Host Agent
   Loaded: loaded (/usr/lib/systemd/system/codedeploy-agent.service; enabled; vendor preset: disabled)
   Active: active (running) since Sat 2024-09-14 06:32:17 UTC; 197ms ago
  Process: 3873 ExecStart=/bin/bash -a -c [ -f /etc/profile ] && source /etc/profile; /opt/codedeploy-agent/bin/codedeploy-agent start (code=exited, status=0/SUCCESS)
 Main PID: 3885 (ruby)
   CGroup: /system.slice/codedeploy-agent.service
           ├─3885 codedeploy-agent: master 3885
           └─3889 codedeploy-agent: booting child

Sep 14 06:32:17 ip-172-31-38-107.ap-northeast-1.compute.internal systemd[1]: Starting AWS CodeDeploy Host Agent...
Sep 14 06:32:17 ip-172-31-38-107.ap-northeast-1.compute.internal systemd[1]: Started AWS CodeDeploy Host Agent.
```
### EC2 Instance Connect を切断
```bash:コマンド
exit

```
```bash:出力
[ec2-user@ip-172-31-38-107 ~]$ exit
logout
Connection to 13.113.212.231 closed.
```
# 05 EC2 インスタンスをデプロイ先とした、CI/CD 環境を構築する【CodeBuild 編】
## IAM
```bash:コマンド
# 変数
CODEBUILD_NAME="h4b-hands-on" \
&& echo ${CODEBUILD_NAME}

# CODEBUILDアーティファクト用のS3バケット名
CODEBUILD_ARTIFACTSTORE_BUCKET_NAME="codebuild-${CODEBUILD_NAME}-artifactstore" \
&& echo ${CODEBUILD_ARTIFACTSTORE_BUCKET_NAME}

# ポリシー名
CODEBUILD_IAM_POLICY_NAME="CodeBuildBasePolicy-${CODEBUILD_NAME}-${REGION}" \
&& echo ${CODEBUILD_IAM_POLICY_NAME}

# ロール名
CODEBUILD_IAM_ROLE_NAME="codebuild-${CODEBUILD_NAME}-service-role" \
&& echo ${CODEBUILD_IAM_ROLE_NAME}

# AWS管理ポリシー
AWS_POLICY_NAME="AWSCodeDeployDeployerAccess" \
&& echo ${AWS_POLICY_NAME}

# IAMパス
IAM_PATH="/service-role/" \
&& echo ${IAM_PATH}

# IAMポリシー
POLICY_DOCUMENT_JSON=$(cat << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Resource": [
                "arn:aws:logs:ap-northeast-1:999999999999:log-group:/aws/codebuild/h4b-hands-on",
                "arn:aws:logs:ap-northeast-1:999999999999:log-group:/aws/codebuild/h4b-hands-on:*"
            ],
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ]
        },
        {
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::codepipeline-ap-northeast-1-*"
            ],
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:GetObjectVersion",
                "s3:GetBucketAcl",
                "s3:GetBucketLocation"
            ]
        },
        {
            "Effect": "Allow",
            "Resource": [
                "arn:aws:codecommit:ap-northeast-1:999999999999:h4b-hands-on"
            ],
            "Action": [
                "codecommit:GitPull"
            ]
        },
        {
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::${CODEBUILD_ARTIFACTSTORE_BUCKET_NAME}",
                "arn:aws:s3:::${CODEBUILD_ARTIFACTSTORE_BUCKET_NAME}/*"
            ],
            "Action": [
                "s3:PutObject",
                "s3:GetBucketAcl",
                "s3:GetBucketLocation"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "codebuild:CreateReportGroup",
                "codebuild:CreateReport",
                "codebuild:UpdateReport",
                "codebuild:BatchPutTestCases",
                "codebuild:BatchPutCodeCoverages"
            ],
            "Resource": [
                "arn:aws:codebuild:ap-northeast-1:999999999999:report-group/h4b-hands-on-*"
            ]
        }
    ]
}
EOF
) \
&& echo ${POLICY_DOCUMENT_JSON}

# JSONフォーマットの確認
echo ${POLICY_DOCUMENT_JSON} | python -m json.tool

# ポリシーの作成
aws iam create-policy \
    --policy-name ${CODEBUILD_IAM_POLICY_NAME} \
    --path ${IAM_PATH} \
    --policy-document "${POLICY_DOCUMENT_JSON}"

# ARN取得
CODEBUILD_IAM_POLICY_ARN=$(
    aws iam list-policies \
        --query "Policies[?PolicyName=='${CODEBUILD_IAM_POLICY_NAME}'].Arn" \
        --output text
) \
&& echo ${CODEBUILD_IAM_POLICY_ARN}

# 信頼関係ポリシードキュメントの作成
ASSUME_ROLE_POLICY_DOCUMENT=$(cat << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "codebuild.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
EOF
) \
&& echo ${ASSUME_ROLE_POLICY_DOCUMENT}

# JSONフォーマットの確認
echo ${ASSUME_ROLE_POLICY_DOCUMENT} | python -m json.tool

# IAMロールの作成
aws iam create-role \
    --path ${IAM_PATH} \
    --role-name ${CODEBUILD_IAM_ROLE_NAME} \
    --assume-role-policy-document "${ASSUME_ROLE_POLICY_DOCUMENT}"

# ARN取得
CODEBUILD_IAM_ROLE_ARN=$(
    aws iam get-role \
        --role-name ${CODEBUILD_IAM_ROLE_NAME} \
        --query 'Role.Arn' --output text
) \
&& echo ${CODEBUILD_IAM_ROLE_ARN}

# IAMロールにポリシーをアタッチ
aws iam attach-role-policy \
    --role-name ${CODEBUILD_IAM_ROLE_NAME} \
    --policy-arn ${CODEBUILD_IAM_POLICY_ARN}

aws iam attach-role-policy \
    --role-name ${CODEBUILD_IAM_ROLE_NAME} \
    --policy-arn arn:aws:iam::aws:policy/${AWS_POLICY_NAME}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # 変数
[cloudshell-user@ip-10-132-76-170 ~]$ CODEBUILD_NAME="h4b-hands-on" \
> && echo ${CODEBUILD_NAME}
h4b-hands-on
[cloudshell-user@ip-10-132-76-170 ~]$ 
a[cloudshell-user@ip-10-132-76-170 ~]$ # CODEBUILDアーティファクト用のS3バケット名
[cloudshell-user@ip-10-132-76-170 ~]$ CODEBUILD_ARTIFACTSTORE_BUCKET_NAME="codebuild-${CODEBUILD_NAME}-artifactstore" \
> && echo ${CODEBUILD_ARTIFACTSTORE_BUCKET_NAME}
codebuild-h4b-hands-on-artifactstore
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ポリシー名
[cloudshell-user@ip-10-132-76-170 ~]$ CODEBUILD_IAM_POLICY_NAME="CodeBuildBasePolicy-${CODEBUILD_NAME}-${REGION}" \
> && echo ${CODEBUILD_IAM_POLICY_NAME}
CodeBuildBasePolicy-h4b-hands-on-ap-northeast-1
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ロール名
[cloudshell-user@ip-10-132-76-170 ~]$ CODEBUILD_IAM_ROLE_NAME="codebuild-${CODEBUILD_NAME}-service-role" \
> && echo ${CODEBUILD_IAM_ROLE_NAME}
codebuild-h4b-hands-on-service-role
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # AWS管理ポリシー
[cloudshell-user@ip-10-132-76-170 ~]$ AWS_POLICY_NAME="AWSCodeDeployDeployerAccess" \
> && echo ${AWS_POLICY_NAME}
AWSCodeDeployDeployerAccess
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMパス
[cloudshell-user@ip-10-132-76-170 ~]$ IAM_PATH="/service-role/" \
> && echo ${IAM_PATH}
/service-role/
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMポリシー
[cloudshell-user@ip-10-132-76-170 ~]$ POLICY_DOCUMENT_JSON=$(cat << EOF
> {
>     "Version": "2012-10-17",
>     "Statement": [
>         {
>             "Effect": "Allow",
>             "Resource": [
>                 "arn:aws:logs:ap-northeast-1:999999999999:log-group:/aws/codebuild/h4b-hands-on",
>                 "arn:aws:logs:ap-northeast-1:999999999999:log-group:/aws/codebuild/h4b-hands-on:*"
>             ],
>             "Action": [
>                 "logs:CreateLogGroup",
>                 "logs:CreateLogStream",
>                 "logs:PutLogEvents"
>             ]
>         },
>         {
>             "Effect": "Allow",
>             "Resource": [
>                 "arn:aws:s3:::codepipeline-ap-northeast-1-*"
>             ],
>             "Action": [
>                 "s3:PutObject",
>                 "s3:GetObject",
>                 "s3:GetObjectVersion",
>                 "s3:GetBucketAcl",
>                 "s3:GetBucketLocation"
>             ]
>         },
>         {
>             "Effect": "Allow",
>             "Resource": [
>                 "arn:aws:codecommit:ap-northeast-1:999999999999:h4b-hands-on"
>             ],
>             "Action": [
>                 "codecommit:GitPull"
>             ]
>         },
>         {
>             "Effect": "Allow",
>             "Resource": [
>                 "arn:aws:s3:::${CODEBUILD_ARTIFACTSTORE_BUCKET_NAME}",
>                 "arn:aws:s3:::${CODEBUILD_ARTIFACTSTORE_BUCKET_NAME}/*"
>             ],
>             "Action": [
>                 "s3:PutObject",
>                 "s3:GetBucketAcl",
>                 "s3:GetBucketLocation"
>             ]
>         },
>         {
>             "Effect": "Allow",
>             "Action": [
>                 "codebuild:CreateReportGroup",
>                 "codebuild:CreateReport",
>                 "codebuild:UpdateReport",
>                 "codebuild:BatchPutTestCases",
>                 "codebuild:BatchPutCodeCoverages"
>             ],
>             "Resource": [
>                 "arn:aws:codebuild:ap-northeast-1:999999999999:report-group/h4b-hands-on-*"
>             ]
>         }
>     ]
> }
> EOF
> ) \
> && echo ${POLICY_DOCUMENT_JSON}
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Resource": [ "arn:aws:logs:ap-northeast-1:999999999999:log-group:/aws/codebuild/h4b-hands-on", "arn:aws:logs:ap-northeast-1:999999999999:log-group:/aws/codebuild/h4b-hands-on:*" ], "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ] }, { "Effect": "Allow", "Resource": [ "arn:aws:s3:::codepipeline-ap-northeast-1-*" ], "Action": [ "s3:PutObject", "s3:GetObject", "s3:GetObjectVersion", "s3:GetBucketAcl", "s3:GetBucketLocation" ] }, { "Effect": "Allow", "Resource": [ "arn:aws:codecommit:ap-northeast-1:999999999999:h4b-hands-on" ], "Action": [ "codecommit:GitPull" ] }, { "Effect": "Allow", "Resource": [ "arn:aws:s3:::codebuild-h4b-hands-on-artifactstore", "arn:aws:s3:::codebuild-h4b-hands-on-artifactstore/*" ], "Action": [ "s3:PutObject", "s3:GetBucketAcl", "s3:GetBucketLocation" ] }, { "Effect": "Allow", "Action": [ "codebuild:CreateReportGroup", "codebuild:CreateReport", "codebuild:UpdateReport", "codebuild:BatchPutTestCases", "codebuild:BatchPutCodeCoverages" ], "Resource": [ "arn:aws:codebuild:ap-northeast-1:999999999999:report-group/h4b-hands-on-*" ] } ] }
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-76-170 ~]$ echo ${POLICY_DOCUMENT_JSON} | python -m json.tool
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Resource": [
                "arn:aws:logs:ap-northeast-1:999999999999:log-group:/aws/codebuild/h4b-hands-on",
                "arn:aws:logs:ap-northeast-1:999999999999:log-group:/aws/codebuild/h4b-hands-on:*"
            ],
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ]
        },
        {
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::codepipeline-ap-northeast-1-*"
            ],
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:GetObjectVersion",
                "s3:GetBucketAcl",
                "s3:GetBucketLocation"
            ]
        },
        {
            "Effect": "Allow",
            "Resource": [
                "arn:aws:codecommit:ap-northeast-1:999999999999:h4b-hands-on"
            ],
            "Action": [
                "codecommit:GitPull"
            ]
        },
        {
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::codebuild-h4b-hands-on-artifactstore",
                "arn:aws:s3:::codebuild-h4b-hands-on-artifactstore/*"
            ],
            "Action": [
                "s3:PutObject",
                "s3:GetBucketAcl",
                "s3:GetBucketLocation"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "codebuild:CreateReportGroup",
                "codebuild:CreateReport",
                "codebuild:UpdateReport",
                "codebuild:BatchPutTestCases",
                "codebuild:BatchPutCodeCoverages"
            ],
            "Resource": [
                "arn:aws:codebuild:ap-northeast-1:999999999999:report-group/h4b-hands-on-*"
            ]
        }
    ]
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ポリシーの作成
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam create-policy \
>     --policy-name ${CODEBUILD_IAM_POLICY_NAME} \
>     --path ${IAM_PATH} \
>     --policy-document "${POLICY_DOCUMENT_JSON}"
{
    "Policy": {
        "PolicyName": "CodeBuildBasePolicy-h4b-hands-on-ap-northeast-1",
        "PolicyId": "ANPAWFKRCMKOZJ4SXYWZP",
        "Arn": "arn:aws:iam::999999999999:policy/service-role/CodeBuildBasePolicy-h4b-hands-on-ap-northeast-1",
        "Path": "/service-role/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 0,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "CreateDate": "2024-09-14T06:33:09+00:00",
        "UpdateDate": "2024-09-14T06:33:09+00:00"
    }
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ARN取得
[cloudshell-user@ip-10-132-76-170 ~]$ CODEBUILD_IAM_POLICY_ARN=$(
>     aws iam list-policies \
>         --query "Policies[?PolicyName=='${CODEBUILD_IAM_POLICY_NAME}'].Arn" \
>         --output text
> ) \
> && echo ${CODEBUILD_IAM_POLICY_ARN}
arn:aws:iam::999999999999:policy/service-role/CodeBuildBasePolicy-h4b-hands-on-ap-northeast-1
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # 信頼関係ポリシードキュメントの作成
[cloudshell-user@ip-10-132-76-170 ~]$ ASSUME_ROLE_POLICY_DOCUMENT=$(cat << EOF
> {
>     "Version": "2012-10-17",
>     "Statement": [
>         {
>             "Effect": "Allow",
>             "Principal": {
>                 "Service": "codebuild.amazonaws.com"
>             },
>             "Action": "sts:AssumeRole"
>         }
>     ]
> }
> EOF
> ) \
> && echo ${ASSUME_ROLE_POLICY_DOCUMENT}
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "codebuild.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-76-170 ~]$ echo ${ASSUME_ROLE_POLICY_DOCUMENT} | python -m json.tool
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "codebuild.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMロールの作成
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam create-role \
>     --path ${IAM_PATH} \
>     --role-name ${CODEBUILD_IAM_ROLE_NAME} \
>     --assume-role-policy-document "${ASSUME_ROLE_POLICY_DOCUMENT}"
{
    "Role": {
        "Path": "/service-role/",
        "RoleName": "codebuild-h4b-hands-on-service-role",
        "RoleId": "AROAWFKRCMKO3C47DZRRL",
        "Arn": "arn:aws:iam::999999999999:role/service-role/codebuild-h4b-hands-on-service-role",
        "CreateDate": "2024-09-14T06:33:16+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "codebuild.amazonaws.com"
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        }
    }
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ARN取得
[cloudshell-user@ip-10-132-76-170 ~]$ CODEBUILD_IAM_ROLE_ARN=$(
>     aws iam get-role \
>         --role-name ${CODEBUILD_IAM_ROLE_NAME} \
>         --query 'Role.Arn' --output text
> ) \
> && echo ${CODEBUILD_IAM_ROLE_ARN}
arn:aws:iam::999999999999:role/service-role/codebuild-h4b-hands-on-service-role
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMロールにポリシーをアタッチ
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam attach-role-policy \
>     --role-name ${CODEBUILD_IAM_ROLE_NAME} \
>     --policy-arn ${CODEBUILD_IAM_POLICY_ARN}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam attach-role-policy \
>     --role-name ${CODEBUILD_IAM_ROLE_NAME} \
>     --policy-arn arn:aws:iam::aws:policy/${AWS_POLICY_NAME}
```
## 作成
```bash:コマンド
# バケット作成
aws s3api create-bucket \
    --bucket ${CODEBUILD_ARTIFACTSTORE_BUCKET_NAME} \
    --create-bucket-configuration LocationConstraint=${REGION}

# 作成
aws codebuild create-project \
    --name "${CODEBUILD_NAME}" \
    --source "type=CODECOMMIT,location=${CLONEURLHTTP},gitCloneDepth=1,insecureSsl=false,gitSubmodulesConfig={fetchSubmodules=false}" \
    --source-version "refs/heads/master" \
    --artifacts "type=S3,location=${CODEBUILD_ARTIFACTSTORE_BUCKET_NAME},namespaceType=NONE,name=${CODEBUILD_NAME},packaging=NONE,overrideArtifactName=false,encryptionDisabled=false" \
    --environment "type=LINUX_CONTAINER,image=aws/codebuild/amazonlinux2-x86_64-standard:5.0,computeType=BUILD_GENERAL1_SMALL,privilegedMode=false,imagePullCredentialsType=CODEBUILD" \
    --service-role "arn:aws:iam::999999999999:role/service-role/codebuild-h4b-hands-on-service-role" \
    --logs-config "cloudWatchLogs={status=ENABLED},s3Logs={status=DISABLED,encryptionDisabled=false}" \
    --no-cli-pager

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # バケット作成
[cloudshell-user@ip-10-132-76-170 ~]$ aws s3api create-bucket \
>     --bucket ${CODEBUILD_ARTIFACTSTORE_BUCKET_NAME} \
>     --create-bucket-configuration LocationConstraint=${REGION}
{
    "Location": "http://codebuild-h4b-hands-on-artifactstore.s3.amazonaws.com/"
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # 作成
[cloudshell-user@ip-10-132-76-170 ~]$ aws codebuild create-project \
>     --name "${CODEBUILD_NAME}" \
>     --source "type=CODECOMMIT,location=${CLONEURLHTTP},gitCloneDepth=1,insecureSsl=false,gitSubmodulesConfig={fetchSubmodules=false}" \
>     --source-version "refs/heads/master" \
>     --artifacts "type=S3,location=${CODEBUILD_ARTIFACTSTORE_BUCKET_NAME},namespaceType=NONE,name=${CODEBUILD_NAME},packaging=NONE,overrideArtifactName=false,encryptionDisabled=false" \
>     --environment "type=LINUX_CONTAINER,image=aws/codebuild/amazonlinux2-x86_64-standard:5.0,computeType=BUILD_GENERAL1_SMALL,privilegedMode=false,imagePullCredentialsType=CODEBUILD" \
>     --service-role "arn:aws:iam::999999999999:role/service-role/codebuild-h4b-hands-on-service-role" \
>     --logs-config "cloudWatchLogs={status=ENABLED},s3Logs={status=DISABLED,encryptionDisabled=false}" \
>     --no-cli-pager
{
    "project": {
        "name": "h4b-hands-on",
        "arn": "arn:aws:codebuild:ap-northeast-1:999999999999:project/h4b-hands-on",
        "source": {
            "type": "CODECOMMIT",
            "location": "https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/h4b-hands-on",
            "gitCloneDepth": 1,
            "gitSubmodulesConfig": {
                "fetchSubmodules": false
            },
            "insecureSsl": false
        },
        "sourceVersion": "refs/heads/master",
        "artifacts": {
            "type": "S3",
            "location": "codebuild-h4b-hands-on-artifactstore",
            "namespaceType": "NONE",
            "name": "h4b-hands-on",
            "packaging": "NONE",
            "overrideArtifactName": false,
            "encryptionDisabled": false
        },
        "cache": {
            "type": "NO_CACHE"
        },
        "environment": {
            "type": "LINUX_CONTAINER",
            "image": "aws/codebuild/amazonlinux2-x86_64-standard:5.0",
            "computeType": "BUILD_GENERAL1_SMALL",
            "environmentVariables": [],
            "privilegedMode": false,
            "imagePullCredentialsType": "CODEBUILD"
        },
        "serviceRole": "arn:aws:iam::999999999999:role/service-role/codebuild-h4b-hands-on-service-role",
        "timeoutInMinutes": 60,
        "queuedTimeoutInMinutes": 480,
        "encryptionKey": "arn:aws:kms:ap-northeast-1:999999999999:alias/aws/s3",
        "created": "2024-09-14T06:34:05.519000+00:00",
        "lastModified": "2024-09-14T06:34:05.519000+00:00",
        "badge": {
            "badgeEnabled": false
        },
        "logsConfig": {
            "cloudWatchLogs": {
                "status": "ENABLED"
            },
            "s3Logs": {
                "status": "DISABLED",
                "encryptionDisabled": false
            }
        },
        "projectVisibility": "PRIVATE"
    }
}
```
## 確認
```bash:コマンド
# 確認
aws codebuild batch-get-projects \
    --names ${CODEBUILD_NAME} \
    --no-cli-pager

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # 確認
[cloudshell-user@ip-10-132-76-170 ~]$ aws codebuild batch-get-projects \
>     --names ${CODEBUILD_NAME} \
>     --no-cli-pager
{
    "projects": [
        {
            "name": "h4b-hands-on",
            "arn": "arn:aws:codebuild:ap-northeast-1:999999999999:project/h4b-hands-on",
            "source": {
                "type": "CODECOMMIT",
                "location": "https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/h4b-hands-on",
                "gitCloneDepth": 1,
                "gitSubmodulesConfig": {
                    "fetchSubmodules": false
                },
                "insecureSsl": false
            },
            "sourceVersion": "refs/heads/master",
            "artifacts": {
                "type": "S3",
                "location": "codebuild-h4b-hands-on-artifactstore",
                "namespaceType": "NONE",
                "name": "h4b-hands-on",
                "packaging": "NONE",
                "overrideArtifactName": false,
                "encryptionDisabled": false
            },
            "cache": {
                "type": "NO_CACHE"
            },
            "environment": {
                "type": "LINUX_CONTAINER",
                "image": "aws/codebuild/amazonlinux2-x86_64-standard:5.0",
                "computeType": "BUILD_GENERAL1_SMALL",
                "environmentVariables": [],
                "privilegedMode": false,
                "imagePullCredentialsType": "CODEBUILD"
            },
            "serviceRole": "arn:aws:iam::999999999999:role/service-role/codebuild-h4b-hands-on-service-role",
            "timeoutInMinutes": 60,
            "queuedTimeoutInMinutes": 480,
            "encryptionKey": "arn:aws:kms:ap-northeast-1:999999999999:alias/aws/s3",
            "tags": [],
            "created": "2024-09-14T06:34:05.519000+00:00",
            "lastModified": "2024-09-14T06:34:05.519000+00:00",
            "badge": {
                "badgeEnabled": false
            },
            "logsConfig": {
                "cloudWatchLogs": {
                    "status": "ENABLED"
                },
                "s3Logs": {
                    "status": "DISABLED",
                    "encryptionDisabled": false
                }
            },
            "projectVisibility": "PRIVATE"
        }
    ],
    "projectsNotFound": []
}
```
:::note info
以降、Cloud9で実施
:::
## buildspec.yamlの作成
:::note info
CODEBUILD_ARTIFACTSTORE_BUCKET_NAMEは適宜変更
:::
```bash:コマンド
# フォルダの作成
mkdir ~/environment/h4b-hands-on/src

# index.htmlの移動
mv ~/environment/h4b-hands-on/index.html ~/environment/h4b-hands-on/src/

# バケット変数
CODEBUILD_ARTIFACTSTORE_BUCKET_NAME="codebuild-h4b-hands-on-artifactstore" \
&& echo ${CODEBUILD_ARTIFACTSTORE_BUCKET_NAME}

# buildspec.yamlの作成
cat << EOF > buildspec.yaml
version: 0.2

phases:
  build:
    commands:
      - aws deploy push --application-name h4b-app --s3-location s3://${CODEBUILD_ARTIFACTSTORE_BUCKET_NAME}/artifact.zip --source src
artifacts:
  files:
    - '**/*'
  base-directory: src
EOF

```
```bash:出力
admin:~/environment/h4b-hands-on (master) $ # フォルダの作成
admin:~/environment/h4b-hands-on (master) $ mkdir ~/environment/h4b-hands-on/src
admin:~/environment/h4b-hands-on (master) $ 
admin:~/environment/h4b-hands-on (master) $ # index.htmlの移動
admin:~/environment/h4b-hands-on (master) $ mv ~/environment/h4b-hands-on/index.html ~/environment/h4b-hands-on/src/
admin:~/environment/h4b-hands-on (master) $ 
admin:~/environment/h4b-hands-on (master) $ # バケット変数
admin:~/environment/h4b-hands-on (master) $ CODEBUILD_ARTIFACTSTORE_BUCKET_NAME="codebuild-h4b-hands-on-artifactstore" \
> && echo ${CODEBUILD_ARTIFACTSTORE_BUCKET_NAME}
codebuild-h4b-hands-on-artifactstore
admin:~/environment/h4b-hands-on (master) $ 
admin:~/environment/h4b-hands-on (master) $ # buildspec.yamlの作成
admin:~/environment/h4b-hands-on (master) $ cat << EOF > buildspec.yaml
> version: 0.2
> 
> phases:
>   build:
>     commands:
>       - aws deploy push --application-name h4b-app --s3-location s3://${CODEBUILD_ARTIFACTSTORE_BUCKET_NAME}/artifact.zip --source src
> artifacts:
>   files:
>     - '**/*'
>   base-directory: src
> EOF
```
# 06 EC2 インスタンスをデプロイ先とした、CI/CD 環境を構築する【CodeDeploy 編】
:::note info
以降、CloudShellで実施
:::
```bash:コマンド
# ロール名
CODEDEPLOY_IAM_ROLE_NAME="CodeDeployRole" \
&& echo ${CODEDEPLOY_IAM_ROLE_NAME}

# AWS管理ポリシー
AWS_POLICY_NAME="AWSCodeDeployRole" \
&& echo ${AWS_POLICY_NAME}

# 信頼関係ポリシードキュメントの作成
ASSUME_ROLE_POLICY_DOCUMENT=$(cat << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "Service": "codedeploy.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
EOF
) \
&& echo ${ASSUME_ROLE_POLICY_DOCUMENT}

# JSONフォーマットの確認
echo ${ASSUME_ROLE_POLICY_DOCUMENT} | python -m json.tool

# IAMロールの作成
aws iam create-role \
    --role-name ${CODEDEPLOY_IAM_ROLE_NAME} \
    --assume-role-policy-document "${ASSUME_ROLE_POLICY_DOCUMENT}"

# ARN取得
CODEDEPLOY_IAM_ROLE_ARN=$(
    aws iam get-role \
        --role-name ${CODEDEPLOY_IAM_ROLE_NAME} \
        --query 'Role.Arn' --output text
) \
&& echo ${CODEDEPLOY_IAM_ROLE_ARN}

# IAMロールにポリシーをアタッチ
aws iam attach-role-policy \
    --role-name ${CODEDEPLOY_IAM_ROLE_NAME} \
    --policy-arn arn:aws:iam::aws:policy/service-role/${AWS_POLICY_NAME}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # ロール名
[cloudshell-user@ip-10-132-76-170 ~]$ CODEDEPLOY_IAM_ROLE_NAME="CodeDeployRole" \
> && echo ${CODEDEPLOY_IAM_ROLE_NAME}
CodeDeployRole
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # AWS管理ポリシー
[cloudshell-user@ip-10-132-76-170 ~]$ AWS_POLICY_NAME="AWSCodeDeployRole" \
> && echo ${AWS_POLICY_NAME}
AWSCodeDeployRole
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # 信頼関係ポリシードキュメントの作成
[cloudshell-user@ip-10-132-76-170 ~]$ ASSUME_ROLE_POLICY_DOCUMENT=$(cat << EOF
> {
>     "Version": "2012-10-17",
>     "Statement": [
>         {
>             "Sid": "",
>             "Effect": "Allow",
>             "Principal": {
>                 "Service": "codedeploy.amazonaws.com"
>             },
>             "Action": "sts:AssumeRole"
>         }
>     ]
> }
> EOF
> ) \
> && echo ${ASSUME_ROLE_POLICY_DOCUMENT}
{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": "codedeploy.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-76-170 ~]$ echo ${ASSUME_ROLE_POLICY_DOCUMENT} | python -m json.tool
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "Service": "codedeploy.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMロールの作成
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam create-role \
>     --role-name ${CODEDEPLOY_IAM_ROLE_NAME} \
>     --assume-role-policy-document "${ASSUME_ROLE_POLICY_DOCUMENT}"
{
    "Role": {
        "Path": "/",
        "RoleName": "CodeDeployRole",
        "RoleId": "AROAWFKRCMKO52G73R6PL",
        "Arn": "arn:aws:iam::999999999999:role/CodeDeployRole",
        "CreateDate": "2024-09-14T06:35:52+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Sid": "",
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "codedeploy.amazonaws.com"
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        }
    }
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ARN取得
[cloudshell-user@ip-10-132-76-170 ~]$ CODEDEPLOY_IAM_ROLE_ARN=$(
>     aws iam get-role \
>         --role-name ${CODEDEPLOY_IAM_ROLE_NAME} \
>         --query 'Role.Arn' --output text
> ) \
> && echo ${CODEDEPLOY_IAM_ROLE_ARN}
arn:aws:iam::999999999999:role/CodeDeployRole
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMロールにポリシーをアタッチ
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam attach-role-policy \
>     --role-name ${CODEDEPLOY_IAM_ROLE_NAME} \
>     --policy-arn arn:aws:iam::aws:policy/service-role/${AWS_POLICY_NAME}
```
## CodeDeploy
### アプリケーション
```bash:コマンド
# 変数
CODEDEPLOY_APP_NAME="h4b-app" \
&& echo ${CODEDEPLOY_APP_NAME}

# 作成
aws deploy create-application \
    --application-name ${CODEDEPLOY_APP_NAME} \
    --compute-platform Server

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # 変数
[cloudshell-user@ip-10-132-76-170 ~]$ CODEDEPLOY_APP_NAME="h4b-app" \
> && echo ${CODEDEPLOY_APP_NAME}
h4b-app
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # 作成
[cloudshell-user@ip-10-132-76-170 ~]$ aws deploy create-application \
>     --application-name ${CODEDEPLOY_APP_NAME} \
>     --compute-platform Server
{
    "applicationId": "065b91d9-744e-4001-adec-6e3d7745cdcd"
}
```
### デプロイグループ
```bash:コマンド
# 変数
CODEDEPLOY_GROUP_NAME="Web" \
&& echo ${CODEDEPLOY_GROUP_NAME}

# 作成
aws deploy create-deployment-group \
    --application-name ${CODEDEPLOY_APP_NAME} \
    --deployment-group-name ${CODEDEPLOY_GROUP_NAME} \
    --service-role-arn ${CODEDEPLOY_IAM_ROLE_ARN} \
    --deployment-config-name CodeDeployDefault.AllAtOnce \
    --ec2-tag-filters Key=Name,Value=Web,Type=KEY_AND_VALUE

# 確認
aws deploy get-deployment-group \
    --application-name ${CODEDEPLOY_APP_NAME} \
    --deployment-group-name ${CODEDEPLOY_GROUP_NAME}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # 変数
[cloudshell-user@ip-10-132-76-170 ~]$ CODEDEPLOY_GROUP_NAME="Web" \
> && echo ${CODEDEPLOY_GROUP_NAME}
Web
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # 作成
[cloudshell-user@ip-10-132-76-170 ~]$ aws deploy create-deployment-group \
>     --application-name ${CODEDEPLOY_APP_NAME} \
>     --deployment-group-name ${CODEDEPLOY_GROUP_NAME} \
>     --service-role-arn ${CODEDEPLOY_IAM_ROLE_ARN} \
>     --deployment-config-name CodeDeployDefault.AllAtOnce \
>     --ec2-tag-filters Key=Name,Value=Web,Type=KEY_AND_VALUE
{
    "deploymentGroupId": "e6ad5cde-6789-42bd-8cad-23b5fedc7703"
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # 確認
[cloudshell-user@ip-10-132-76-170 ~]$ aws deploy get-deployment-group \
>     --application-name ${CODEDEPLOY_APP_NAME} \
>     --deployment-group-name ${CODEDEPLOY_GROUP_NAME}
{
    "deploymentGroupInfo": {
        "applicationName": "h4b-app",
        "deploymentGroupId": "e6ad5cde-6789-42bd-8cad-23b5fedc7703",
        "deploymentGroupName": "Web",
        "deploymentConfigName": "CodeDeployDefault.AllAtOnce",
        "ec2TagFilters": [
            {
                "Key": "Name",
                "Value": "Web",
                "Type": "KEY_AND_VALUE"
            }
        ],
        "onPremisesInstanceTagFilters": [],
        "autoScalingGroups": [],
        "serviceRoleArn": "arn:aws:iam::999999999999:role/CodeDeployRole",
        "triggerConfigurations": [],
        "deploymentStyle": {
            "deploymentType": "IN_PLACE",
            "deploymentOption": "WITHOUT_TRAFFIC_CONTROL"
        },
        "outdatedInstancesStrategy": "UPDATE",
        "computePlatform": "Server",
        "terminationHookEnabled": false
    }
}
```
:::note info
以降、Cloud9で実施
:::
## appspec.ymlの作成
```bash:コマンド
cat << EOF > src/appspec.yml
version: 0.0
os: linux
files:
  - source: index.html
    destination: /var/www/html/
EOF

```
```bash:出力
admin:~/environment/h4b-hands-on (master) $ cat << EOF > src/appspec.yml
> version: 0.0
> os: linux
> files:
>   - source: index.html
>     destination: /var/www/html/
> EOF
```
## リポジトリの更新
```bash:コマンド
git add -A
git commit -m "fix."
git push origin master

```
```bash:出力
admin:~/environment/h4b-hands-on (master) $ git add -A
admin:~/environment/h4b-hands-on (master) $ git commit -m "fix."
[master 6457444] fix.
 3 files changed, 15 insertions(+)
 create mode 100644 buildspec.yaml
 create mode 100644 src/appspec.yml
 rename index.html => src/index.html (100%)
admin:~/environment/h4b-hands-on (master) $ git push origin master
Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (5/5), 591 bytes | 591.00 KiB/s, done.
Total 5 (delta 0), reused 0 (delta 0), pack-reused 0
remote: Validating objects: 100%
To https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/h4b-hands-on
   8cb8648..6457444  master -> master
```
:::note info
以降、CloudShellで実施
:::
## ビルドプロジェクトの開始
### 開始
```bash:コマンド
aws codebuild start-build \
    --project-name ${CODEBUILD_NAME} \
    --no-cli-pager

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ aws codebuild start-build \
>     --project-name ${CODEBUILD_NAME} \
>     --no-cli-pager
{
    "build": {
        "id": "h4b-hands-on:b0350b03-06ed-48f6-971d-dcbfa6ca8837",
        "arn": "arn:aws:codebuild:ap-northeast-1:999999999999:build/h4b-hands-on:b0350b03-06ed-48f6-971d-dcbfa6ca8837",
        "buildNumber": 1,
        "startTime": "2024-09-14T06:40:44.235000+00:00",
        "currentPhase": "QUEUED",
        "buildStatus": "IN_PROGRESS",
        "sourceVersion": "refs/heads/master",
        "projectName": "h4b-hands-on",
        "phases": [
            {
                "phaseType": "SUBMITTED",
                "phaseStatus": "SUCCEEDED",
                "startTime": "2024-09-14T06:40:44.235000+00:00",
                "endTime": "2024-09-14T06:40:44.307000+00:00",
                "durationInSeconds": 0
            },
            {
                "phaseType": "QUEUED",
                "startTime": "2024-09-14T06:40:44.307000+00:00"
            }
        ],
        "source": {
            "type": "CODECOMMIT",
            "location": "https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/h4b-hands-on",
            "gitCloneDepth": 1,
            "gitSubmodulesConfig": {
                "fetchSubmodules": false
            },
            "insecureSsl": false
        },
        "secondarySources": [],
        "secondarySourceVersions": [],
        "artifacts": {
            "location": "arn:aws:s3:::codebuild-h4b-hands-on-artifactstore/h4b-hands-on",
            "overrideArtifactName": false,
            "encryptionDisabled": false
        },
        "cache": {
            "type": "NO_CACHE"
        },
        "environment": {
            "type": "LINUX_CONTAINER",
            "image": "aws/codebuild/amazonlinux2-x86_64-standard:5.0",
            "computeType": "BUILD_GENERAL1_SMALL",
            "environmentVariables": [],
            "privilegedMode": false,
            "imagePullCredentialsType": "CODEBUILD"
        },
        "serviceRole": "arn:aws:iam::999999999999:role/service-role/codebuild-h4b-hands-on-service-role",
        "logs": {
            "deepLink": "https://console.aws.amazon.com/cloudwatch/home?region=ap-northeast-1#logsV2:log-groups",
            "cloudWatchLogsArn": "arn:aws:logs:ap-northeast-1:999999999999:log-group:null:log-stream:null",
            "cloudWatchLogs": {
                "status": "ENABLED"
            },
            "s3Logs": {
                "status": "DISABLED",
                "encryptionDisabled": false
            }
        },
        "timeoutInMinutes": 45,
        "queuedTimeoutInMinutes": 480,
        "buildComplete": false,
        "initiator": "admin",
        "encryptionKey": "arn:aws:kms:ap-northeast-1:999999999999:alias/aws/s3"
    }
}
```
### ビルドの詳細を取得
```bash:コマンド
# 最近のビルドIDを取得
BUILD_ID=$(
    aws codebuild list-builds \
        --sort-order DESCENDING \
        --query 'ids[0]' \
        --output text
) \
&& echo ${BUILD_ID}

# ビルドの詳細を取得
aws codebuild batch-get-builds \
    --ids ${BUILD_ID} \
    --no-cli-pager

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # 最近のビルドIDを取得
[cloudshell-user@ip-10-132-76-170 ~]$ BUILD_ID=$(
>     aws codebuild list-builds \
>         --sort-order DESCENDING \
>         --query 'ids[0]' \
>         --output text
> ) \
> && echo ${BUILD_ID}
h4b-hands-on:b0350b03-06ed-48f6-971d-dcbfa6ca8837
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ビルドの詳細を取得
[cloudshell-user@ip-10-132-76-170 ~]$ aws codebuild batch-get-builds \
>     --ids ${BUILD_ID} \
>     --no-cli-pager
{
    "builds": [
        {
            "id": "h4b-hands-on:b0350b03-06ed-48f6-971d-dcbfa6ca8837",
            "arn": "arn:aws:codebuild:ap-northeast-1:999999999999:build/h4b-hands-on:b0350b03-06ed-48f6-971d-dcbfa6ca8837",
            "buildNumber": 1,
            "startTime": "2024-09-14T06:40:44.235000+00:00",
            "currentPhase": "BUILD",
            "buildStatus": "IN_PROGRESS",
            "sourceVersion": "refs/heads/master",
            "resolvedSourceVersion": "64574445a2585cc5ccba54602b1c51c5dc14cdd5",
            "projectName": "h4b-hands-on",
            "phases": [
                {
                    "phaseType": "SUBMITTED",
                    "phaseStatus": "SUCCEEDED",
                    "startTime": "2024-09-14T06:40:44.235000+00:00",
                    "endTime": "2024-09-14T06:40:44.307000+00:00",
                    "durationInSeconds": 0
                },
                {
                    "phaseType": "QUEUED",
                    "phaseStatus": "SUCCEEDED",
                    "startTime": "2024-09-14T06:40:44.307000+00:00",
                    "endTime": "2024-09-14T06:40:45.057000+00:00",
                    "durationInSeconds": 0
                },
                {
                    "phaseType": "PROVISIONING",
                    "phaseStatus": "SUCCEEDED",
                    "startTime": "2024-09-14T06:40:45.057000+00:00",
                    "endTime": "2024-09-14T06:40:50.299000+00:00",
                    "durationInSeconds": 5,
                    "contexts": [
                        {
                            "statusCode": "",
                            "message": ""
                        }
                    ]
                },
                {
                    "phaseType": "DOWNLOAD_SOURCE",
                    "phaseStatus": "SUCCEEDED",
                    "startTime": "2024-09-14T06:40:50.299000+00:00",
                    "endTime": "2024-09-14T06:40:58.931000+00:00",
                    "durationInSeconds": 8,
                    "contexts": [
                        {
                            "statusCode": "",
                            "message": ""
                        }
                    ]
                },
                {
                    "phaseType": "INSTALL",
                    "phaseStatus": "SUCCEEDED",
                    "startTime": "2024-09-14T06:40:58.931000+00:00",
                    "endTime": "2024-09-14T06:40:58.985000+00:00",
                    "durationInSeconds": 0,
                    "contexts": [
                        {
                            "statusCode": "",
                            "message": ""
                        }
                    ]
                },
                {
                    "phaseType": "PRE_BUILD",
                    "phaseStatus": "SUCCEEDED",
                    "startTime": "2024-09-14T06:40:58.985000+00:00",
                    "endTime": "2024-09-14T06:40:59.031000+00:00",
                    "durationInSeconds": 0,
                    "contexts": [
                        {
                            "statusCode": "",
                            "message": ""
                        }
                    ]
                },
                {
                    "phaseType": "BUILD",
                    "startTime": "2024-09-14T06:40:59.031000+00:00"
                }
            ],
            "source": {
                "type": "CODECOMMIT",
                "location": "https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/h4b-hands-on",
                "gitCloneDepth": 1,
                "gitSubmodulesConfig": {
                    "fetchSubmodules": false
                },
                "insecureSsl": false
            },
            "secondarySources": [],
            "secondarySourceVersions": [],
            "artifacts": {
                "location": "arn:aws:s3:::codebuild-h4b-hands-on-artifactstore/h4b-hands-on",
                "overrideArtifactName": false,
                "encryptionDisabled": false
            },
            "cache": {
                "type": "NO_CACHE"
            },
            "environment": {
                "type": "LINUX_CONTAINER",
                "image": "aws/codebuild/amazonlinux2-x86_64-standard:5.0",
                "computeType": "BUILD_GENERAL1_SMALL",
                "environmentVariables": [],
                "privilegedMode": false,
                "imagePullCredentialsType": "CODEBUILD"
            },
            "serviceRole": "arn:aws:iam::999999999999:role/service-role/codebuild-h4b-hands-on-service-role",
            "logs": {
                "groupName": "/aws/codebuild/h4b-hands-on",
                "streamName": "b0350b03-06ed-48f6-971d-dcbfa6ca8837",
                "deepLink": "https://console.aws.amazon.com/cloudwatch/home?region=ap-northeast-1#logsV2:log-groups/log-group/$252Faws$252Fcodebuild$252Fh4b-hands-on/log-events/b0350b03-06ed-48f6-971d-dcbfa6ca8837",
                "cloudWatchLogsArn": "arn:aws:logs:ap-northeast-1:999999999999:log-group:/aws/codebuild/h4b-hands-on:log-stream:b0350b03-06ed-48f6-971d-dcbfa6ca8837",
                "cloudWatchLogs": {
                    "status": "ENABLED"
                },
                "s3Logs": {
                    "status": "DISABLED",
                    "encryptionDisabled": false
                }
            },
            "timeoutInMinutes": 45,
            "queuedTimeoutInMinutes": 480,
            "buildComplete": false,
            "initiator": "admin",
            "encryptionKey": "arn:aws:kms:ap-northeast-1:999999999999:alias/aws/s3"
        }
    ],
    "buildsNotFound": []
}
```
### テールログの確認
```bash:コマンド
# ビルドログの確認
LOG_GROUP_NAME="/aws/codebuild/${CODEBUILD_NAME}" \
&& echo ${LOG_GROUP_NAME}

LOG_STREAM_NAME=$(
    aws logs describe-log-streams \
        --log-group-name ${LOG_GROUP_NAME} \
        --order-by LastEventTime \
        --descending \
        --limit 1 \
        --query 'logStreams[0].logStreamName' \
        --output text
) \
&& echo ${LOG_STREAM_NAME}

aws logs get-log-events \
    --log-group-name ${LOG_GROUP_NAME} \
    --log-stream-name ${LOG_STREAM_NAME} \
    --output text \
    --no-cli-pager

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # ビルドログの確認
[cloudshell-user@ip-10-132-76-170 ~]$ LOG_GROUP_NAME="/aws/codebuild/${CODEBUILD_NAME}" \
> && echo ${LOG_GROUP_NAME}
/aws/codebuild/h4b-hands-on
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ LOG_STREAM_NAME=$(
>     aws logs describe-log-streams \
>         --log-group-name ${LOG_GROUP_NAME} \
>         --order-by LastEventTime \
>         --descending \
>         --limit 1 \
>         --query 'logStreams[0].logStreamName' \
>         --output text
> ) \
> && echo ${LOG_STREAM_NAME}
b0350b03-06ed-48f6-971d-dcbfa6ca8837
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ aws logs get-log-events \
>     --log-group-name ${LOG_GROUP_NAME} \
>     --log-stream-name ${LOG_STREAM_NAME} \
>     --output text \
>     --no-cli-pager
b/38497688623292670323638309851495241895033887558412140544/s    f/38497688884835810012005458069591474214596368678172688409/s
EVENTS  1726296062364   [Container] 2024/09/14 06:40:50.109700 Running on CodeBuild On-demand
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:50.109746 Waiting for agent ping
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:50.311161 Waiting for DOWNLOAD_SOURCE
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:58.273967 Phase is DOWNLOAD_SOURCE
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:58.322286 CODEBUILD_SRC_DIR=/codebuild/output/src280942417/src/git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/h4b-hands-on
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:58.322795 YAML location is /codebuild/output/src280942417/src/git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/h4b-hands-on/buildspec.yaml
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:58.324406 Not setting HTTP client timeout for source type codecommit
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:58.324610 Processing environment variables
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:58.548234 No runtime version selected in buildspec.
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:58.578527 Moving to directory /codebuild/output/src280942417/src/git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/h4b-hands-on
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:58.581813 Unable to initialize cache download: no paths specified to be cached
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:58.778875 Configuring ssm agent with target id: codebuild:b0350b03-06ed-48f6-971d-dcbfa6ca8837
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:58.815424 Successfully updated ssm agent configuration
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:58.815856 Registering with agent
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:58.862897 Phases found in YAML: 1
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:58.862922  BUILD: 1 commands
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:58.863528 Phase complete: DOWNLOAD_SOURCE State: SUCCEEDED
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:58.863552 Phase context status code:  Message: 
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:58.952063 Entering phase INSTALL
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:58.959279 Phase complete: INSTALL State: SUCCEEDED
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:58.959309 Phase context status code:  Message: 
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:59.003793 Entering phase PRE_BUILD
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:59.007236 Phase complete: PRE_BUILD State: SUCCEEDED
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:59.007255 Phase context status code:  Message: 
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:59.049948 Entering phase BUILD
        1726296062332
EVENTS  1726296062364   [Container] 2024/09/14 06:40:59.094525 Running command aws deploy push --application-name h4b-app --s3-location s3://codebuild-h4b-hands-on-artifactstore/artifact.zip --source src
        1726296062332
EVENTS  1726296074081   To deploy with this revision, run:
        1726296074060
EVENTS  1726296074081   aws deploy create-deployment --application-name h4b-app --s3-location bucket=codebuild-h4b-hands-on-artifactstore,key=artifact.zip,bundleType=zip,eTag=8dc3595d7c932fd7bf4520d570e4dea5 --deployment-group-name <deployment-group-name> --deployment-config-name <deployment-config-name> --description <description>
        1726296074060
EVENTS  1726296074081
        1726296074060
EVENTS  1726296074081   [Container] 2024/09/14 06:41:13.560456 Phase complete: BUILD State: SUCCEEDED
        1726296074060
EVENTS  1726296074081   [Container] 2024/09/14 06:41:13.560478 Phase context status code:  Message: 
        1726296074060
EVENTS  1726296074081   [Container] 2024/09/14 06:41:13.594475 Entering phase POST_BUILD
        1726296074060
EVENTS  1726296074081   [Container] 2024/09/14 06:41:13.596228 Phase complete: POST_BUILD State: SUCCEEDED
        1726296074060
EVENTS  1726296074081   [Container] 2024/09/14 06:41:13.596246 Phase context status code:  Message: 
        1726296074060
EVENTS  1726296074081   [Container] 2024/09/14 06:41:13.694181 Expanding base directory path: src
        1726296074060
EVENTS  1726296074081   [Container] 2024/09/14 06:41:13.700155 Assembling file list
        1726296074060
EVENTS  1726296074081   [Container] 2024/09/14 06:41:13.700171 Expanding src
        1726296074060
EVENTS  1726296074081   [Container] 2024/09/14 06:41:13.705504 Expanding file paths for base directory src
        1726296074060
EVENTS  1726296074081   [Container] 2024/09/14 06:41:13.705517 Assembling file list
        1726296074060
EVENTS  1726296074081   [Container] 2024/09/14 06:41:13.705521 Expanding **/*
        1726296074060
EVENTS  1726296074081   [Container] 2024/09/14 06:41:13.710280 Found 2 file(s)
        1726296074060
EVENTS  1726296074081   [Container] 2024/09/14 06:41:13.711837 Set report auto-discover timeout to 5 seconds
        1726296074060
EVENTS  1726296074081   [Container] 2024/09/14 06:41:13.711867 Expanding base directory path:  .
        1726296074060
EVENTS  1726296074081   [Container] 2024/09/14 06:41:13.716154 Assembling file list
        1726296074060
EVENTS  1726296074081   [Container] 2024/09/14 06:41:13.716167 Expanding .
        1726296074060
EVENTS  1726296074081   [Container] 2024/09/14 06:41:13.720291 Expanding file paths for base directory .
        1726296074060
EVENTS  1726296074081   [Container] 2024/09/14 06:41:13.720304 Assembling file list
        1726296074060
EVENTS  1726296074081   [Container] 2024/09/14 06:41:13.720308 Expanding **/*
        1726296074060
EVENTS  1726296074081   [Container] 2024/09/14 06:41:13.723792 No matching auto-discover report paths found
        1726296074060
EVENTS  1726296074081   [Container] 2024/09/14 06:41:13.723810 Report auto-discover file discovery took 0.011973 seconds
        1726296074060
EVENTS  1726296074081   [Container] 2024/09/14 06:41:13.723826 Phase complete: UPLOAD_ARTIFACTS State: SUCCEEDED
        1726296074060
EVENTS  1726296074081   [Container] 2024/09/14 06:41:13.723834 Phase context status code:  Message: 
        1726296074060
```
# 07 EC2 インスタンスをデプロイ先とした、CI/CD 環境を構築する【CodePipeline 編】
## 変数
```bash:コマンド
# パイプライン名
PIPELINE_2_NAME="h4b-hands-on-ec2" \
&& echo ${PIPELINE_2_NAME}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # パイプライン名
[cloudshell-user@ip-10-132-76-170 ~]$ PIPELINE_2_NAME="h4b-hands-on-ec2" \
> && echo ${PIPELINE_2_NAME}
h4b-hands-on-ec2
```
## パイプライン定義ファイル
```bash:コマンド
# パイプライン定義ファイル
PIPELINE_2_JSON=$(cat << EOF
{
    "pipeline": {
        "name": "${PIPELINE_2_NAME}",
        "roleArn": "${PIPELINE_IAM_ROLE_ARN}",
        "artifactStore": {
            "type": "S3",
            "location": "${ARTIFACTSTORE_BUCKET_NAME}"
        },
        "stages": [
            {
                "name": "Source",
                "actions": [
                    {
                        "name": "Source",
                        "actionTypeId": {
                            "category": "Source",
                            "owner": "AWS",
                            "provider": "CodeCommit",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "BranchName": "master",
                            "OutputArtifactFormat": "CODE_ZIP",
                            "PollForSourceChanges": "false",
                            "RepositoryName": "${REPOSITORY_NAME}"
                        },
                        "outputArtifacts": [
                            {
                                "name": "SourceArtifact"
                            }
                        ],
                        "inputArtifacts": [],
                        "region": "ap-northeast-1",
                        "namespace": "SourceVariables"
                    }
                ]
            },
            {
                "name": "Build",
                "actions": [
                    {
                        "name": "Build",
                        "actionTypeId": {
                            "category": "Build",
                            "owner": "AWS",
                            "provider": "CodeBuild",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "ProjectName": "${CODEBUILD_NAME}"
                        },
                        "outputArtifacts": [
                            {
                                "name": "BuildArtifact"
                            }
                        ],
                        "inputArtifacts": [
                            {
                                "name": "SourceArtifact"
                            }
                        ],
                        "region": "ap-northeast-1",
                        "namespace": "BuildVariables"
                    }
                ]
            },
            {
                "name": "Deploy",
                "actions": [
                    {
                        "name": "Deploy",
                        "actionTypeId": {
                            "category": "Deploy",
                            "owner": "AWS",
                            "provider": "CodeDeploy",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "ApplicationName": "${CODEDEPLOY_APP_NAME}",
                            "DeploymentGroupName": "${CODEDEPLOY_GROUP_NAME}"
                        },
                        "outputArtifacts": [],
                        "inputArtifacts": [
                            {
                                "name": "BuildArtifact"
                            }
                        ],
                        "region": "ap-northeast-1",
                        "namespace": "DeployVariables"
                    }
                ]
            }
        ],
        "version": 1,
        "executionMode": "QUEUED",
        "pipelineType": "V2"
    }
}
EOF
) \
&& echo ${PIPELINE_2_JSON}

# JSONフォーマットの確認
echo ${PIPELINE_2_JSON} | python -m json.tool

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # パイプライン定義ファイル
[cloudshell-user@ip-10-132-76-170 ~]$ PIPELINE_2_JSON=$(cat << EOF
> {
>     "pipeline": {
>         "name": "${PIPELINE_2_NAME}",
>         "roleArn": "${PIPELINE_IAM_ROLE_ARN}",
>         "artifactStore": {
>             "type": "S3",
>             "location": "${ARTIFACTSTORE_BUCKET_NAME}"
>         },
>         "stages": [
>             {
>                 "name": "Source",
>                 "actions": [
>                     {
>                         "name": "Source",
>                         "actionTypeId": {
>                             "category": "Source",
>                             "owner": "AWS",
>                             "provider": "CodeCommit",
>                             "version": "1"
>                         },
>                         "runOrder": 1,
>                         "configuration": {
>                             "BranchName": "master",
>                             "OutputArtifactFormat": "CODE_ZIP",
>                             "PollForSourceChanges": "false",
>                             "RepositoryName": "${REPOSITORY_NAME}"
>                         },
>                         "outputArtifacts": [
>                             {
>                                 "name": "SourceArtifact"
>                             }
>                         ],
>                         "inputArtifacts": [],
>                         "region": "ap-northeast-1",
>                         "namespace": "SourceVariables"
>                     }
>                 ]
>             },
>             {
>                 "name": "Build",
>                 "actions": [
>                     {
>                         "name": "Build",
>                         "actionTypeId": {
>                             "category": "Build",
>                             "owner": "AWS",
>                             "provider": "CodeBuild",
>                             "version": "1"
>                         },
>                         "runOrder": 1,
>                         "configuration": {
>                             "ProjectName": "${CODEBUILD_NAME}"
>                         },
>                         "outputArtifacts": [
>                             {
>                                 "name": "BuildArtifact"
>                             }
>                         ],
>                         "inputArtifacts": [
>                             {
>                                 "name": "SourceArtifact"
>                             }
>                         ],
>                         "region": "ap-northeast-1",
>                         "namespace": "BuildVariables"
>                     }
>                 ]
>             },
>             {
>                 "name": "Deploy",
>                 "actions": [
>                     {
>                         "name": "Deploy",
>                         "actionTypeId": {
>                             "category": "Deploy",
>                             "owner": "AWS",
>                             "provider": "CodeDeploy",
>                             "version": "1"
>                         },
>                         "runOrder": 1,
>                         "configuration": {
>                             "ApplicationName": "${CODEDEPLOY_APP_NAME}",
>                             "DeploymentGroupName": "${CODEDEPLOY_GROUP_NAME}"
>                         },
>                         "outputArtifacts": [],
>                         "inputArtifacts": [
>                             {
>                                 "name": "BuildArtifact"
>                             }
>                         ],
>                         "region": "ap-northeast-1",
>                         "namespace": "DeployVariables"
>                     }
>                 ]
>             }
>         ],
>         "version": 1,
>         "executionMode": "QUEUED",
>         "pipelineType": "V2"
>     }
> }
> EOF
> ) \
> && echo ${PIPELINE_2_JSON}
{ "pipeline": { "name": "h4b-hands-on-ec2", "roleArn": "arn:aws:iam::999999999999:role/service-role/AWSCodePipelineServiceRole-ap-northeast-1", "artifactStore": { "type": "S3", "location": "codepipeline-ap-northeast-1-artifactstore-20240914" }, "stages": [ { "name": "Source", "actions": [ { "name": "Source", "actionTypeId": { "category": "Source", "owner": "AWS", "provider": "CodeCommit", "version": "1" }, "runOrder": 1, "configuration": { "BranchName": "master", "OutputArtifactFormat": "CODE_ZIP", "PollForSourceChanges": "false", "RepositoryName": "h4b-hands-on" }, "outputArtifacts": [ { "name": "SourceArtifact" } ], "inputArtifacts": [], "region": "ap-northeast-1", "namespace": "SourceVariables" } ] }, { "name": "Build", "actions": [ { "name": "Build", "actionTypeId": { "category": "Build", "owner": "AWS", "provider": "CodeBuild", "version": "1" }, "runOrder": 1, "configuration": { "ProjectName": "h4b-hands-on" }, "outputArtifacts": [ { "name": "BuildArtifact" } ], "inputArtifacts": [ { "name": "SourceArtifact" } ], "region": "ap-northeast-1", "namespace": "BuildVariables" } ] }, { "name": "Deploy", "actions": [ { "name": "Deploy", "actionTypeId": { "category": "Deploy", "owner": "AWS", "provider": "CodeDeploy", "version": "1" }, "runOrder": 1, "configuration": { "ApplicationName": "h4b-app", "DeploymentGroupName": "Web" }, "outputArtifacts": [], "inputArtifacts": [ { "name": "BuildArtifact" } ], "region": "ap-northeast-1", "namespace": "DeployVariables" } ] } ], "version": 1, "executionMode": "QUEUED", "pipelineType": "V2" } }
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-76-170 ~]$ echo ${PIPELINE_2_JSON} | python -m json.tool
{
    "pipeline": {
        "name": "h4b-hands-on-ec2",
        "roleArn": "arn:aws:iam::999999999999:role/service-role/AWSCodePipelineServiceRole-ap-northeast-1",
        "artifactStore": {
            "type": "S3",
            "location": "codepipeline-ap-northeast-1-artifactstore-20240914"
        },
        "stages": [
            {
                "name": "Source",
                "actions": [
                    {
                        "name": "Source",
                        "actionTypeId": {
                            "category": "Source",
                            "owner": "AWS",
                            "provider": "CodeCommit",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "BranchName": "master",
                            "OutputArtifactFormat": "CODE_ZIP",
                            "PollForSourceChanges": "false",
                            "RepositoryName": "h4b-hands-on"
                        },
                        "outputArtifacts": [
                            {
                                "name": "SourceArtifact"
                            }
                        ],
                        "inputArtifacts": [],
                        "region": "ap-northeast-1",
                        "namespace": "SourceVariables"
                    }
                ]
            },
            {
                "name": "Build",
                "actions": [
                    {
                        "name": "Build",
                        "actionTypeId": {
                            "category": "Build",
                            "owner": "AWS",
                            "provider": "CodeBuild",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "ProjectName": "h4b-hands-on"
                        },
                        "outputArtifacts": [
                            {
                                "name": "BuildArtifact"
                            }
                        ],
                        "inputArtifacts": [
                            {
                                "name": "SourceArtifact"
                            }
                        ],
                        "region": "ap-northeast-1",
                        "namespace": "BuildVariables"
                    }
                ]
            },
            {
                "name": "Deploy",
                "actions": [
                    {
                        "name": "Deploy",
                        "actionTypeId": {
                            "category": "Deploy",
                            "owner": "AWS",
                            "provider": "CodeDeploy",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "ApplicationName": "h4b-app",
                            "DeploymentGroupName": "Web"
                        },
                        "outputArtifacts": [],
                        "inputArtifacts": [
                            {
                                "name": "BuildArtifact"
                            }
                        ],
                        "region": "ap-northeast-1",
                        "namespace": "DeployVariables"
                    }
                ]
            }
        ],
        "version": 1,
        "executionMode": "QUEUED",
        "pipelineType": "V2"
    }
}
```
## パイプラインの作成
### 作成
```bash:コマンド
aws codepipeline create-pipeline \
    --cli-input-json "${PIPELINE_2_JSON}" \
    --no-cli-pager

# ARN取得
PIPELINE_2_ARN=$(
    aws codepipeline get-pipeline \
        --name ${PIPELINE_2_NAME} \
        --query metadata.pipelineArn \
        --output text
) \
&& echo ${PIPELINE_2_ARN}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ aws codepipeline create-pipeline \
>     --cli-input-json "${PIPELINE_2_JSON}" \
>     --no-cli-pager
{
    "pipeline": {
        "name": "h4b-hands-on-ec2",
        "roleArn": "arn:aws:iam::999999999999:role/service-role/AWSCodePipelineServiceRole-ap-northeast-1",
        "artifactStore": {
            "type": "S3",
            "location": "codepipeline-ap-northeast-1-artifactstore-20240914"
        },
        "stages": [
            {
                "name": "Source",
                "actions": [
                    {
                        "name": "Source",
                        "actionTypeId": {
                            "category": "Source",
                            "owner": "AWS",
                            "provider": "CodeCommit",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "BranchName": "master",
                            "OutputArtifactFormat": "CODE_ZIP",
                            "PollForSourceChanges": "false",
                            "RepositoryName": "h4b-hands-on"
                        },
                        "outputArtifacts": [
                            {
                                "name": "SourceArtifact"
                            }
                        ],
                        "inputArtifacts": [],
                        "region": "ap-northeast-1",
                        "namespace": "SourceVariables"
                    }
                ]
            },
            {
                "name": "Build",
                "actions": [
                    {
                        "name": "Build",
                        "actionTypeId": {
                            "category": "Build",
                            "owner": "AWS",
                            "provider": "CodeBuild",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "ProjectName": "h4b-hands-on"
                        },
                        "outputArtifacts": [
                            {
                                "name": "BuildArtifact"
                            }
                        ],
                        "inputArtifacts": [
                            {
                                "name": "SourceArtifact"
                            }
                        ],
                        "region": "ap-northeast-1",
                        "namespace": "BuildVariables"
                    }
                ]
            },
            {
                "name": "Deploy",
                "actions": [
                    {
                        "name": "Deploy",
                        "actionTypeId": {
                            "category": "Deploy",
                            "owner": "AWS",
                            "provider": "CodeDeploy",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "ApplicationName": "h4b-app",
                            "DeploymentGroupName": "Web"
                        },
                        "outputArtifacts": [],
                        "inputArtifacts": [
                            {
                                "name": "BuildArtifact"
                            }
                        ],
                        "region": "ap-northeast-1",
                        "namespace": "DeployVariables"
                    }
                ]
            }
        ],
        "version": 1,
        "executionMode": "QUEUED",
        "pipelineType": "V2"
    }
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ARN取得
[cloudshell-user@ip-10-132-76-170 ~]$ PIPELINE_2_ARN=$(
>     aws codepipeline get-pipeline \
>         --name ${PIPELINE_2_NAME} \
>         --query metadata.pipelineArn \
>         --output text
> ) \
> && echo ${PIPELINE_2_ARN}
arn:aws:codepipeline:ap-northeast-1:999999999999:h4b-hands-on-ec2
```
### 確認
```bash:コマンド
# 詳細確認
aws codepipeline get-pipeline \
    --name ${PIPELINE_2_NAME} \
    --no-cli-pager

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # 詳細確認
[cloudshell-user@ip-10-132-76-170 ~]$ aws codepipeline get-pipeline \
>     --name ${PIPELINE_2_NAME} \
>     --no-cli-pager
{
    "pipeline": {
        "name": "h4b-hands-on-ec2",
        "roleArn": "arn:aws:iam::999999999999:role/service-role/AWSCodePipelineServiceRole-ap-northeast-1",
        "artifactStore": {
            "type": "S3",
            "location": "codepipeline-ap-northeast-1-artifactstore-20240914"
        },
        "stages": [
            {
                "name": "Source",
                "actions": [
                    {
                        "name": "Source",
                        "actionTypeId": {
                            "category": "Source",
                            "owner": "AWS",
                            "provider": "CodeCommit",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "BranchName": "master",
                            "OutputArtifactFormat": "CODE_ZIP",
                            "PollForSourceChanges": "false",
                            "RepositoryName": "h4b-hands-on"
                        },
                        "outputArtifacts": [
                            {
                                "name": "SourceArtifact"
                            }
                        ],
                        "inputArtifacts": [],
                        "region": "ap-northeast-1",
                        "namespace": "SourceVariables"
                    }
                ]
            },
            {
                "name": "Build",
                "actions": [
                    {
                        "name": "Build",
                        "actionTypeId": {
                            "category": "Build",
                            "owner": "AWS",
                            "provider": "CodeBuild",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "ProjectName": "h4b-hands-on"
                        },
                        "outputArtifacts": [
                            {
                                "name": "BuildArtifact"
                            }
                        ],
                        "inputArtifacts": [
                            {
                                "name": "SourceArtifact"
                            }
                        ],
                        "region": "ap-northeast-1",
                        "namespace": "BuildVariables"
                    }
                ]
            },
            {
                "name": "Deploy",
                "actions": [
                    {
                        "name": "Deploy",
                        "actionTypeId": {
                            "category": "Deploy",
                            "owner": "AWS",
                            "provider": "CodeDeploy",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "ApplicationName": "h4b-app",
                            "DeploymentGroupName": "Web"
                        },
                        "outputArtifacts": [],
                        "inputArtifacts": [
                            {
                                "name": "BuildArtifact"
                            }
                        ],
                        "region": "ap-northeast-1",
                        "namespace": "DeployVariables"
                    }
                ]
            }
        ],
        "version": 1,
        "executionMode": "QUEUED",
        "pipelineType": "V2"
    },
    "metadata": {
        "pipelineArn": "arn:aws:codepipeline:ap-northeast-1:999999999999:h4b-hands-on-ec2",
        "created": "2024-09-14T05:18:39.488000+00:00",
        "updated": "2024-09-14T05:18:39.488000+00:00"
    }
}
```
## EventBridge
### IAM
```bash:コマンド
# ポリシー名
EVENT_IAM_POLICY_2_NAME="start-pipeline-execution-${REGION}-${PIPELINE_2_NAME}" \
&& echo ${EVENT_IAM_POLICY_2_NAME}

# ロール名
EVENT_IAM_ROLE_2_NAME="cwe-role-${REGION}-${PIPELINE_2_NAME}" \
&& echo ${EVENT_IAM_ROLE_2_NAME}

# IAMパス
IAM_PATH="/service-role/" \
&& echo ${IAM_PATH}

# IAMポリシー
POLICY_DOCUMENT_JSON=$(cat << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "codepipeline:StartPipelineExecution"
            ],
            "Resource": [
                "${PIPELINE_2_ARN}"
            ]
        }
    ]
}
EOF
) \
&& echo ${POLICY_DOCUMENT_JSON}

# JSONフォーマットの確認
echo ${POLICY_DOCUMENT_JSON} | python -m json.tool

# ポリシーの作成
aws iam create-policy \
    --policy-name ${EVENT_IAM_POLICY_2_NAME} \
    --path ${IAM_PATH} \
    --policy-document "${POLICY_DOCUMENT_JSON}"

# ARN取得
EVENT_IAM_POLICY_2_ARN=$(
    aws iam list-policies \
        --query "Policies[?PolicyName=='${EVENT_IAM_POLICY_2_NAME}'].Arn" \
        --output text
) \
&& echo ${EVENT_IAM_POLICY_2_ARN}

# 信頼関係ポリシードキュメントの作成
ASSUME_ROLE_POLICY_DOCUMENT=$(cat << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "events.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
EOF
) \
&& echo ${ASSUME_ROLE_POLICY_DOCUMENT}

# JSONフォーマットの確認
echo ${ASSUME_ROLE_POLICY_DOCUMENT} | python -m json.tool

# IAMロールの作成
aws iam create-role \
    --path ${IAM_PATH} \
    --role-name ${EVENT_IAM_ROLE_2_NAME} \
    --assume-role-policy-document "${ASSUME_ROLE_POLICY_DOCUMENT}"

# ARN取得
EVENT_IAM_ROLE_2_ARN=$(
    aws iam get-role \
        --role-name ${EVENT_IAM_ROLE_2_NAME} \
        --query 'Role.Arn' --output text
) \
&& echo ${EVENT_IAM_ROLE_2_ARN}

# IAMロールにポリシーをアタッチ
aws iam attach-role-policy \
    --role-name ${EVENT_IAM_ROLE_2_NAME} \
    --policy-arn ${EVENT_IAM_POLICY_2_ARN}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # ポリシー名
[cloudshell-user@ip-10-132-76-170 ~]$ EVENT_IAM_POLICY_2_NAME="start-pipeline-execution-${REGION}-${PIPELINE_2_NAME}" \
> && echo ${EVENT_IAM_POLICY_2_NAME}
start-pipeline-execution-ap-northeast-1-h4b-hands-on-ec2
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ロール名
[cloudshell-user@ip-10-132-76-170 ~]$ EVENT_IAM_ROLE_2_NAME="cwe-role-${REGION}-${PIPELINE_2_NAME}" \
> && echo ${EVENT_IAM_ROLE_2_NAME}
cwe-role-ap-northeast-1-h4b-hands-on-ec2
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMパス
[cloudshell-user@ip-10-132-76-170 ~]$ IAM_PATH="/service-role/" \
> && echo ${IAM_PATH}
/service-role/
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMポリシー
[cloudshell-user@ip-10-132-76-170 ~]$ POLICY_DOCUMENT_JSON=$(cat << EOF
> {
>     "Version": "2012-10-17",
>     "Statement": [
>         {
>             "Effect": "Allow",
>             "Action": [
>                 "codepipeline:StartPipelineExecution"
>             ],
>             "Resource": [
>                 "${PIPELINE_2_ARN}"
>             ]
>         }
>     ]
> }
> EOF
> ) \
> && echo ${POLICY_DOCUMENT_JSON}
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "codepipeline:StartPipelineExecution" ], "Resource": [ "arn:aws:codepipeline:ap-northeast-1:999999999999:h4b-hands-on-ec2" ] } ] }
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-76-170 ~]$ echo ${POLICY_DOCUMENT_JSON} | python -m json.tool
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "codepipeline:StartPipelineExecution"
            ],
            "Resource": [
                "arn:aws:codepipeline:ap-northeast-1:999999999999:h4b-hands-on-ec2"
            ]
        }
    ]
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ポリシーの作成
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam create-policy \
>     --policy-name ${EVENT_IAM_POLICY_2_NAME} \
>     --path ${IAM_PATH} \
>     --policy-document "${POLICY_DOCUMENT_JSON}"
{
    "Policy": {
        "PolicyName": "start-pipeline-execution-ap-northeast-1-h4b-hands-on-ec2",
        "PolicyId": "ANPAWFKRCMKO22BJUS675",
        "Arn": "arn:aws:iam::999999999999:policy/service-role/start-pipeline-execution-ap-northeast-1-h4b-hands-on-ec2",
        "Path": "/service-role/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 0,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "CreateDate": "2024-09-14T06:44:49+00:00",
        "UpdateDate": "2024-09-14T06:44:49+00:00"
    }
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ARN取得
[cloudshell-user@ip-10-132-76-170 ~]$ EVENT_IAM_POLICY_2_ARN=$(
>     aws iam list-policies \
>         --query "Policies[?PolicyName=='${EVENT_IAM_POLICY_2_NAME}'].Arn" \
>         --output text
> ) \
> && echo ${EVENT_IAM_POLICY_2_ARN}
arn:aws:iam::999999999999:policy/service-role/start-pipeline-execution-ap-northeast-1-h4b-hands-on-ec2
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # 信頼関係ポリシードキュメントの作成
[cloudshell-user@ip-10-132-76-170 ~]$ ASSUME_ROLE_POLICY_DOCUMENT=$(cat << EOF
> {
>     "Version": "2012-10-17",
>     "Statement": [
>         {
>             "Effect": "Allow",
>             "Principal": {
>                 "Service": "events.amazonaws.com"
>             },
>             "Action": "sts:AssumeRole"
>         }
>     ]
> }
> EOF
> ) \
> && echo ${ASSUME_ROLE_POLICY_DOCUMENT}
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "events.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-76-170 ~]$ echo ${ASSUME_ROLE_POLICY_DOCUMENT} | python -m json.tool
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "events.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMロールの作成
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam create-role \
>     --path ${IAM_PATH} \
>     --role-name ${EVENT_IAM_ROLE_2_NAME} \
>     --assume-role-policy-document "${ASSUME_ROLE_POLICY_DOCUMENT}"
{
    "Role": {
        "Path": "/service-role/",
        "RoleName": "cwe-role-ap-northeast-1-h4b-hands-on-ec2",
        "RoleId": "AROAWFKRCMKOVH6HPI7VL",
        "Arn": "arn:aws:iam::999999999999:role/service-role/cwe-role-ap-northeast-1-h4b-hands-on-ec2",
        "CreateDate": "2024-09-14T06:47:18+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "events.amazonaws.com"
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        }
    }
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ARN取得
[cloudshell-user@ip-10-132-76-170 ~]$ EVENT_IAM_ROLE_2_ARN=$(
>     aws iam get-role \
>         --role-name ${EVENT_IAM_ROLE_2_NAME} \
>         --query 'Role.Arn' --output text
> ) \
> && echo ${EVENT_IAM_ROLE_2_ARN}
arn:aws:iam::999999999999:role/service-role/cwe-role-ap-northeast-1-h4b-hands-on-ec2
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMロールにポリシーをアタッチ
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam attach-role-policy \
>     --role-name ${EVENT_IAM_ROLE_2_NAME} \
>     --policy-arn ${EVENT_IAM_POLICY_2_ARN}
```
### ルール作成
```bash:コマンド
# ルール名
EVENTS_RULE_2_NAME="codepipeline-${PIPELINE_2_NAME}-rule" \
&& echo ${EVENTS_RULE_2_NAME}

# ルール
aws events put-rule \
    --name "${EVENTS_RULE_2_NAME}" \
    --event-pattern "${EVENT_PATTERN_JSON}" \
    --role-arn "${EVENT_IAM_ROLE_ARN}"

# ターゲット
aws events put-targets \
    --rule ${EVENTS_RULE_2_NAME} \
    --targets Id="codepipeline-${PIPELINE_2_NAME}",Arn="${PIPELINE_2_ARN}",RoleArn="${EVENT_IAM_ROLE_2_ARN}"

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # ルール名
[cloudshell-user@ip-10-132-76-170 ~]$ EVENTS_RULE_2_NAME="codepipeline-${PIPELINE_2_NAME}-rule" \
> && echo ${EVENTS_RULE_2_NAME}
codepipeline-h4b-hands-on-ec2-rule
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ルール
[cloudshell-user@ip-10-132-76-170 ~]$ aws events put-rule \
>     --name "${EVENTS_RULE_2_NAME}" \
>     --event-pattern "${EVENT_PATTERN_JSON}" \
>     --role-arn "${EVENT_IAM_ROLE_ARN}"
{
    "RuleArn": "arn:aws:events:ap-northeast-1:999999999999:rule/codepipeline-h4b-hands-on-ec2-rule"
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ターゲット
[cloudshell-user@ip-10-132-76-170 ~]$ aws events put-targets \
>     --rule ${EVENTS_RULE_2_NAME} \
>     --targets Id="codepipeline-${PIPELINE_2_NAME}",Arn="${PIPELINE_2_ARN}",RoleArn="${EVENT_IAM_ROLE_2_ARN}"
{
    "FailedEntryCount": 0,
    "FailedEntries": []
}
```
:::note info
以降、Cloud9で実施
:::
## index.htmlの更新
```bash:コマンド
cat << EOF > src/index.html
<!DOCTYPE html>

<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>S3 Static Web Hosting</title>
</head>
<body>
  Hello, AWS Code* World!! :)
</body>
</html>
EOF

```
```bash:出力
admin:~/environment/h4b-hands-on (master) $ cat << EOF > src/index.html
> <!DOCTYPE html>
> 
> <html lang="ja">
> <head>
>   <meta charset="utf-8">
>   <title>S3 Static Web Hosting</title>
> </head>
> <body>
>   Hello, AWS Code* World!! :)
> </body>
> </html>
> EOF
```
## リポジトリの更新
```bash:コマンド
git add -A
git commit -m "fix."
git push origin master

```
```bash:出力
admin:~/environment/h4b-hands-on (master) $ git add -A
admin:~/environment/h4b-hands-on (master) $ git commit -m "fix."
[master 3f86091] fix.
 1 file changed, 1 insertion(+), 1 deletion(-)
admin:~/environment/h4b-hands-on (master) $ git push origin master
Enumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 398 bytes | 398.00 KiB/s, done.
Total 4 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Validating objects: 100%
To https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/h4b-hands-on
   6457444..3f86091  master -> master
```
:::note info
以降、CloudShellで実施
:::
## アクセス確認
```bash:コマンド
curl ${EC2_PUBLIC_IP}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ curl ${EC2_PUBLIC_IP}
<!DOCTYPE html>

<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>S3 Static Web Hosting</title>
</head>
<body>
  Hello, AWS Code* World!! :)
</body>
</html
```
# 08 削除手順の紹介、本シリーズのまとめ、Next Step のご案内
## Cloud9
```bash:コマンド
aws cloud9 delete-environment \
    --environment-id ${CLOUD9_ENVIRONMENT_ID}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ aws cloud9 delete-environment \
>     --environment-id ${CLOUD9_ENVIRONMENT_ID}
```
## EC2
### インスタンス
```bash:コマンド
# インスタンス
aws ec2 terminate-instances \
    --instance-ids ${EC2_INSTANCE_ID} 

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # インスタンス
[cloudshell-user@ip-10-132-76-170 ~]$ aws ec2 terminate-instances \
>     --instance-ids ${EC2_INSTANCE_ID} 
{
    "TerminatingInstances": [
        {
            "CurrentState": {
                "Code": 32,
                "Name": "shutting-down"
            },
            "InstanceId": "i-02a25fbe53f00866b",
            "PreviousState": {
                "Code": 16,
                "Name": "running"
            }
        }
    ]
}
```
:::note warn
以下、インスタンス削除後に実施 (約2分)
:::
### SG
```bash:コマンド
# セキュリティグループ
aws ec2 delete-security-group \
    --group-id ${EC2_SG_ID}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # セキュリティグループ
[cloudshell-user@ip-10-132-76-170 ~]$ aws ec2 delete-security-group \
>     --group-id ${EC2_SG_ID}
```
## CodePipeline
```bash:コマンド
# CodePipeline削除
aws codepipeline delete-pipeline \
    --name ${PIPELINE_NAME}

aws codepipeline delete-pipeline \
    --name ${PIPELINE_2_NAME}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # CodePipeline削除
[cloudshell-user@ip-10-132-76-170 ~]$ aws codepipeline delete-pipeline \
>     --name ${PIPELINE_NAME}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ aws codepipeline delete-pipeline \
>     --name ${PIPELINE_2_NAME}
```
## CodeCommit
```bash:コマンド
# CodeCommitリポジトリ削除
aws codecommit delete-repository \
    --repository-name ${REPOSITORY_NAME}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # CodeCommitリポジトリ削除
[cloudshell-user@ip-10-132-76-170 ~]$ aws codecommit delete-repository \
>     --repository-name ${REPOSITORY_NAME}
{
    "repositoryId": "944f7933-79af-41e8-a9af-35db1f7d0324"
}
```
## CodeBuild
```bash:コマンド
# プロジェクト
aws codebuild delete-project \
    --name ${CODEBUILD_NAME}

```
```bash:出力
cloudshell-user@ip-10-132-76-170 ~]$ # プロジェクト
[cloudshell-user@ip-10-132-76-170 ~]$ aws codebuild delete-project \
>     --name ${CODEBUILD_NAME}
```
## CodeDeploy
```bash:コマンド
# デプロイグループ
aws deploy delete-deployment-group \
    --application-name ${CODEDEPLOY_APP_NAME} \
    --deployment-group-name ${CODEDEPLOY_GROUP_NAME}

# アプリケーション
aws deploy delete-application \
    --application-name ${CODEDEPLOY_APP_NAME}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # デプロイグループ
[cloudshell-user@ip-10-132-76-170 ~]$ aws deploy delete-deployment-group \
>     --application-name ${CODEDEPLOY_APP_NAME} \
>     --deployment-group-name ${CODEDEPLOY_GROUP_NAME}
{
    "hooksNotCleanedUp": []
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # アプリケーション
[cloudshell-user@ip-10-132-76-170 ~]$ aws deploy delete-application \
>     --application-name ${CODEDEPLOY_APP_NAME}
```
## S3
```bash:コマンド
# オブジェクト一覧取得
OBJECT_LIST=$(
    aws s3api list-object-versions \
        --bucket ${S3_BUCKET_NAME} \
        --query='{Objects: Versions[].{Key:Key,VersionId:VersionId}}'
) \
&& echo ${OBJECT_LIST}

# JSONフォーマットの確認
echo ${OBJECT_LIST} | python -m json.tool

# バケットを空にする
aws s3api delete-objects \
    --bucket ${S3_BUCKET_NAME} \
    --delete "${OBJECT_LIST}"

# S3バケットを削除
aws s3api delete-bucket \
    --bucket ${S3_BUCKET_NAME}

# オブジェクト一覧取得
OBJECT_LIST=$(
    aws s3api list-object-versions \
        --bucket ${ARTIFACTSTORE_BUCKET_NAME} \
        --query='{Objects: Versions[].{Key:Key,VersionId:VersionId}}'
) \
&& echo ${OBJECT_LIST}

# JSONフォーマットの確認
echo ${OBJECT_LIST} | python -m json.tool

# バケットを空にする
aws s3api delete-objects \
    --bucket ${ARTIFACTSTORE_BUCKET_NAME} \
    --delete "${OBJECT_LIST}"

# S3バケットを削除
aws s3api delete-bucket \
    --bucket ${ARTIFACTSTORE_BUCKET_NAME}

# オブジェクト一覧取得
OBJECT_LIST=$(
    aws s3api list-object-versions \
        --bucket ${CODEBUILD_ARTIFACTSTORE_BUCKET_NAME} \
        --query='{Objects: Versions[].{Key:Key,VersionId:VersionId}}'
) \
&& echo ${OBJECT_LIST}

# JSONフォーマットの確認
echo ${OBJECT_LIST} | python -m json.tool

# バケットを空にする
aws s3api delete-objects \
    --bucket ${CODEBUILD_ARTIFACTSTORE_BUCKET_NAME} \
    --delete "${OBJECT_LIST}"

# S3バケットを削除
aws s3api delete-bucket \
    --bucket ${CODEBUILD_ARTIFACTSTORE_BUCKET_NAME}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # オブジェクト一覧取得
[cloudshell-user@ip-10-132-76-170 ~]$ OBJECT_LIST=$(
>     aws s3api list-object-versions \
>         --bucket ${S3_BUCKET_NAME} \
>         --query='{Objects: Versions[].{Key:Key,VersionId:VersionId}}'
> ) \
> && echo ${OBJECT_LIST}
{ "Objects": [ { "Key": "buildspec.yaml", "VersionId": "null" }, { "Key": "index.html", "VersionId": "null" }, { "Key": "src/appspec.yml", "VersionId": "null" }, { "Key": "src/index.html", "VersionId": "null" } ] }
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-76-170 ~]$ echo ${OBJECT_LIST} | python -m json.tool
{
    "Objects": [
        {
            "Key": "buildspec.yaml",
            "VersionId": "null"
        },
        {
            "Key": "index.html",
            "VersionId": "null"
        },
        {
            "Key": "src/appspec.yml",
            "VersionId": "null"
        },
        {
            "Key": "src/index.html",
            "VersionId": "null"
        }
    ]
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # バケットを空にする
[cloudshell-user@ip-10-132-76-170 ~]$ aws s3api delete-objects \
>     --bucket ${S3_BUCKET_NAME} \
>     --delete "${OBJECT_LIST}"
{
    "Deleted": [
        {
            "Key": "index.html",
            "VersionId": "null"
        },
        {
            "Key": "src/appspec.yml",
            "VersionId": "null"
        },
        {
            "Key": "buildspec.yaml",
            "VersionId": "null"
        },
        {
            "Key": "src/index.html",
            "VersionId": "null"
        }
    ]
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # S3バケットを削除
[cloudshell-user@ip-10-132-76-170 ~]$ aws s3api delete-bucket \
>     --bucket ${S3_BUCKET_NAME}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # オブジェクト一覧取得
[cloudshell-user@ip-10-132-76-170 ~]$ OBJECT_LIST=$(
>     aws s3api list-object-versions \
>         --bucket ${ARTIFACTSTORE_BUCKET_NAME} \
>         --query='{Objects: Versions[].{Key:Key,VersionId:VersionId}}'
> ) \
> && echo ${OBJECT_LIST}
{ "Objects": [ { "Key": "h4b-hands-on-ec2/BuildArtif/wkxrsDK", "VersionId": "null" }, { "Key": "h4b-hands-on-ec2/SourceArti/8LHRFme", "VersionId": "null" }, { "Key": "h4b-hands-on-s3/SourceArti/MYU9p06", "VersionId": "null" }, { "Key": "h4b-hands-on-s3/SourceArti/Wovweya", "VersionId": "null" }, { "Key": "h4b-hands-on-s3/SourceArti/ozYCGsg", "VersionId": "null" }, { "Key": "h4b-hands-on-s3/SourceArti/xNtW3Ec", "VersionId": "null" } ] }
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-76-170 ~]$ echo ${OBJECT_LIST} | python -m json.tool
{
    "Objects": [
        {
            "Key": "h4b-hands-on-ec2/BuildArtif/wkxrsDK",
            "VersionId": "null"
        },
        {
            "Key": "h4b-hands-on-ec2/SourceArti/8LHRFme",
            "VersionId": "null"
        },
        {
            "Key": "h4b-hands-on-s3/SourceArti/MYU9p06",
            "VersionId": "null"
        },
        {
            "Key": "h4b-hands-on-s3/SourceArti/Wovweya",
            "VersionId": "null"
        },
        {
            "Key": "h4b-hands-on-s3/SourceArti/ozYCGsg",
            "VersionId": "null"
        },
        {
            "Key": "h4b-hands-on-s3/SourceArti/xNtW3Ec",
            "VersionId": "null"
        }
    ]
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # バケットを空にする
[cloudshell-user@ip-10-132-76-170 ~]$ aws s3api delete-objects \
>     --bucket ${ARTIFACTSTORE_BUCKET_NAME} \
>     --delete "${OBJECT_LIST}"
{
    "Deleted": [
        {
            "Key": "h4b-hands-on-s3/SourceArti/ozYCGsg",
            "VersionId": "null"
        },
        {
            "Key": "h4b-hands-on-ec2/BuildArtif/wkxrsDK",
            "VersionId": "null"
        },
        {
            "Key": "h4b-hands-on-s3/SourceArti/Wovweya",
            "VersionId": "null"
        },
        {
            "Key": "h4b-hands-on-ec2/SourceArti/8LHRFme",
            "VersionId": "null"
        },
        {
            "Key": "h4b-hands-on-s3/SourceArti/MYU9p06",
            "VersionId": "null"
        },
        {
            "Key": "h4b-hands-on-s3/SourceArti/xNtW3Ec",
            "VersionId": "null"
        }
    ]
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # S3バケットを削除
[cloudshell-user@ip-10-132-76-170 ~]$ aws s3api delete-bucket \
>     --bucket ${ARTIFACTSTORE_BUCKET_NAME}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # オブジェクト一覧取得
[cloudshell-user@ip-10-132-76-170 ~]$ OBJECT_LIST=$(
>     aws s3api list-object-versions \
>         --bucket ${CODEBUILD_ARTIFACTSTORE_BUCKET_NAME} \
>         --query='{Objects: Versions[].{Key:Key,VersionId:VersionId}}'
> ) \
> && echo ${OBJECT_LIST}
{ "Objects": [ { "Key": "artifact.zip", "VersionId": "null" }, { "Key": "h4b-hands-on/appspec.yml", "VersionId": "null" }, { "Key": "h4b-hands-on/index.html", "VersionId": "null" } ] }
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-76-170 ~]$ echo ${OBJECT_LIST} | python -m json.tool
{
    "Objects": [
        {
            "Key": "artifact.zip",
            "VersionId": "null"
        },
        {
            "Key": "h4b-hands-on/appspec.yml",
            "VersionId": "null"
        },
        {
            "Key": "h4b-hands-on/index.html",
            "VersionId": "null"
        }
    ]
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # バケットを空にする
[cloudshell-user@ip-10-132-76-170 ~]$ aws s3api delete-objects \
>     --bucket ${CODEBUILD_ARTIFACTSTORE_BUCKET_NAME} \
>     --delete "${OBJECT_LIST}"
{
    "Deleted": [
        {
            "Key": "h4b-hands-on/index.html",
            "VersionId": "null"
        },
        {
            "Key": "artifact.zip",
            "VersionId": "null"
        },
        {
            "Key": "h4b-hands-on/appspec.yml",
            "VersionId": "null"
        }
    ]
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # S3バケットを削除
[cloudshell-user@ip-10-132-76-170 ~]$ aws s3api delete-bucket \
>     --bucket ${CODEBUILD_ARTIFACTSTORE_BUCKET_NAME}
```
## IAM
```bash:コマンド
# ロールにアタッチされているポリシーをリスト
POLICIES=$(
    aws iam list-attached-role-policies \
        --role-name ${PIPELINE_IAM_ROLE_NAME} \
        --query 'AttachedPolicies[*].PolicyArn' \
        --output text
) \
&& echo ${POLICIES}

# リスト内のポリシーをデタッチする
for POLICY in ${POLICIES}; do
    aws iam detach-role-policy \
        --role-name ${PIPELINE_IAM_ROLE_NAME} \
        --policy-arn ${POLICY}
done

# IAMロールの削除
aws iam delete-role \
    --role-name ${PIPELINE_IAM_ROLE_NAME}

# IAMポリシーの削除
aws iam delete-policy \
    --policy-arn ${PIPELINE_IAM_POLICY_ARN}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # ロールにアタッチされているポリシーをリスト
[cloudshell-user@ip-10-132-76-170 ~]$ POLICIES=$(
>     aws iam list-attached-role-policies \
>         --role-name ${PIPELINE_IAM_ROLE_NAME} \
>         --query 'AttachedPolicies[*].PolicyArn' \
>         --output text
> ) \
> && echo ${POLICIES}
arn:aws:iam::999999999999:policy/service-role/AWSCodePipelineServiceRole-ap-northeast-1
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # リスト内のポリシーをデタッチする
[cloudshell-user@ip-10-132-76-170 ~]$ for POLICY in ${POLICIES}; do
>     aws iam detach-role-policy \
>         --role-name ${PIPELINE_IAM_ROLE_NAME} \
>         --policy-arn ${POLICY}
> done
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMロールの削除
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam delete-role \
>     --role-name ${PIPELINE_IAM_ROLE_NAME}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMポリシーの削除
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam delete-policy \
>     --policy-arn ${PIPELINE_IAM_POLICY_ARN}
```

```bash:コマンド
# CODEDEPLOY_IAM_ROLE_NAME
# ロールにアタッチされているポリシーをリスト
POLICIES=$(
    aws iam list-attached-role-policies \
        --role-name ${EVENT_IAM_ROLE_NAME} \
        --query 'AttachedPolicies[*].PolicyArn' \
        --output text
) \
&& echo ${POLICIES}

# リスト内のポリシーをデタッチする
for POLICY in ${POLICIES}; do
    aws iam detach-role-policy \
        --role-name ${EVENT_IAM_ROLE_NAME} \
        --policy-arn ${POLICY}
done

# IAMロールの削除
aws iam delete-role \
    --role-name ${EVENT_IAM_ROLE_NAME}

# IAMポリシーの削除
aws iam delete-policy \
    --policy-arn ${EVENT_IAM_POLICY_ARN}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # CODEDEPLOY_IAM_ROLE_NAME
[cloudshell-user@ip-10-132-76-170 ~]$ # ロールにアタッチされているポリシーをリスト
[cloudshell-user@ip-10-132-76-170 ~]$ POLICIES=$(
>     aws iam list-attached-role-policies \
>         --role-name ${EVENT_IAM_ROLE_NAME} \
>         --query 'AttachedPolicies[*].PolicyArn' \
>         --output text
> ) \
> && echo ${POLICIES}
arn:aws:iam::999999999999:policy/service-role/start-pipeline-execution-ap-northeast-1-h4b-hands-on-s3
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # リスト内のポリシーをデタッチする
[cloudshell-user@ip-10-132-76-170 ~]$ for POLICY in ${POLICIES}; do
>     aws iam detach-role-policy \
>         --role-name ${EVENT_IAM_ROLE_NAME} \
>         --policy-arn ${POLICY}
> done
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMロールの削除
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam delete-role \
>     --role-name ${EVENT_IAM_ROLE_NAME}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMポリシーの削除
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam delete-policy \
>     --policy-arn ${EVENT_IAM_POLICY_ARN}
```

```bash:コマンド
# CODEDEPLOY_IAM_ROLE_NAME
# ロールにアタッチされているポリシーをリスト
POLICIES=$(
    aws iam list-attached-role-policies \
        --role-name ${EVENT_IAM_ROLE_2_NAME} \
        --query 'AttachedPolicies[*].PolicyArn' \
        --output text
) \
&& echo ${POLICIES}

# リスト内のポリシーをデタッチする
for POLICY in ${POLICIES}; do
    aws iam detach-role-policy \
        --role-name ${EVENT_IAM_ROLE_2_NAME} \
        --policy-arn ${POLICY}
done

# IAMロールの削除
aws iam delete-role \
    --role-name ${EVENT_IAM_ROLE_2_NAME}

# IAMポリシーの削除
aws iam delete-policy \
    --policy-arn ${EVENT_IAM_POLICY_2_ARN}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # CODEDEPLOY_IAM_ROLE_NAME
[cloudshell-user@ip-10-132-76-170 ~]$ # ロールにアタッチされているポリシーをリスト
[cloudshell-user@ip-10-132-76-170 ~]$ POLICIES=$(
>     aws iam list-attached-role-policies \
>         --role-name ${EVENT_IAM_ROLE_2_NAME} \
>         --query 'AttachedPolicies[*].PolicyArn' \
>         --output text
> ) \
> && echo ${POLICIES}
arn:aws:iam::999999999999:policy/service-role/start-pipeline-execution-ap-northeast-1-h4b-hands-on-ec2
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # リスト内のポリシーをデタッチする
[cloudshell-user@ip-10-132-76-170 ~]$ for POLICY in ${POLICIES}; do
>     aws iam detach-role-policy \
>         --role-name ${EVENT_IAM_ROLE_2_NAME} \
>         --policy-arn ${POLICY}
> done
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMロールの削除
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam delete-role \
>     --role-name ${EVENT_IAM_ROLE_2_NAME}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMポリシーの削除
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam delete-policy \
>     --policy-arn ${EVENT_IAM_POLICY_2_ARN}
```

```bash:コマンド
# EC2_IAM_ROLE_NAME
# IAMプロファイルのデタッチ
aws iam remove-role-from-instance-profile \
    --instance-profile-name ${EC2_IAM_ROLE_NAME}\
    --role-name ${EC2_IAM_ROLE_NAME}

# インスタンスプロファイル削除
aws iam delete-instance-profile \
    --instance-profile-name ${EC2_IAM_ROLE_NAME}

# ロールにアタッチされているポリシーをリスト
POLICIES=$(
    aws iam list-attached-role-policies \
        --role-name ${EC2_IAM_ROLE_NAME} \
        --query 'AttachedPolicies[*].PolicyArn' \
        --output text
) \
&& echo ${POLICIES}

# リスト内のポリシーをデタッチする
for POLICY in ${POLICIES}; do
    aws iam detach-role-policy \
        --role-name ${EC2_IAM_ROLE_NAME} \
        --policy-arn ${POLICY}
done

# IAMロールの削除
aws iam delete-role \
    --role-name ${EC2_IAM_ROLE_NAME}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # EC2_IAM_ROLE_NAME
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMプロファイルのデタッチ
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam remove-role-from-instance-profile \
>     --instance-profile-name ${EC2_IAM_ROLE_NAME}\
>     --role-name ${EC2_IAM_ROLE_NAME}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # インスタンスプロファイル削除
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam delete-instance-profile \
>     --instance-profile-name ${EC2_IAM_ROLE_NAME}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # ロールにアタッチされているポリシーをリスト
[cloudshell-user@ip-10-132-76-170 ~]$ POLICIES=$(
>     aws iam list-attached-role-policies \
>         --role-name ${EC2_IAM_ROLE_NAME} \
>         --query 'AttachedPolicies[*].PolicyArn' \
>         --output text
> ) \
> && echo ${POLICIES}
arn:aws:iam::aws:policy/AmazonS3FullAccess
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # リスト内のポリシーをデタッチする
[cloudshell-user@ip-10-132-76-170 ~]$ for POLICY in ${POLICIES}; do
>     aws iam detach-role-policy \
>         --role-name ${EC2_IAM_ROLE_NAME} \
>         --policy-arn ${POLICY}
> done
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMロールの削除
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam delete-role \
>     --role-name ${EC2_IAM_ROLE_NAME}
```

```bash:コマンド
# CODEBUILD_IAM_ROLE_NAME
# ロールにアタッチされているポリシーをリスト
POLICIES=$(
    aws iam list-attached-role-policies \
        --role-name ${CODEBUILD_IAM_ROLE_NAME} \
        --query 'AttachedPolicies[*].PolicyArn' \
        --output text
) \
&& echo ${POLICIES}

# リスト内のポリシーをデタッチする
for POLICY in ${POLICIES}; do
    aws iam detach-role-policy \
        --role-name ${CODEBUILD_IAM_ROLE_NAME} \
        --policy-arn ${POLICY}
done

# IAMロールの削除
aws iam delete-role \
    --role-name ${CODEBUILD_IAM_ROLE_NAME}

# IAMポリシーの削除
aws iam delete-policy \
    --policy-arn ${CODEBUILD_IAM_POLICY_ARN}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # CODEBUILD_IAM_ROLE_NAME
[cloudshell-user@ip-10-132-76-170 ~]$ # ロールにアタッチされているポリシーをリスト
[cloudshell-user@ip-10-132-76-170 ~]$ POLICIES=$(
>     aws iam list-attached-role-policies \
>         --role-name ${CODEBUILD_IAM_ROLE_NAME} \
>         --query 'AttachedPolicies[*].PolicyArn' \
>         --output text
> ) \
> && echo ${POLICIES}
arn:aws:iam::999999999999:policy/service-role/CodeBuildBasePolicy-h4b-hands-on-ap-northeast-1 arn:aws:iam::aws:policy/AWSCodeDeployDeployerAccess
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # リスト内のポリシーをデタッチする
[cloudshell-user@ip-10-132-76-170 ~]$ for POLICY in ${POLICIES}; do
>     aws iam detach-role-policy \
>         --role-name ${CODEBUILD_IAM_ROLE_NAME} \
>         --policy-arn ${POLICY}
> done
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMロールの削除
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam delete-role \
>     --role-name ${CODEBUILD_IAM_ROLE_NAME}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMポリシーの削除
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam delete-policy \
>     --policy-arn ${CODEBUILD_IAM_POLICY_ARN}
```

```bash:コマンド
# CODEDEPLOY_IAM_ROLE_NAME
# ロールにアタッチされているポリシーをリスト
POLICIES=$(
    aws iam list-attached-role-policies \
        --role-name ${CODEDEPLOY_IAM_ROLE_NAME} \
        --query 'AttachedPolicies[*].PolicyArn' \
        --output text
) \
&& echo ${POLICIES}

# リスト内のポリシーをデタッチする
for POLICY in ${POLICIES}; do
    aws iam detach-role-policy \
        --role-name ${CODEDEPLOY_IAM_ROLE_NAME} \
        --policy-arn ${POLICY}
done

# IAMロールの削除
aws iam delete-role \
    --role-name ${CODEDEPLOY_IAM_ROLE_NAME}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # CODEDEPLOY_IAM_ROLE_NAME
[cloudshell-user@ip-10-132-76-170 ~]$ # ロールにアタッチされているポリシーをリスト
[cloudshell-user@ip-10-132-76-170 ~]$ POLICIES=$(
>     aws iam list-attached-role-policies \
>         --role-name ${CODEDEPLOY_IAM_ROLE_NAME} \
>         --query 'AttachedPolicies[*].PolicyArn' \
>         --output text
> ) \
> && echo ${POLICIES}
arn:aws:iam::aws:policy/service-role/AWSCodeDeployRole
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # リスト内のポリシーをデタッチする
[cloudshell-user@ip-10-132-76-170 ~]$ for POLICY in ${POLICIES}; do
>     aws iam detach-role-policy \
>         --role-name ${CODEDEPLOY_IAM_ROLE_NAME} \
>         --policy-arn ${POLICY}
> done
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # IAMロールの削除
[cloudshell-user@ip-10-132-76-170 ~]$ aws iam delete-role \
>     --role-name ${CODEDEPLOY_IAM_ROLE_NAME}
```
## EventBridge
```bash:コマンド
# codepipeline-h4b-hands-on-s3-rule用
aws events remove-targets \
    --rule ${EVENTS_RULE_NAME} \
    --ids "codepipeline-${PIPELINE_NAME}"

aws events delete-rule \
    --name ${EVENTS_RULE_NAME}

# codepipeline-h4b-hands-on-ec2-rule用
aws events remove-targets \
    --rule ${EVENTS_RULE_2_NAME} \
    --ids "codepipeline-${PIPELINE_2_NAME}"

aws events delete-rule \
    --name ${EVENTS_RULE_2_NAME}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # codepipeline-h4b-hands-on-s3-rule用
[cloudshell-user@ip-10-132-76-170 ~]$ aws events remove-targets \
>     --rule ${EVENTS_RULE_NAME} \
>     --ids "codepipeline-${PIPELINE_NAME}"
{
    "FailedEntryCount": 0,
    "FailedEntries": []
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ aws events delete-rule \
>     --name ${EVENTS_RULE_NAME}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ # codepipeline-h4b-hands-on-ec2-rule用
[cloudshell-user@ip-10-132-76-170 ~]$ aws events remove-targets \
>     --rule ${EVENTS_RULE_2_NAME} \
>     --ids "codepipeline-${PIPELINE_2_NAME}"
{
    "FailedEntryCount": 0,
    "FailedEntries": []
}
[cloudshell-user@ip-10-132-76-170 ~]$ 
[cloudshell-user@ip-10-132-76-170 ~]$ aws events delete-rule \
>     --name ${EVENTS_RULE_2_NAME}
```
## CloudWatch
```bash:コマンド
# ロググループ
aws logs delete-log-group \
    --log-group-name ${LOG_GROUP_NAME}

```
```bash:出力
[cloudshell-user@ip-10-132-76-170 ~]$ # ロググループ
[cloudshell-user@ip-10-132-76-170 ~]$ aws logs delete-log-group \
>     --log-group-name ${LOG_GROUP_NAME}
```