AWS

CFNを使用してECRリポジトリポリシー入門

スポンサーリンク
CloudFormationを使用してECRリポジトリポリシー入門 AWS
スポンサーリンク
スポンサーリンク

CloudFormationを使用してECRリポジトリポリシー入門

ECRリポジトリはリソースベースのポリシーを設定することができます。

本ページでは、リポジトリポリシーを設定し、イメージのプッシュ/プルを制限することを目指します。

構築する環境

Diagram of introduction to ECR Repository Policies using CFN

ECRを作成します。
ECRリポジトリポリシーを設定し、リポジトリに対するイメージのプッシュ/プルを制限します。

プライベートサブネット内にEC2インスタンスを3つ作成します。
インスタンスは最新版のAmazon Linux 2とします。
3台は同様の設定を行いますが、リポジトリポリシーによって、以下の動作を実現します。

  • EC2インスタンス1:イメージのプッシュを許可する
  • EC2インスタンス2:イメージのプルを許可する
  • EC2インスタンス3:イメージのプッシュ/プルを許可しない

CloudFormationテンプレートファイル

上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。

awstut-fa/085 at main · awstut-an-r/awstut-fa
Contribute to awstut-an-r/awstut-fa development by creating an account on GitHub.

テンプレートファイルのポイント解説

EC2

Resources: Instance1: Type: AWS::EC2::Instance Properties: IamInstanceProfile: !Ref InstanceProfile1 ImageId: !Ref ImageId InstanceType: !Ref InstanceType NetworkInterfaces: - DeviceIndex: 0 SubnetId: !Ref InstanceSubnet GroupSet: - !Ref InstanceSecurityGroup UserData: !Ref UserData Instance2: Type: AWS::EC2::Instance Properties: ... Instance3: Type: AWS::EC2::Instance Properties: ...
Code language: YAML (yaml)

3台のEC2インスタンスを作成します。
全て同様の設定を行います。

インスタンス作成時に、ユーザデータを使用して、初期化処理を行います。
今回は以下の処理を実行します。

#!/bin/bash -xe yum update -y amazon-linux-extras install docker systemctl start docker usermod -a -G docker ec2-user
Code language: Bash (bash)

Dockerをインストール後、これを起動し、ec2-userの権限でDockerコマンドを実行できるようにします。

以下がインスタンス用のIAMロールです。

Resources: InstanceRole1: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: sts:AssumeRole Principal: Service: - ec2.amazonaws.com ManagedPolicyArns: - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess InstanceRole2: Type: AWS::IAM::Role Properties: ... InstanceRole3: Type: AWS::IAM::Role Properties: ...
Code language: YAML (yaml)

各インスタンス用にIAMロールを作成します。
全て同様の設定を行います。

ポイントはAWS管理ポリシー「AmazonEC2ContainerRegistryFullAccess」をアタッチする点です。
つまりこれらのIAMロールをアタッチすることによって、3台のインスタンスはECRリポジトリにイメージをプッシュ/プルする権限が付与されるということです。

ECR

Resources: ECRRepository: Type: AWS::ECR::Repository Properties: RepositoryName: !Ref Prefix RepositoryPolicyText: Version: 2012-10-17 Statement: - Effect: Deny Principal: "*" NotAction: - ecr:BatchCheckLayerAvailability - ecr:CompleteLayerUpload - ecr:InitiateLayerUpload - ecr:PutImage - ecr:UploadLayerPart Condition: ArnEquals: aws:PrincipalArn: !Ref InstanceRoleArn1 - Effect: Deny Principal: "*" NotAction: - ecr:BatchGetImage - ecr:GetDownloadUrlForLayer Condition: ArnEquals: aws:PrincipalArn: !Ref InstanceRoleArn2 - Effect: Deny Principal: "*" Action: "*" Condition: ArnNotEquals: aws:PrincipalArn: - !Ref InstanceRoleArn1 - !Ref InstanceRoleArn2
Code language: YAML (yaml)

RepositoryPolicyTextプロパティでリポジトリポリシーを設定します。

リポジトリポリシーは3つのステートメントで構成されています。

1つ目のステートメントはEC2インスタンス1用です。
Condition要素でArnEqualsおよびaws:PrincipalArnを使用して、EC2インスタンス1にアタッチしたIAMロールのARNを指定します。
Effect要素に「Deny」を指定した上で、NotAction要素を使用することによって、NotActionで指定されたアクション以外を拒否することになります。
NotActionにはイメージプッシュに必要なアクションを指定しましたので、インスタンス1はプッシュ以外のアクションが拒否されるということです。

