AWS CodeArtifact でプライベートリポジトリを作ろう

2020年6月 AWS Code 兄弟に突如新生が。その名も AWS CodeArtifact 。
ソフトウェアパッケージを安全に保存、公開、共有できるようにするプライベートリポジトリサービスです。
すでに東京リージョンで一般利用可能かつ、VPC Endpoint にも対応済みです。

:rocket: **Introducing AWS CodeArtifact: A fully managed software artifact repository service**
https://aws.amazon.com/jp/about-aws/whats-new/2020/06/introducing-aws-codeartifact-a-fully-managed-software-artifact-repository-service/

類似のツールやサービスとしては JFrog Artifactory や GitHub Package Registry,
Azure Artifacts あたりが有名かと思います。

## なにが嬉しいのか
AWS CodeArtifact のようなリポジトリマネージャーの利点は大きく2つあります。

### 1. 公式リポジトリのキャッシュ
ソフトウェアを開発する際、各種言語のパッケージマネージャーなどのエコシステムを
利用することがもはや当たり前になってきました。

CodeArtifact は maven や npm などの対応するパッケージマネージャーの Proxy として利用できます。
管理者はパッケージへのアクセス制御が可能となり、組織内で使用が承認されている
最新のパッケージのみを開発者に提供できるようになります。

また組織のポリシーによっては自由に公開リポジトリにアクセスできない場合もあります。
VPC Endpoint 利用することでインターネットを経由せずに、CodeArtifact にキャッシュされた
パッケージにアクセスできます。またダウンロード時間の短縮も期待できます。

2020年11月時点で以下の外部接続に対応しています。
他社サービスと比較すると最低限という感じですが、今後のアップデートに期待です。

|Type|Description|
|---|---|
|npm|npm public registry|
|Python|Python Package Index|
|Maven|Maven Central|
|Maven|Google Android repository|
|Maven|Gradle plugins repository|
|Maven|CommonsWare Android repository|
|NuGet|NuGet Gallery|

### 2. 独自パッケージの管理
CodeArtifact は組織内で構築されたパッケージを格納する中心的な場所を提供します。
格納されたパッケージは安全に共有でき、既存のパッケージマネージャーから利用できるため
開発の時間短縮につながります。

## CodeArtifact で覚えておきたい重要な概念
### リポジトリ
アカウント内で複数のリポジトリを作成できます。 (最大100個)
1つのリポジトリにはサポートされている複数言語のパッケージを含めることができます。
リポジトリは各パッケージマネージャーからアクセスする際のエンドポイントの単位になります。

### ドメイン
CodeArtifact 独自の概念です。各リポジトリを単一のドメインに紐づけて管理します。

各パッケージはリポジトリを経由して利用しますが、データの実体はリポジトリではなく
ドメインに保存されます。同じドメイン内であれば、特定のパッケージを複数のリポジトリで
利用してもリポジトリの数に関係なく、保存されるのは1回のみです。
つまりストレージ料金は重複して発生しません。

またドメインはクロスアカウントで利用可能です。組織の共通ドメインを作成し、
各アカウントで独自のリポジトリを利用することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/9e27146f-aad9-454e-dd1f-a536cd6d9810.png)

### アップストリームリポジトリ
各リポジトリに、アップストリームリポジトリとして他リポジトリを設定することができます。
これにより組織内共通のリポジトリ、開発チーム用のリポジトリ、のように用途に応じて
分けている場合でもクライアントは単一のエンドポイントからアクセスすることが可能になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/fe2cf5ca-724e-fa7a-8f9e-399aec523b03.png)

### ドメインポリシーとリポジトリポリシー
ともにおなじみの json 形式で設定可能です。

ドメインポリシー設定することで組織内のアカウントや特定の IAM プリンシパルに
ドメインへのアクセスを許可することができます。

同様にリソースポリシーを定義するとリポジトリにアクセスできるユーザーと、リポジトリに対して
実行できるアクションを指定できます。
これにより上述の構成例の場合、組織共有リポジトリには組織内からの読み取り権限のみを設定し、
開発チームリポジトリには開発メンバーのみ読み取りおよび書き込みを許可するような設定が可能です。

