背景
AWSでコンテナイメージを提供するための要素の一つとして、
ECRの特定のリポジトリを特定のAWSアカウントのみアクセス可能にしたい
実現したいこと
アカウント1のECRでコンテナイメージを提供し、アカウント2からのみアクセス可能にする
方針
特定のECRリポジトリのみアクセス可能にする
ECRリポジトリにタグを設定し、ポリシーで特定のタグがついたリポジトリにのみアクセスできるよう設定する
※アクセスさせたいリポジトリが複数ある場合に設定が楽になると思われる
特定のAWSアカウントのみアクセス可能にする
上で作成したポリシーをアタッチしたロールを作成し、ロールを使用できるアカウントを指定することで、特定のAWSアカウントのみアクセスできるようにする
実現方法
アカウント1のECRに「release」と「develop」の2つのリポジトリを用意し、releaseリポジトリにのみアクセスできることを確認する
前提として、両方のリポジトリにイメージタグv.1.0のイメージを準備してある
$ aws ecr list-images --repository-name release
{
"imageIds": [
{
"imageTag": "v1.0",
"imageDigest": "sha256:255d71ecc31ed42351dbc809905360aec3421a6544759315988d26ea114363b3"
}
]
}
$ aws ecr list-images --repository-name develop
{
"imageIds": [
{
"imageTag": "v1.0",
"imageDigest": "sha256:255d71ecc31ed42351dbc809905360aec3421a6544759315988d26ea114363b3"
}
]
}
ECRリポジトリのタグ付け(アカウント1)
アクセス可能にしたいコンテナリポジトリにタグを設定する
今回は、releaseリポジトリのみアクセス可能にさせるため、releaseリポジトリにのみタグを設定する
タグは、「キー:environment、値:release」とする
IAMの設定(アカウント1)
ポリシー作成
ECRのアクセスレベルは、「リスト」と「読み込み」を指定したタグにのみ実行可能なように設定した
また、認証トークンの取得に関しては、リポジトリに設定したタグに紐付かないので、制限をかけない形で別途設定した
Jsonで表示したポリシーは以下
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ecr:GetRegistryPolicy",
"ecr:DescribeImageScanFindings",
"ecr:GetLifecyclePolicyPreview",
"ecr:DescribeRegistry",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:DescribeImages",
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetRepositoryPolicy",
"ecr:GetLifecyclePolicy"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"ecr:ResourceTag/environment": "release"
}
}
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": "ecr:GetAuthorizationToken",
"Resource": "*"
}
]
}
ロール作成
今回は別のAWSアカウントで使用するロールを作成する
※サードパーティーにロールを使用させる場合は外部ID
を使用するのがベストプラクティスとのこと
後で使うのでメモっておく
ポリシーは上で作成した「allow_ecr_release」を選択する
作成したロールの信頼関係を確認するとアカウント2のrootアカウントが対象になっている
特定のユーザを対象にしたい場合は「root」を「user/XXXXX」に書き換える
変更前
変更後
ECRからイメージのプル(アカウント2)
今回はEC2でイメージをプルするとこまで実施する。
※前提として、EC2にはAWS CLIとDockerがインストールしてある
ロールの認証情報取得
現在のアカウント情報を確認し、アカウント2であることがわかる
$ aws sts get-caller-identity
{
"Account": "{アカウント2_aws_account_id}",
"UserId": "XXXXX",
"Arn": "arn:aws:iam::{アカウント2_aws_account_id}:user/XXXXXX"
}
アカウント2でアカウント1のロールの認証情報を取得する
※ロール作成時に設定した外部ID
はここで使用する
$ aws sts assume-role --role-arn "arn:aws:iam::{アカウント1_aws_account_id}:role/allow_ecr_release" --role-session-name allow_ecr_release --external-id test
{
"AssumedRoleUser": {
"AssumedRoleId": "XXXXX:allow_ecr_release",
"Arn": "arn:aws:sts::{アカウント1_aws_account_id}:assumed-role/allow_ecr_release/allow_ecr_release"
},
"Credentials": {
"SecretAccessKey": "XXXXX",
"SessionToken": "XXXXX",
"Expiration": "2021-04-07T16:37:46Z",
"AccessKeyId": "XXXXX"
}
}
取得した認証情報を環境変数に設定する
$ export AWS_ACCESS_KEY_ID=XXXXX
$ export AWS_SECRET_ACCESS_KEY=XXXXX
$ export AWS_SESSION_TOKEN=XXXXX
現在のアカウント情報を確認し、アカウント1のallow_ecr_releaseロールになっていることがわかる
$ aws sts get-caller-identity
{
"Account": "{アカウント1_aws_account_id}",
"UserId": "XXXXX:allow_ecr_release",
"Arn": "arn:aws:sts::{アカウント1_aws_account_id}:assumed-role/allow_ecr_release/allow_ecr_release"
}
ECRへのアクセス確認
releaseリポジトリの情報のみ取得できている事がわかる
$ aws ecr describe-images --repository-name release
{
"imageDetails": [
{
"artifactMediaType": "application/vnd.docker.container.image.v1+json",
"imageSizeInBytes": 83920901,
"imageDigest": "sha256:255d71ecc31ed42351dbc809905360aec3421a6544759315988d26ea114363b3",
"imageManifestMediaType": "application/vnd.docker.distribution.manifest.v2+json",
"imageTags": [
"v1.0"
],
"registryId": "{アカウント1_aws_account_id}",
"repositoryName": "release",
"imagePushedAt": 1617543739.0
}
]
}
$ aws ecr describe-images --repository-name develop
An error occurred (AccessDeniedException) when calling the DescribeImages operation: User: arn:aws:sts::{アカウント1_aws_account_id}:assumed-role/allow_ecr_release/allow_ecr_release is not authorized to perform: ecr:DescribeImages on resource: arn:aws:ecr:{region}:{アカウント1_aws_account_id}:repository/develop
認証
ECRプライベートレジストリに対してDockerを認証させる
$ aws ecr get-login-password --region {region} | docker login --username AWS --password-stdin {アカウント1_aws_account_id}.dkr.ecr.{region}.amazonaws.com
コンテナイメージのプル
releaseリポジトリのコンテナイメージのみプルできている事がわかる
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
$ docker pull {アカウント1_aws_account_id}.dkr.ecr.{region}.amazonaws.com/release:v1.0
v1.0: Pulling from release
6e0aa5e7af40: Pull complete
d47239a868b3: Pull complete
49cbb10cca85: Pull complete
2e8c0debf4c7: Pull complete
0f33714d40be: Pull complete
1290c8a7c595: Pull complete
Digest: sha256:255d71ecc31ed42351dbc809905360aec3421a6544759315988d26ea114363b3
Status: Downloaded newer image for {アカウント1_aws_account_id}.dkr.ecr.{region}.amazonaws.com/release:v1.0
{アカウント1_aws_account_id}.dkr.ecr.{region}.amazonaws.com/release:v1.0
$ docker pull {アカウント1_aws_account_id}.dkr.ecr.{region}.amazonaws.com/develop:v1.0
Error response from daemon: pull access denied for {アカウント1_aws_account_id}.dkr.ecr.{region}.amazonaws.com/develop, repository does not exist or may require 'docker login': denied: User: arn:aws:sts::{アカウント1_aws_account_id}:assumed-role/allow_ecr_release/allow_ecr_release is not authorized to perform: ecr:BatchGetImage on resource: arn:aws:ecr:{region}:{アカウント1_aws_account_id}:repository/develop
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
{アカウント1_aws_account_id}.dkr.ecr.{region}.amazonaws.com/release v1.0 935e47d46598 5 days ago 196MB
最後に
検証した後にクロスアカウントレプリケーションができることを知った。。。