AppRunnerでサービスを立ち上げるときに、ECRのプライベートリポジトリのイメージを指定することができます。
今回は、指定先のECRリポジトリにアクセス制限されている場合の設定方法を中心に、AppRunnerの使い方を説明したいと思います。
ターゲット
- AppRunnerを使ってみたい
- ポリシーでアクセス制限が設定されたECRリポジトリを使用したい
- AppRunnerでサービスを立ち上げようとすると、イメージのpullで失敗する
要約
- AppRunnerのサービスロールは、AWS CLIからのみ作成できる(2021年7月8日現在)
- イメージのpullで失敗するときは、ECRリポジトリのポリシーでサービスロールが拒否されていないか確認する
- サービスロールの許可は、ロールを委任したセッションを許可する必要がある
準備
AppRunnerのサービス作成のために必要な資材や環境を準備します。
プログラムによるアクセスが可能なIAMユーザーを作成
AWSマネジメントコンソールより、「プログラムからのアクセス」が可能かつIAMとECRにアクセスできるIAMユーザーを作成してください。
ユーザー名を良しなに決めて「プログラムからのアクセス」にチェックして、「次のステップ:アクセス制限」に進みます。
CLIからロールの作成やユーザーID・ロールIDの確認を行うので、IAMFullAccess
をアタッチします。
また、ECRを操作するためにAmazonEC2ContainerRegistryPowerUser
をアタッチします。
その後は、「次のステップ:タグ」を飛ばして「次のステップ:確認」まで進みます。
赤枠の条件を確認してください。
間違いがなければ「ユーザーを作成」をしてください。
AWS CLIからのログインにアクセスキーとシークレットキーが必要なので、csvをダウンロードしてください。
※シークレットキーは後から確認できませんので、必ず保管してください。
ECRの準備
ECRでプライベートリポジトリ作成
AppRunnerで使用するコンテナイメージのために、ECRにプライベートリポジトリを作成してください。
例では、東京リージョン(ap-northeast-1)に作成しています。
ECRリポジトリにアクセス制限を設定(ポリシー)
作成したリポジトリにポリシーを設定することで、アクセス制限を行います。
以下の例では、先ほど作成したIAMユーザー以外は明示的に拒否するポリシーを設定します。
左のナビゲーションペインから「Permissions」を押下します。
「ポリシーJOSNの編集」を押下して、以下のポリシーを設定してください。
<アカウントID>と<ユーザ名>を置き換えて使用してください。
※rootユーザは必ず含めてください。
アカウントIDの確認方法
マネジメントコンソールからIAMを開いて、赤枠の部分にある数字12桁がアカウントIDです。 ![スクリーンショット 2021-07-07 120432_edit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1166959/7e2dbb04-37c4-2d1c-f172-d2d02c96a715.png){
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyOthers",
"Effect": "Deny",
"NotPrincipal": {
"AWS": [
"arn:aws:iam::<アカウントID>:root",
"arn:aws:iam::<アカウントID>:user/<ユーザ名>"
]
},
"Action": "ecr:*"
}
]
}
以下の通りになっていれば、IAMエンティティに指定されているユーザー以外へのアクセス制限は完了です。
コンテナイメージを準備
コンテナイメージを作成
今回は、AppRunnerを作成時に正しく動作しているかを確認するため、簡単なWebアプリをコンテナ化します。
Webアプリを構築する ~ Dockerfileを作成を参考に、Dockerfileを作成しましょう。
コンテナイメージをECRリポジトリにプッシュ
初めに、ECRリポジトリからプッシュコマンドを確認します。
IAMユーザーを作成した際にダウンロードしたcsvから、アクセスキーとシークレットキーの情報を使用して、AWS CLIでログインするアカウント情報を設定します。
$ aws configure
AWS Access Key ID:<Access key ID>
AWS Secret Access Key:<Secret access key>
Default region name:<リージョン>
Default output format:json
プッシュコマンドの1.
を使用して、ログインを行います。
$ aws ecr get-login-password --region <リージョン> | docker login --username AWS --password-stdin <アカウントID>.dkr.ecr.<リージョン>.amazonaws.com
作成したDockerfileをプッシュコマンドの2.
を使用して、ビルドします。
$ docker build -t <ECRリポジトリ名> .
Dockerのコンテナイメージをプッシュコマンドの3.
を使用して、タグの付け替えをします。
$ docker tag <ECRリポジトリ名>:latest <アカウントID>.dkr.ecr.<リージョン>.amazonaws.com/<ECRリポジトリ名>:latest
タグ付けしたコンテナイメージをECRリポジトリにプッシュします。
$ docker push <アカウントID>.dkr.ecr.<リージョン>.amazonaws.com/<ECRリポジトリ名>:latest
以下のように、全てのレイヤーがプッシュされれば成功です。
The push refers to repository [<アカウントID>.dkr.ecr.<リージョン>.amazonaws.com/<ECRリポジトリ名>]
245acaaf78bf: Pushed
6369640f9374: Pushed
8c67849326e8: Pushed
5f70bf18a086: Pushed
b5afd022688e: Pushed
fef4ad87ab4f: Pushed
3286e333a984: Pushed
da654bc8bc80: Pushed
4ef81dc52d99: Pushed
909e93c71745: Pushed
7f03bfe4d6dc: Pushed
latest: digest: sha256:340f985e6c8efbbc2315d6310df7660cf0c641a6e60da04a3e79f28d25b5ae33 size: 2627
マネジメントコンソールからも確認できます。
AppRunnerのサービスロール作成
AppRunner用のサービスロールは、AWS CLIからのみ作成できます。(2021年7月8日現在)
任意のフォルダに以下の内容でJSONファイルを作成します。
ファイル名は自由です。(次のコマンドでファイル名を使用します。)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "build.apprunner.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
JSONファイルと同じ場所で、以下のコマンドを実行してサービスロールを作成します。
<ロール名>は自由です。(例:AppRunnerECRAccessRole)
$ aws iam create-role --role-name <ロール名> --path /service-role/ --assume-role-policy-document file://<JSONファイル名>
上記で作成したサービスロールにECRへのアクセス権限を与えるために、ポリシーをアタッチします。
今回は、AWSで予め用意されているAWSAppRunnerServicePolicyForECRAccess
を使用します。
$ aws iam attach-role-policy --role-name <ロール名> --policy-arn arn:aws:iam::aws:policy/service-role/AWSAppRunnerServicePolicyForECRAccess
以下の2つのコマンドで、それぞれサービスロールが作成されていることと、適用済みのポリシーを確認できます。
$ aws iam get-role --role-name <ロール名>
{
"Role": {
"Path": "/service-role/",
"RoleName": "<ロール名>",
"RoleId": "AROAxxxxxxxxxxxxxxxxx",
"Arn": "arn:aws:iam::<アカウントID>:role/service-role/<ロール名>",
"CreateDate": "2021-07-08T07:21:46+00:00",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "build.apprunner.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
},
"MaxSessionDuration": 3600,
"RoleLastUsed": {}
}
}
$ aws iam list-attached-role-policies --role-name <ロール名>
{
"AttachedPolicies": [
{
"PolicyName": "AWSAppRunnerServicePolicyForECRAccess",
"PolicyArn": "arn:aws:iam::aws:policy/service-role/AWSAppRunnerServicePolicyForECRAccess"
}
]
}
ECRリポジトリでサービスロールをアクセス制限対象から除外
作成したサービスロールをECRリポジトリにアクセス制限対象から除外します。
最初にポリシーを設定したときと同様に、ECRリポジトリのPermissionsから「ポリシーJOSNの編集」を押下して、以下のポリシーを設定してください。
※<ロールID>は、`$ aws iam get-role --role-name <ロール名>`で確認できます。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyOthers",
"Effect": "Deny",
"NotPrincipal": {
"AWS": [
"arn:aws:iam::<アカウントID>:root",
"arn:aws:iam::<アカウントID>:user/<ユーザ名>"
]
},
"Action": "ecr:*",
+ "Condition": {
+ "StringNotLike": {
+ "aws:userid": "<ロールID>:*"
+ }
+ }
}
]
}
NotPrincipal
にロールのARNを指定せずにCondition
を利用する理由は、aws:userid
で指定している文字列からわかる通り、ロールID以降の文字列が一意に特定できないためです。
その部分はセッションIDとなっています。AppRunnerを立ち上げる際にbuild.apprunner.amazonaws.com
にサービスロールが委任されますが、その時のセッションIDはランダムです。そのため、*
(ワイルドカード)を使用できないNotPrincipal
では意図した設定を出来ませんので、代わりにCondition
でロールIDを文字列比較して判定しています。
詳しくは、以下の記事を参照してください。
【AWS】ECRへのアクセスをユーザー・ロール・サービス単位で制限する
AppRunnerでサービスを作成
いよいよAppRunnerでサービスを作成します。
AppRunnerのサービス画面で、「サービスの作成」を押下します。
リポジトリタイプは「コンテナレジストリ」、プロバイダーは「Amazon ECR」にチェックします。
コンテナイメージのURIの「参照」を押下して、ECRリポジトリとイメージ(タグ)を選択します。
イメージリポジトリに作成したリポジトリ名を選択して、イメージタグは一番最新のイメージを示すlatest
を選択してください。(1度しかイメージをプッシュしていない場合はイメージタグが自動で選択されます。)
デプロイトリガーで「自動」にチェックします。
また、ECRアクセスロールは、「既存のサービスロールを使用」をチェックして、作成したサービスロール名を選択してください。
完了したら「次へ」を押下します。
サービス名を自由に設定してください。
ポートは、アプリケーションで使用するポートを指定します。今回の例で使用しているGoのWebアプリでは8080
を設定します。
完了したら「次へ」を押下します。
設定を確認後「作成とデプロイ」を押下して、サービスを作成してください。
サービスが作成されたら、デフォルトドメインを押下して「Hello World!」が表示されることを確認しましょう。
さいごに
AppRunnerを立ち上げることはできましたか?
デプロイ・ロードバランシング・オートスケーリング・証明書管理など、様々な管理を自動で行ってくれる便利なサービスです。
しかし、ECRのアクセス制限の設定に少し複雑な部分があったのでまとめてみました。
コンテナ技術を使用したサービスを手軽に構築する手段として、これからもAppRunnerを使用していきたいと思います。