2つ目のステートメントはEC2インスタンス2用です。
1つ目と同様の記法で、EC2インスタンス2にイメージプル以外のアクションを拒否します。

3つ目のステートメントは上記以外のリソースからアクセス用です。
Condition要素でArnNotEqualsおよびaws:PrincipalArnを使用して、上述の2つのIAMロールのARNを指定し、これら以外のリソースを対象とします。
Effect要素に「Deny」を、Actionに「*」を指定することによって、全てのアクションを拒否することになります。
つまり2つのEC2インスタンス以外のアクセスの場合は、全て拒否されるということです。

環境構築

CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。

CloudFormationスタックを作成し、スタック内のリソースを確認する

CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。

各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。

  • ECRリポジトリ:fa-085
  • EC2インスタンス1:i-0bde1cc6fc498a208
  • EC2インスタンス2:i-0296e9a1b5f70b522
  • EC2インスタンス3:i-0d0cc36a5186db23b

作成されたリソースをAWS Management Consoleから確認します。
ECRを確認します。

Detail of ECR Repository 1.

正常にECRリポジトリが作成されています。

続いてECRのリポジトリポリシーを確認します。

Detail of ECR Repository Policy 1.

CloudFormationテンプレートで定義した通りに、リポジトリポリシーが作成されていることがわかります。

ECRにイメージをプッシュするためのコマンドを確認します。

Detail of ECR Image Push Command.

このコマンドを3つのEC2インスタンスで実行して、イメージのプッシュを試みます。

動作確認

EC2インスタンス1

準備が整いましたので、EC2インスタンス1にアクセスします。
インスタンスへのアクセスはSSM Session Managerを使用します。

% aws ssm start-session --target i-0bde1cc6fc498a208 Starting session with SessionId: root-0c908f28046ae77b1 sh-4.2$
Code language: Bash (bash)

SSM Session Managerの詳細につきましては、以下のページをご確認ください。

操作するユーザを変更します。

sh-4.2$ sudo su --login ec2-user [ec2-user@ip-10-0-2-38 ~]$
Code language: Bash (bash)

SSM Session Managerのデフォルトユーザであるssm-userから、ec2-userに切り替えました。
これでec2-userの権限で、Dockerコマンドを実行することができます。

検証用のDockerfileを作成後、ECRリポジトリにイメージをプッシュするコマンドを実行します。

