【AWS】AWS CodeArtifactをAWS CodeBuildで検証する（実践編）

## はじめに

この記事では「この前リリースされた機能って実際に動かすとどんな感じなんだろう」とか「もしかしたら内容次第では使えるかも？？」などAWSサービスの中でも特定の機能にフォーカスしたり、サービス間連携を検証していく記事です。
主な内容としては実践したときのメモを中心に書きます。（忘れやすいことなど）誤りなどがあれば書き直していく予定です。

今回はAWS CodeBuildでAWS CodeArtifactを使うとどうなるのかを検証します。なお、環境セットアップについては以下の記事を参考にしてください。

[【AWS】AWS CodeArtifactをAWS CodeBuildで検証する（準備編）](https://qiita.com/ymd65536/items/aca6234a6baf85c24856)

## 前回のおさらい

前回は環境を構築しましたが、実際のところどのような構成だったのでしょうか。ここでおさらいしておきましょう。

サービスアイコンを並べただけですが、前回作った構成は以下のようになります。
CodeBuildではS3、サービス同士はIAMロールを利用しています。
※今回説明したいサービスにフォーカスしてもらいたいために省略

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/8aaaa641-6e36-5690-fc5d-5447eb0c0275.png)

## CodeBuildでCodeArtifactを利用する場合

CodeBuildのおさらいになりますが、CodeBuildはビルドを実行したときのみマシンを起動してビルドを実行します。つまり、CodeArtifactの設定はCodeBuild起動時に行わないといけません。

設定手順としては以下のとおりです。

1. AWS CLIをインストールする
2. CodeArtifactにログインする

