What's?
- 2020年6月に登場した、AWS CodeArtifactを使ってみたい
- そもそも、AWS CodeArtifactとはどういうものか?
- 試しに使ってみる
ということを調べたり、やってみたりする記事です。
最後の「使ってみる」の部分には、Apache Mavenを利用します。つまり、Javaでのサンプルということになりますね。
AWS CodeArtifactとは
AWSの提供する、マネージドなアーティファクトリポジトリサービスです。
AWS CodeArtifact Documentation
AWS CodeArtifact によるソフトウェアパッケージ管理
AWSがソフトウェアパッケージのリポジトリサービス「AWS CodeArtifact」正式リリース。npmやMavenなどのパッケージを共有可能
平たく言うと、ソースコードをビルドしたりして生成された、パッケージを管理してくれるものになります。
対応しているのは、このあたりですね。
- npm
- PyPI
- Maven
AWS CodeArtifact Concepts / Package
要するに、JavaScript、Python、Java、の3つですと。
AWS CodeArtifactを使わない場合は、以下のような選択肢から環境を構築していることかと思います(GitHub Packagesは違いますが)。
この管理を、AWSに任せることができるというサービスですね。
AWS CodeArtifactにおける要素
「AWSが提供するマネージドなパッケージリポジトリだ」と書くとあっさりしていますが、いろいろと概念、要素があるようなので理解しておく必要がありそうですね。
順にちょっと見ていってみましょう。
概要自体は、こちらに書いてあります。
リポジトリ
パッケージをまとめたもので、おそらく他のパッケージマネージャーを知っていると、1番理解のしやすい概念かと。
AWS CodeArtifact Concepts / Repository
リポジトリは、各種パッケージマネージャーのクライアントツール(npm、PyPI、Mavenなど)のエンドポイントとなります。
アクセス制御を行うためのポリシーを設定することもできます。
また、リポジトリはPolyglotであり、複数の言語で利用することができます。言語ごとにリポジトリを作らなくても良い、と言っていますね。
リポジトリは、後述のドメイン内に作ることになります。ドメインなしのリポジトリは存在できません。
You cannot create a repository without a domain. When you use the CreateRepository API to create a repository, you must specify a domain name. You cannot move a repository from one domain to another.
また、アップストリームのリポジトリも持つことができたり、外部リポジトリへの接続を行うことができます。
外部接続を追加すると、AWS CodeArtifactリポジトリにパッケージがない場合に、パブリックなnpm RegistryやMaven Repositoryなどの外部リポジトリからパッケージを取得することができます。
パッケージ / パッケージバージョン / アセット
パッケージは、パッケージマネージャーを使ってソフトウェアをインストールするために必要となるメタデータです。
AWS CodeArtifact Concepts / Package
また、パッケージを構成するアセット(.tgz
ファイルやJAR
ファイルなど)を含めたものが、パッケージバージョンです。
AWS CodeArtifact Concepts / Package version
AWS CodeArtifact Concepts / Asset
ドメイン
リポジトリを集約する概念のようです。
AWS CodeArtifact Concepts / Domain
パッケージのアセットとメタデータの保存先は、実はリポジトリではなくドメインです。ドメイン内にいくつリポジトリがあっても、ドメイン内に同じバージョン、アセットのパッケージは1回だけ保存されます。
また、AWS KMSを使った暗号化も行われます。
パッケージの取得は、リポジトリを介して行うことになります。
ドメインはアカウント内で複数持つことができますが、通常は単一のドメインを勧めているようです。
Although an organization can have multiple domains, we recommend a single production domain that contains all published artifacts so that teams can find and share packages across their organization.
ドメインの内容を見ると
- リポジトリのストレージ+暗号化
- リポジトリ間のメタデータのコピー(※アップストリームリポジトリに関連)
- アクセス管理(リポジトリにアクセスすることができるアカウント制限や、ポリシーの管理)
- リポジトリの名前空間の提供
といったところがドメインの主な機能なようですね。
アップストリームリポジトリ
AWS CodeArtifact Concepts / Upstream repository
アップストリームリポジトリに関しては、個別のドキュメントを見た方がわかりやすい気がします。
Working with upstream repositories in CodeArtifact
AWS CodeArtifactリポジトリが、他のAWS CodeArtifactリポジトリをアップストリーム(上流)のリポジトリにすることができる、というものです。
こういう使い方も可能みたいですね。
If an upstream repository has an external connection to a public repository, the repositories that are downstream from it can pull packages from that public repository. For example, suppose that the repository my-repo has an upstream repository named upstream, and upstream has an external connection to a public npm repository. In this case, a package manager that is connected to my-repo can pull packages from the npm public repository.
アップストリームリポジトリに対してパブリックな外部リポジトリへの接続を定義し、ダウンストリームリポジトリからアップストリームリポジトリ経由でパブリックリポジトリからパッケージを取得する、といったケースですね。
始め方(ざっくり)
AWS CodeArtifactの使う時のざっくりした流れを書きます。
まあ、ここのまとめなんですけど。
Getting started using the AWS CLI
AWS CodeArtifact側
- ドメインを作成する
- リポジトリを作成する
外部リポジトリへの接続定義は、任意でしょう。
パッケージマネージャーのクライアント側
- AWS CodeArtifactへログインする
- パッケージマネージャーのクライアントの設定に、リポジトリの情報を追加する
- 使う
最初にログインがあるのがポイントで、トークンを発行して環境変数に設定する、などの手順を踏む必要があります。
Configure pip without the login command
Using Maven / Pass an auth token using an environment variable
使ってみる
と、前置きはこれくらいにして、そろそろ使っていってみましょう。
AWS CodeArtifactでリポジトリを作って、Java(Maven)で使ってみる、というのを今回のシナリオにしてみます。
今回の環境は、こちらです。
$ aws --version
aws-cli/2.0.34 Python/3.7.3 Linux/4.15.0-112-generic botocore/2.0.0dev38
AWSのクレデンシャルは、環境変数で設定しているものとします。
$ export AWS_ACCESS_KEY_ID=.....
$ export AWS_SECRET_ACCESS_KEY=.....
$ export AWS_DEFAULT_REGION=.....
AWS CodeArtifactのリポジトリを作る
こちらを参考に。
Getting started using the AWS CLI
なお、普段ならこの手のものはTerraformで構築するのですが、TerraformがまだAWS CodeArtifactには対応していないので、AWS CLIでやっていきます。
(余談)Terraformでのサポートに関するissue
Add AWS CodeArtifact service support
AWS CLIでの、AWS CodeArtifactに関するリファレンスはこちら。
最初に、AWS KMS CMKを作成します。
$ aws kms create-key
$ aws kms create-alias --alias-name alias/code-artifact-key --target-key-id [作成したAWS KMS(CMK)のARN]
今回は、専用のキーにしました。キーを指定しない場合は、AWSが管理するキーが使われるようです。
そして、このCMKを使ってドメインを作ります。ドメイン名は、ドキュメントのそのままですが、my-domain
にしました。
$ aws codeartifact create-domain --domain my-domain --encryption-key alias/code-artifact-key
次に、リポジトリを作成します。リポジトリを作成するには、ドメイン名を指定する必要があります。
$ aws codeartifact create-repository --domain my-domain --repository my-repo
リポジトリ名も、ドキュメントそのままmy-repo
にしました。
ドキュメントにある-domain-owner
というオプションは完全に無視しましたが、今回はそのまま作成したAWSアカウントIDが使われます。
ドキュメントでは、他にも外部リポジトリへの接続やアップストリームなどの例がありますが、今回はここまでで。
作成したドメイン、リポジトリの情報を確認してみましょう。
$ aws codeartifact describe-domain --domain my-domain
{
"domain": {
"name": "my-domain",
"owner": "[AWSアカウントID]",
"arn": "arn:aws:codeartifact:ap-northeast-1:[AWSアカウントID]:domain/my-domain",
"status": "Active",
"createdTime": "2020-07-26T14:32:35.003000+09:00",
"encryptionKey": "arn:aws:kms:ap-northeast-1:[AWSアカウントID]:key/a6529646-1a8a-4772-a28a-b62c1e82992c",
"repositoryCount": 1,
"assetSizeBytes": 0
}
}
$ aws codeartifact describe-repository --domain my-domain --repository my-repo
{
"repository": {
"name": "my-repo",
"administratorAccount": "[AWSアカウントID]",
"domainName": "my-domain",
"domainOwner": "[AWSアカウントID]",
"arn": "arn:aws:codeartifact:ap-northeast-1:[AWSアカウントID]:repository/my-domain/my-repo",
"upstreams": [],
"externalConnections": []
}
}
これで、準備は完了です。
Mavenから使う
では、Mavenから使ってみましょう。
ドキュメントは、こちらを参考に。
今回の環境は、こちらです。
$ java --version
openjdk 11.0.8 2020-07-14
OpenJDK Runtime Environment (build 11.0.8+10-post-Ubuntu-0ubuntu118.04.1)
OpenJDK 64-Bit Server VM (build 11.0.8+10-post-Ubuntu-0ubuntu118.04.1, mixed mode, sharing)
$ mvn --version
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Maven home: $HOME/.sdkman/candidates/maven/current
Java version: 11.0.8, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "4.15.0-112-generic", arch: "amd64", family: "unix"
こちらを見ながら、やっていってきましょう。
settings.xml
の作成と、認証トークンの取得
まずはsettings.xml
を用意します。今回は、このサンプル専用に作成することにしました。
settings.xml
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
https://maven.apache.org/xsd/settings-1.0.0.xsd">
<servers>
<server>
<id>codeartifact</id>
<username>aws</username>
<password>${env.CODEARTIFACT_TOKEN}</password>
</server>
</servers>
</settings>
ユーザー名はaws
みたいですね。パスワードは、環境変数として設定します。
こんな感じですね。
$ export CODEARTIFACT_TOKEN=`aws codeartifact get-authorization-token --domain my-domain --query authorizationToken --output text`
Pass an auth token using an environment variable
注意事項にもありますが、この認証トークンの有効期限は最大で12時間だそうです。これが切れると、都度取得する必要があります。
CodeArtifact authorization tokens are valid for a default period of 12 hours. You can change how long a token is valid using the --durationSeconds argument (max authorization period is 12 hours). When the authorization period expires, you must call get-authorization-token to get another token. The authorization period begins after get-authorization-token is called.
毎日取得してね、という感じですね。
アーティファクトをリポジトリにアップロードする
続いて、アーティファクトをリポジトリにアップロードしてみます。というわけで、簡単なライブラリを作ってみましょう。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.charon.r13b</groupId>
<artifactId>library</artifactId>
<version>0.0.1</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<repositories>
<repository>
<id>codeartifact</id>
<name>codeartifact</name>
<url>https://my-domain-[AWSアカウントID].d.codeartifact.ap-northeast-1.amazonaws.com/maven/my-repo/</url>
</repository>
</repositories>
<distributionManagement>
<repository>
<id>codeartifact</id>
<name>codeartifact</name>
<url>https://my-domain-[AWSアカウントID].d.codeartifact.ap-northeast-1.amazonaws.com/maven/my-repo</url>
</repository>
</distributionManagement>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>
</dependencies>
</project>
今回の例ではrepositories/repository
は不要なのですが、なんとなく。少なくとも、distributionManagement
の方のrepository
があればOKです。
Apache Commons Langは、なんとなく依存する外部ライブラリとして使っておきました。
ドキュメントを見た時の以下のURLの解釈に迷ったのですが、
<url>https://my-domain-domain-owner-id.d.codeartifact.us-west-2.amazonaws.com/maven/my-repo/</url>
こう読めばいいんですね。
<url>https://[AWS CodeArtifactのドメイン名]-[ドメインのOwner id(AWSアカウントID)].d.codeartifact.[リージョン].amazonaws.com/maven/[リポジトリ名]/</url>
あとは、mvn deploy
で。今回は、settings.xml
はオプションで指定しています。
$ mvn deploy -s settings.xml
BUILD SUCCESS
になれば、アーティファクトがアップロードされているので、確認してみましょう。
$ aws codeartifact list-packages --domain my-domain --repository my-repo
{
"packages": [
{
"format": "maven",
"namespace": "com.github.charon.r13b",
"package": "library"
}
]
}
OKです。
アップロードされたアーティファクトを使ってみる
最後に、アップロードされたアーティファクトを使ってみます。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.charon.r13b</groupId>
<artifactId>app</artifactId>
<version>0.0.1</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<repositories>
<repository>
<id>codeartifact</id>
<name>codeartifact</name>
<url>https://my-domain-[AWSアカウントID].d.codeartifact.ap-northeast-1.amazonaws.com/maven/my-repo/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.github.charon.r13b</groupId>
<artifactId>library</artifactId>
<version>0.0.1</version>
</dependency>
</dependencies>
</project>
こちらは利用側なので、repositories/repository
の定義があればOKです。
<repositories>
<repository>
<id>codeartifact</id>
<name>codeartifact</name>
<url>https://my-domain-[AWSアカウントID].d.codeartifact.ap-northeast-1.amazonaws.com/maven/my-repo/</url>
</repository>
</repositories>
depencencies/dependency
には、先ほどアップロードしたアーティファクトを含めています。
<dependencies>
<dependency>
<groupId>com.github.charon.r13b</groupId>
<artifactId>library</artifactId>
<version>0.0.1</version>
</dependency>
</dependencies>
サンプルコードは、こんな感じで。
src/main/java/com/github/charon/r13b/app/App.java
package com.github.charon.r13b.app;
import com.github.charon.r13b.library.MessageService;
public class App {
public static void main(String... args) {
MessageService messageService = new MessageService("★★★", "★★★");
System.out.println(messageService.decorate("Hello World!!"));
}
}
ビルドして、実行。settings.xml
は、アーティファクトをアップロードした時に使ったものと、同じものを使用しています。
$ mvn compile exec:java -s settings.xml -Dexec.mainClass=com.github.charon.r13b.app.App
実行できました、と。
[INFO] --- exec-maven-plugin:1.6.0:java (default-cli) @ app ---
★★★Hello World!!★★★
なお、認証トークンがない状態だと、401
になるのでアーティファクトを使うのにも認証が必要ですよ、と。
[ERROR] Failed to execute goal on project app: Could not resolve dependencies for project com.github.charon.r13b:app:jar:0.0.1: Failed to collect dependencies at com.github.charon.r13b:library:jar:0.0.1: Failed to read artifact descriptor for com.github.charon.r13b:library:jar:0.0.1: Could not transfer artifact com.github.charon.r13b:library:pom:0.0.1 from/to codeartifact (https://my-domain-[AWSアカウントID].d.codeartifact.ap-northeast-1.amazonaws.com/maven/my-repo/): Authentication failed for https://my-domain-[AWSアカウントID].d.codeartifact.ap-northeast-1.amazonaws.com/maven/my-repo/com/github/charon/r13b/library/0.0.1/library-0.0.1.pom 401 Unauthorized
## ココ
401 Unauthorized
これで、確認ができました。
ポリシーについて
今回、利用したIAMユーザーがAdministratorAccess
ポリシーを持っていたのでなんでもやれているのですが、実際にはIAMユーザーでアーティファクトのアップロードの可否、参照の可否などを設定していくことになると思います。
ドメイン、リポジトリにそれぞれ設定できるので、見ておきましょう。
後片付け
最後に作成したリソースの後片付けをしておきます。
リポジトリとドメインの削除。
$ aws codeartifact delete-repository --domain my-domain --repository my-repo
$ aws codeartifact delete-domain --domain my-domain
AWS KMSのCMKの削除。
$ aws kms delete-alias --alias-name alias/code-artifact-key
$ aws kms schedule-key-deletion --key-id [AWS KMS(CMK)のキーID]