[ec2-user@ip-10-0-2-38 ~]$ echo "FROM amazonlinux" > Dockerfile [ec2-user@ip-10-0-2-38 ~]$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin [account-id].dkr.ecr.ap-northeast-1.amazonaws.com ... Login Succeeded [ec2-user@ip-10-0-2-38 ~]$ docker build -t fa-085 . Sending build context to Docker daemon 11.26kB Step 1/1 : FROM amazonlinux latest: Pulling from library/amazonlinux 12df598bc31e: Pull complete Digest: sha256:cb8a67164376ecca3b9993e6bb7d81dd868b7836d2631582becd140c8edf27bf Status: Downloaded newer image for amazonlinux:latest ---> 06c59c262be8 Successfully built 06c59c262be8 Successfully tagged fa-085:latest [ec2-user@ip-10-0-2-38 ~]$ docker tag fa-085:latest [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085:latest [ec2-user@ip-10-0-2-38 ~]$ docker push [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085:latest The push refers to repository [[account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085] bb99a8750875: Pushed latest: digest: sha256:ab12022e1a7cd318058af138291d638b1024dcb9844799e8014e6e37d0b35831 size: 529
Code language: Bash (bash)

イメージをプッシュすることができました。

Detail of ECR Repository 2.

確かにイメージがプッシュされていることがわかります。
このようにリポジトリポリシーに従って、EC2インスタンス1からイメージをプッシュすることができました。

続いてイメージのプルを試みます。

[ec2-user@ip-10-0-2-38 ~]$ docker pull [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085:latest Error response from daemon: pull access denied for [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085, repository does not exist or may require 'docker login': denied: User: arn:aws:sts::[account-id]:assumed-role/fa-085-EC2Stack-16BBODB5DWYO1-InstanceRole1-YILWRMUJ51EE/i-0bde1cc6fc498a208 is not authorized to perform: ecr:BatchGetImage on resource: arn:aws:ecr:ap-northeast-1:[account-id]:repository/fa-085 with an explicit deny in a resource-based policy
Code language: Bash (bash)

イメージプルに失敗しました。
EC2インスタンス1にアタッチしたIAMロールでは、ECRへのフルアクセスを許可しています。
しかしリポジトリポリシーによって、プッシュ以外のアクションは拒否されたということです。

EC2インスタンス2

同様の方法でインスタンス2も動作確認を行います。
まずイメージをプルします。

% aws ssm start-session --target i-0296e9a1b5f70b522 Starting session with SessionId: root-0ce11bf400c04ba6d sh-4.2$ sh-4.2$ sudo su --login ec2-user [ec2-user@ip-10-0-2-59 ~]$ [ec2-user@ip-10-0-2-59 ~]$ docker pull [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085:latest latest: Pulling from fa-085 12df598bc31e: Pull complete Digest: sha256:ab12022e1a7cd318058af138291d638b1024dcb9844799e8014e6e37d0b35831 Status: Downloaded newer image for [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085:latest [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085:latest [ec2-user@ip-10-0-2-59 ~]$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085 latest 06c59c262be8 3 weeks ago 194MB
Code language: Bash (bash)

イメージをプルすることができました。

次にイメージのプッシュを試みます。

[ec2-user@ip-10-0-2-59 ~]$ echo "FROM amazonlinux" > Dockerfile [ec2-user@ip-10-0-2-59 ~]$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin [account-id].dkr.ecr.ap-northeast-1.amazonaws.com ... Login Succeeded [ec2-user@ip-10-0-2-59 ~]$ docker build -t fa-085 . Sending build context to Docker daemon 11.26kB Step 1/1 : FROM amazonlinux latest: Pulling from library/amazonlinux Digest: sha256:cb8a67164376ecca3b9993e6bb7d81dd868b7836d2631582becd140c8edf27bf Status: Downloaded newer image for amazonlinux:latest ---> 06c59c262be8 Successfully built 06c59c262be8 Successfully tagged fa-085:latest [ec2-user@ip-10-0-2-59 ~]$ docker tag fa-085:latest [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085:latest [ec2-user@ip-10-0-2-59 ~]$ docker push [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085:latest The push refers to repository [[account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085] bb99a8750875: Retrying in 1 second EOF
Code language: Bash (bash)

ECRリポジトリにイメージをプッシュするコマンドを実行した結果、プッシュ時にタイムアウトして失敗しました。
EC2インスタンス2にアタッチしたIAMロールでも、ECRへのフルアクセスを許可しています。
しかしリポジトリポリシーによって、プル以外のアクションは拒否されたということです。

EC2インスタンス3

最後にインスタンス3も動作確認を行います。
まずイメージのプッシュを試みます。

% aws ssm start-session --target i-0d0cc36a5186db23b Starting session with SessionId: root-0dbc2ca03d6941d57 sh-4.2$ sh-4.2$ sudo su --login ec2-user [ec2-user@ip-10-0-2-67 ~]$ [ec2-user@ip-10-0-2-67 ~]$ echo "FROM amazonlinux" > Dockerfile [ec2-user@ip-10-0-2-67 ~]$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin [account-id].dkr.ecr.ap-northeast-1.amazonaws.com ... Login Succeeded [ec2-user@ip-10-0-2-67 ~]$ docker build -t fa-085 . Sending build context to Docker daemon 11.26kB Step 1/1 : FROM amazonlinux latest: Pulling from library/amazonlinux 12df598bc31e: Pull complete Digest: sha256:cb8a67164376ecca3b9993e6bb7d81dd868b7836d2631582becd140c8edf27bf Status: Downloaded newer image for amazonlinux:latest ---> 06c59c262be8 Successfully built 06c59c262be8 Successfully tagged fa-085:latest [ec2-user@ip-10-0-2-67 ~]$ docker tag fa-085:latest [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085:latest [ec2-user@ip-10-0-2-67 ~]$ docker push [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085:latest The push refers to repository [[account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085] bb99a8750875: Retrying in 1 second EOF
Code language: Bash (bash)

プッシュに失敗しました。

続いてイメージのプルを試みます。

[ec2-user@ip-10-0-2-67 ~]$ docker pull [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085:latest Error response from daemon: pull access denied for [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085, repository does not exist or may require 'docker login': denied: User: arn:aws:sts::[account-id]:assumed-role/fa-085-EC2Stack-16BBODB5DWYO1-InstanceRole3-12LD37CD8F85G/i-0d0cc36a5186db23b is not authorized to perform: ecr:BatchGetImage on resource: arn:aws:ecr:ap-northeast-1:[account-id]:repository/fa-085 with an explicit deny in a resource-based policy
Code language: Bash (bash)

プルも失敗しました。
EC2インスタンス3にアタッチしたIAMロールでも、ECRへのフルアクセスを許可しています。
しかしリポジトリポリシーによって、プッシュ/プルのアクションは拒否されたということです。

まとめ

ECRリポジトリポリシーの設定方法を確認しました。

タイトルとURLをコピーしました