## やってみる
### ドメインとリポジトリの作成
CodeArtifact コンソールのトップで リポジトリを作成 を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/92faf47d-4790-2cdb-fce7-d2a4cb066f0e.png)
リポジトリ名を入力し、パブリックアップストリームリポジトリの設定で
キャッシュを行なう公式リポジトリを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/5fec9254-c74d-0e29-b36a-0502f8653725.png)
次にリポジトリを登録するドメインを選択します。
このアカウントではまだドメインを作成していないため、ドメイン名を指定して新規作成します。
追加設定では暗号化に使用する KMS キーをマネージドまたは特定の CMK から選択できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/7ce63558-f9e6-7392-0270-c940b5ba73a3.png)
最後に設定内容を確認し、リポジトリおよびドメインを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/4dc5039f-2075-90e3-61bd-3d893cbda429.png)
パッケージフローをみてもわかるようにリポジトリの作成ウィザードでは
パブリックアップストリームリポジトリのみが選択可能になっています。
他のリポジトリをアップストリームリポジトリに設定するにはリポジトリ作成後に編集から
設定する必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/0cde4339-b190-db60-9f83-626990c4ed3b.png)

### リポジトリの接続方法
作成したリポジトリの接続情報を取得するには AWS CLI v2.0.21 以上が必要です。
具体的な接続コマンドはコンソールのリポジトリ画面からツール毎に確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/a84836be-d003-00fe-8a9c-b8633a40e636.png)
例えば pip の場合、以下のようになります。
--domain-owner オプションはドメインを作成したアカウントであれば省略可能です。

```shell-session
$ aws codeartifact login --tool pip --repository my-repo --domain my-domain --domain-owner 0123456789012
Successfully logged in to codeartifact for pip.
```
内部的には pip config set で global.index-url を自動で設定してくれているようです。
pip config list で 認証情報が付加されたリポジトリのエンドポイントを確認できます。
この認証情報は12時間後に失効されるため、都度実行する必要があります。

もしくは aws codeartifact get-authorization-token コマンドで認証トークンのみを取得し、
手動で pip config set を行なうことも可能です。

logout コマンドは用意されていないようなので、解除するには
`pip config unset global.index-url` を実行するしかなさそうです。

### 公開リポジトリのキャッシュ
試しに AWS SAM CLI をインストールしてみると CodeArtifact からダウンロードされていることがわかります。

```shell-session
$ pip install -U aws-sam-cli
Collecting aws-sam-cli
  Downloading https://my-domain-123456789012.d.codeartifact.ap-northeast-1.amazonaws.com/pypi/my-repo/simple/aws-sam-cli/0.52.0/aws_sam_cli-0.52.0-py3-none-any.whl (443kB)
```

コンソール上でも 作成したレポジトリに登録されていることがわかります。
実際はパブリックアップストリームリポジトリである pypi-store が PyPI に接続し、キャッシュしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/d6a2857f-ad07-5b22-17a7-40f37d2efe95.png)

### 独自パッケージの共有
ここでは Python Packaging User Guide のチュートリアルのために用意されている
サンプルプロジェクトを CodeArtifact に アップロードしてみます。

https://github.com/pypa/sampleproject を clone します。

```shell-session
$ git clone https://github.com/pypa/sampleproject.git
Cloning into 'sampleproject'...
remote: Enumerating objects: 21, done.
remote: Counting objects: 100% (21/21), done.
remote: Compressing objects: 100% (19/19), done.
remote: Total 441 (delta 7), reused 6 (delta 1), pack-reused 420
Receiving objects: 100% (441/441), 116.64 KiB | 365.00 KiB/s, done.
Resolving deltas: 100% (216/216), done.
```

以下のコマンドでパッケージ化します。

```shell-session
$ cd sampleproject
$ python setup.py bdist_wheel
```

Python の場合、パッケージのアップロードには twine が必要なため、インストールします。

```shell-session
$ pip install -U twine
```

login コマンドで twine の認証情報を設定します。
内部的には ~/.pypirc に CodeArtifact 接続用の設定を追記しています。

```shell-session
$ aws codeartifact login --tool twine --repository my-repo --domain my-domain
Successfully logged in to codeartifact for twine.
```

以下のコマンドで CodeArtifact にアップロードします。

```shell-session
$ twine upload -r codeartifact dist/*
Uploading distributions to https://my-domain-123456789012.d.codeartifact.ap-northeast-1.amazonaws.com/pypi/my-repo/
Uploading sampleproject-1.3.1-py3-none-any.whl
```

コンソール上でもアップロードされていることが確認できました。
独自パッケージの共有も簡単に行なうことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/5810272f-22db-9837-1f87-392681acad81.png)

## 参考
**AWS CodeArtifact 製品ページ**
https://aws.amazon.com/jp/codeartifact/
**CodeArtifact User Guide**
https://docs.aws.amazon.com/codeartifact/latest/ug/welcome.html
**Pythonで作成したライブラリを、PyPIに公開/アップロードする**
https://qiita.com/icoxfog417/items/edba14600323df6bf5e0


以上です。
参考になれば幸いです。