#はじめに
Secrets Manager、SSMパラメータストア、S3に機密情報を環境変数として保存して、実行タスクから参照できるかどうか確かめてみました。
ECS初心者向けの記事を何本か書いていますので、どれか参考になれば幸いです。
#AWS Secrets Manager
AWS Secrets Managerは、AWS内リソース、オンプレミス環境、またはサードパーティアプリケーションにアクセスするための各種機密情報の管理を、簡単にするAWSのサービスです。
Secrets Managerを利用することで、AWS CLI、API、SDKから機密情報へアクセスすることができます。
アプリケーション内に機密情報をハードコードする必要がなくなり、情報漏えいのリスクを減らすことができるようになります。
また、スケジュールに基づいた機密情報のローテーションに対応しており、古くなった機密情報の更新の手間を軽減することができます。
RDSやAuroraでは、機密情報のローテーションとデータベース接続情報のローテーションが統合されています。
#SSMパラメータストア
SSMパラメータストアはSecrets Manager登場前からある機密情報管理サービスです。
Secrets Managerとの違いを比較すると以下のようになります。
Secrets Manager | SSMパラメータストア | |
---|---|---|
値段 | 高価 | 安価 |
ローテーション | 可能 | 不可 |
KMS暗号化 | 必須 | 任意 |
CloudFormationとの統合 | あり | あり |
#実装
ECSで機密情報を取り扱うにあたり、以下の3つの方法あります。
下2つの方法について試しに実装してみます。
- タスク定義にハードコーディング
- SSM/Secrets Managerで管理
- S3で管理
##準備
ecsTaskExecutionRole
のパーミッションの修正、および新しくタスク定義とサービスの作成を行います。
まずはecsTaskExecutionRole
にSecrets ManagerやS3に保管したパラメータの取得に関するインラインポリシーを追加します。
<account-id>
にはアカウントIDを記述します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue",
"ssm:GetParameters",
"kms:Decrypt"
],
"Resource": [
"arn:aws:secretsmanager:ap-northeast-1:<account-id>:secret:*",
"arn:aws:ssm:ap-northeast-1:<account-id>:parameter/*",
"arn:aws:kms:ap-northeast-1:<account-id>:*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::ecs-course-<account-id>/environment-demo.env"
]
},
{
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::ecs-course-<account-id>"
]
}
]
}
次に、タスク定義を新しく作成します。
EC2起動タイプを選択して、タスク定義名の記述とタスク実行ロールの選択を行います。
コンテナの追加を行います。
今回はubuntu:latest
のイメージを取得します。
最後に、作成したタスク定義を元にサービスを新しく作成します。
##SSMパラメータストア
下準備が整ったので、SSMパラメータストアから実装を行っていきます。
Systems Managerのパラメーターストアを開いて、"パラメータの作成"を押します。
パラメータストアでは機密データの暗号化が任意です。
暗号化の可否でそれぞれ検証してみます。
暗号化を行わないケースでは、タイプに"文字列"を選択します。
暗号化を行うケースでは、タイプに"安全な文字列"を選択します。
作成したタスク定義を開いて、"新しいリビジョンの作成"を押します。
"値を追加してください"には、以下のコマンドで取得したARN
の中身を記述します。
$ aws ssm get-parameter --name plain-from-ssm
{
"Parameter": {
"Name": "plain-from-ssm",
"Type": "String",
"Value": "plain variable from SSM parameter store",
"Version": 1,
"LastModifiedDate": "2021-07-13T07:04:13.100000+09:00",
"ARN": "arn:aws:ssm:<<region>>:<<accountid>>:parameter/<<param-name>>",
"DataType": "text"
}
}
plain-ubuntu-service
に最新リビジョンのタスク定義を反映させます(2(latest)
を選択します)。
EC2を開いて、パブリック IPv4 DNS
をコピーします。
EC2にSSHログインします。
$ ssh -i ~/.ssh/udemysample.pem ec2-user@ec2-18-183-76-54.ap-northeast-1.compute.amazonaws.com
ubuntu
の文字列を含むコンテナの中身を表示します。
[ec2-user@ip-172-16-0-156 ~]$ docker container ls | grep ubuntu
b08bf03cc6c8 ubuntu:latest "sleep infinity" 17 minutes ago Up 17 minutes ecs-td-plain-ubuntu-2-plain-ubuntu-ac97cdd3abf9dfc1db01
以下のコマンドで指定したコンテナの環境変数env
を参照します。
[ec2-user@ip-172-16-0-156 ~]$ docker exec -it b08bf03cc6c8 "env"
plain-from-ssm
とencrypted-from-ssm
が確かに含まれています。
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=b08bf03cc6c8
TERM=xterm
ECS_CONTAINER_METADATA_URI=http://169.254.170.2/v3/f352209c-4de8-4214-9003-c66f42856952
ECS_CONTAINER_METADATA_URI_V4=http://169.254.170.2/v4/f352209c-4de8-4214-9003-c66f42856952
plain-from-ssm=plain variable from SSM parameter store
encrypted-from-ssm=encrypted variable from SSM Parameter store
AWS_EXECUTION_ENV=AWS_ECS_EC2
HOME=/root
##Secrets Manager
次に、Secrets Managerで実装を行います。
Secrets Managerを開いて、"新しいシークレットを保存する"を押すと以下の画面になります。
シークレットの種類を選択し、シークレットに格納するキーと値のペアを指定します。
最後のステップでシークレットを取得するためのサンプルコードが表示されます。
"保存"を押します。
作成したシークレットを開いて、シークレットのARNをコピーします。
作成したタスク定義を開いて、"新しいリビジョンの作成"を押します。
コンテナの編集から環境変数を追加します。
値にはコピーしたARNをペーストします。
サービスの設定で新しいリビジョン3(latest)
を選択し、新しいデプロイの強制
にチェックをつけて更新します。
SSMのときと同様に、SSHログインしてからdocker container ls | grep ubuntu
でコンテナIDを調べ、docker exec -it [container-id] "env"
を実行します。
すると、以下のように追加した環境変数secret-from-secrets-manager
が表示されます。
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=04cf089cf8e0
TERM=xterm
AWS_EXECUTION_ENV=AWS_ECS_EC2
ECS_CONTAINER_METADATA_URI=http://169.254.170.2/v3/541d9a24-900e-4c23-bc22-2e055c039ee6
ECS_CONTAINER_METADATA_URI_V4=http://169.254.170.2/v4/541d9a24-900e-4c23-bc22-2e055c039ee6
plain-from-ssm=plain variable from SSM parameter store
secret-from-secrets-manager={"key-from-secrets-manager":"This is the value from secrets manager"}
encrypted-from-ssm=encrypted variable from SSM Parameter store
HOME=/root
##Amazon S3
最後に、S3への環境変数の保存を行います。
以下のコマンドで、UserId、Account、Arnを確認します。
$ aws sts get-caller-identity
もし別のIAMユーザが設定されていたら、以下のコマンドを実行して、アクセスキーIDやシークレットアクセスキーを設定します。
$ aws configure
s3 mb
コマンドで新しくバケットを作成します。
バケット名はグローバルで一意(世界に1つだけ)である必要があります。
今回はバケット名をecs-course-[Account]
としました。
$ aws s3 mb s3://[バケット名]
envファイルを新しく作成します。
$ vi environment-demo.env
envファイルに環境変数を記述して保存します。
variable1-from-s3=value1
variable2-from-s3=value2
作成したenvファイルをS3バケットにアップロードします。
$ aws s3 cp ./environment-demo.env s3://ecs-course-s3://[バケット名]/
以下のコマンドでバケット内のファイルを確認することができます。
$ aws s3 ls s3://[バケット名]
2021-07-18 22:17:24 50 environment-demo.env
”コンテナの定義”で環境ファイルを追加します。
ロケーションにはarn:aws:s3:::[バケット名]/environment-demo.env
を記述します。
docker container ls
でコンテナIDを控え、docker exec -it [コンテナID] "env"
を実行します。
以下のように、envファイルの中身を確認することができます。
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=3a39f9eef85b
TERM=xterm
ECS_CONTAINER_METADATA_URI_V4=http://169.254.170.2/v4/46e249e6-1a76-4259-a97d-7e6f1e46e5c7
encrypted-from-ssm=encrypted variable from SSM Parameter store
plain-from-ssm=plain variable from SSM parameter store
secret-from-secrets-manager={"key-from-secrets-manager":"This is the value from secrets manager"}
variable1-from-s3=value1
variable2-from-s3=value2
AWS_EXECUTION_ENV=AWS_ECS_EC2
ECS_CONTAINER_METADATA_URI=http://169.254.170.2/v3/46e249e6-1a76-4259-a97d-7e6f1e46e5c7
HOME=/root
#Secrets Manager活用例 -プライベートレジストリのDockerイメージの使用-
Secrets Managerにクレデンシャルを保管して、プライベートレジストリのDockerイメージからタスクを起動することができます。
Secrets Manager開き、"その他のシークレット"を選択して、 usernameとpasswordを記述します。
コンテナの追加でコンテナ名とイメージを記述します。
また、"プライベートレジストリの認証"にチェックをつけて、Secrets ManagerのARNをペーストします。
無事にタスクが実行されれば成功です。
#参考資料