[CodeBuild で npm パッケージを使用する - 参考](https://docs.aws.amazon.com/ja_jp/codeartifact/latest/ug/using-npm-packages-in-codebuild.html)

※AWS CLIがインストールされている場合はインストールの必要はありません。

2つの工程をCodeBuildの`pre_build`のステップで実行します。

## ハンズオン

ではここから実際にハンズオンしてみましょう。

### IAMロールを確認する

今回はCodeBuildでCodeArtifactにアクセスするため、CodeArtifactにアクセスするためのIAMポリシーをCodeBuildのIAMロールが持っていないといけません。

では、そのポリシーがどこに定義されているのかを確認します。具体的には[前回使ったリポジトリ](https://github.com/ymd65536/aws_codebuild_artifact.git)内にある`codebuild-role.yml`というファイルです。

```yaml
AWSTemplateFormatVersion: 2010-09-09
Description: "CodeBuild IAM Role"
Parameters:
  PjName:
    Type: String
    Default: Qiita

Resources:
  QiitaCodeBuildRole:
    Type: "AWS::IAM::Role"
    Properties:
      RoleName: QiitaCodeBuildRole
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: "codebuild.amazonaws.com"
            Action: "sts:AssumeRole"
      ManagedPolicyArns:
        - !Ref QiitaCodeBuildPolicy
      Tags:
        - Key: Name
          Value: !Sub "${PjName}"
  QiitaCodeBuildPolicy:
    Type: "AWS::IAM::ManagedPolicy"
    Properties:
      ManagedPolicyName: codebuild-role
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action:
              - "codeartifact:GetAuthorizationToken"
              - "codeartifact:GetRepositoryEndpoint"
              - "codeartifact:ReadFromRepository"
            Resource:
              - "*"
          - Effect: Allow
            Action:
              - "sts:GetServiceBearerToken"
            Resource: "*"
            Condition:
              StringEquals:
                sts:AWSServiceName: "codeartifact.amazonaws.com"
          - Effect: Allow
            Action:
              - "logs:CreateLogStream"
              - "logs:PutLogEvents"
              - "logs:CreateLogGroup"
            Resource: "*"
          - Effect: Allow
            Action:
              - "s3:PutObject"
              - "s3:GetObject"
              - "s3:GetObjectVersion"
              - "s3:GetBucketAcl"
              - "s3:GetBucketLocation"
            Resource:
              - !Join
                - ""
                - - !ImportValue QiitaBucketArn
                  - "/*"
              - !ImportValue QiitaBucketArn
Outputs:
  QiitaCodeBuildRoleName:
    Value: !Ref QiitaCodeBuildRole
    Export:
      Name: CodeBuildRoleName

```

実は環境構築時に定義しています。

## buildspec.ymlを修正

次にCodeBuildの設定ファイルとなる`buildspec.yml`を修正します。

AWSマネジメントコンソールを開き、CodeCommitを検索してクリックします。

![Screenshot 2024-06-15 at 19.07.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/5d750ae6-2951-86fd-20f0-d7c7e8cfa7ed.png)

画面左側の`Repositories`をクリックします。

![Screenshot 2024-06-15 at 19.10.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/46edd59e-5fee-3fd8-9f2f-dc961ec86ad7.png)

画面が切り替わりますのでQiitaというリポジトリ名をクリックします。

![Screenshot 2024-06-15 at 19.11.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/862aa976-8784-bbe2-4d85-2be3066ee3af.png)

リポジトリ内のファイル一覧が表示されたら`Reference`を`code_build_handson`に切り替えます。

![Screenshot 2024-06-15 at 19.12.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/44d45a15-7508-7beb-19f3-8dde1ff6835c.png)

画面が切り替わるので次は`buildspec.yml`をクリックします。

![Screenshot 2024-06-15 at 19.12.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/69b22474-a4b4-ab15-0d20-a901a2529fe5.png)

`Edit`をクリックして`buildspec.yml`を編集します。

![Screenshot 2024-06-15 at 19.12.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/f7de0a84-9287-4ec6-1bd1-e831ac1aa608.png)

現在の設定は以下のようにechoするだけのものとなっているはずです。

```yaml
version: 0.2
phases:
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
  build:
    commands:
      - echo Build started on `date`
      - echo Building the Docker image...
  post_build:
    commands:
      - echo Build completed on `date`
      - echo Pushing the Docker image...

```

上記の設定を下記のように書き換えます。

```yaml
version: 0.2
phases:
  pre_build:
    commands:
      - aws codeartifact login --tool npm --domain $AWS_DOMAIN --domain-owner $AWS_ACCOUNT_ID --repository $REPOSITORY_NAME
  build:
    commands:
      - npm install sample-package@1.0.0
  post_build:
    commands:
      - node index.js
      - echo completed on `date`
```

編集が完了したら`Commit changes`をクリックします。

![Screenshot 2024-06-15 at 19.23.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/7658d9aa-ef3c-5108-658d-aee7c7c33a68.png)

次に`index.js`をアップロードします。`Upload file`をクリックします。

![Screenshot 2024-06-15 at 19.24.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/0f76e101-6ba3-7c68-f441-b5fccb868a07.png)

`index.js`は以下のようにシンプルな内容です。

```js:index.js
const test = require('sample-package');
test();
```

![Screenshot 2024-06-15 at 19.25.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/ae06b1f6-4d56-45b1-223b-075620edd3a0.png)

アップロードが完了したら、`Commit changes`をクリックします。
同じ要領で`package.json`をアップロードします。

`package.json`は以下のようにシンプルな内容です。

```json:package.json
{
    "name": "sample-app",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
    },
    "author": "",
    "license": "ISC",
    "dependencies": {
        "sample-package": "^1.0.0"
    }
}
```

### プルリクエストを作成してマージを実行する

リポジトリのファイル一覧に戻って`Create pull request`をクリックします。

![Screenshot 2024-06-15 at 20.10.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/26ccdd7a-0be8-54cf-a339-874a6a60e455.png)

mainブランチにcode_build_handsonブランチの変更内容をマージするため、`Create pull request`を実行します。

![Screenshot 2024-06-15 at 19.26.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/4dcca739-92b5-dd1e-a899-1be1c706ec0a.png)

次の画面で`Merge`をクリックします。

![Screenshot 2024-06-15 at 19.26.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/6e12f983-e56c-6a5c-831c-e164e7b2e3ec.png)

`Fast forward merge`を選択し、`Merge pull request`をクリックします。

![Screenshot 2024-06-15 at 19.26.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/31a74b69-e93d-7269-02de-a9fb0e4f11a4.png)

Codepipelineの画面に移動すると`In progress`となっています。しばらく待ちましょう。

![Screenshot 2024-06-15 at 19.27.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/7ccc9c59-8e97-88ce-96a5-9ebde1db20d5.png)

※以下、ビルド中の画面

![Screenshot 2024-06-15 at 19.27.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/ab07263d-775b-6c61-ded4-eaaeff202567.png)

## 実行結果

うまくいくと40行目で`Hello CodeArtifact!!`と表示されます。これでCodeBuildからCodeArtifactのパッケージを参照できるようになりました。

![Screenshot 2024-06-15 at 20.00.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/1c6258ce-328e-968f-7eae-1397041aee62.png)

## まとめ

2つの記事にわたってAWS CodeArtifactをAWS CodeBuildで検証する方法を書きました。
CodeBuildでCodeArtifactを利用すると今回紹介したように独自のパッケージをプライベートにホストしたり、OSSで特定のバージョンのみをAWS上に置いてアプリケーションをテストしたりなどができます。

また、CodeArtifactを通すことなく、パッケージをインストールした場合はパブリックレジストリを参照するため、場合によっては悪意のあるコードが埋め込まれてしまいます。
つまり、セキュリティという文脈ではサプライチェーン攻撃の予防にも役立ちます。

再現性のあるプログラムを作成するためにもセキュリティのためにも実装してみると良いかもしれません。

ちなみに試せてはいないですが、CodeBuildのビルド速度も体感レベルで速くなったような気がしています。気がするだけなので別の記事でしっかり検証したいと思います。

## おわり