LoginSignup
6
3

More than 1 year has passed since last update.

【AWS】ECS構築の基礎 −機密情報の参照−

Last updated at Posted at 2021-07-20

はじめに

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を記述します。
スクリーンショット 2021-07-12 22.42.12.png

{
  "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>"
      ]
    }
  ]
}

名前を記述してポリシーをアタッチします。
スクリーンショット 2021-07-12 22.46.16.png

次に、タスク定義を新しく作成します。
EC2起動タイプを選択して、タスク定義名の記述とタスク実行ロールの選択を行います。
スクリーンショット 2021-07-12 22.49.08.png

コンテナの追加を行います。
今回はubuntu:latestのイメージを取得します。
スクリーンショット 2021-07-12 22.51.36.png

エントリポイントを追加しタスク定義を作成します。
スクリーンショット 2021-07-12 22.53.11.png

最後に、作成したタスク定義を元にサービスを新しく作成します。
スクリーンショット 2021-07-12 22.55.22.png

SSMパラメータストア

下準備が整ったので、SSMパラメータストアから実装を行っていきます。

Systems Managerのパラメーターストアを開いて、"パラメータの作成"を押します。
スクリーンショット 2021-07-13 7.01.11.png

パラメータストアでは機密データの暗号化が任意です。
暗号化の可否でそれぞれ検証してみます。

暗号化を行わないケースでは、タイプに"文字列"を選択します。
スクリーンショット 2021-07-13 7.03.54.png

暗号化を行うケースでは、タイプに"安全な文字列"を選択します。
スクリーンショット 2021-07-13 7.06.34.png

作成したタスク定義を開いて、"新しいリビジョンの作成"を押します。
スクリーンショット 2021-07-13 7.08.12.png

コンテナ名をクリックして、環境変数を追加します。
スクリーンショット 2021-07-13 7.17.08.png

"値を追加してください"には、以下のコマンドで取得した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)を選択します)。
スクリーンショット 2021-07-13 7.21.23.png

EC2を開いて、パブリック IPv4 DNSをコピーします。
スクリーンショット 2021-07-13 7.26.54.png

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-ssmencrypted-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を開いて、"新しいシークレットを保存する"を押すと以下の画面になります。
シークレットの種類を選択し、シークレットに格納するキーと値のペアを指定します。
スクリーンショット 2021-07-13 22.15.39.png

シークレットの名前を記述します。
スクリーンショット 2021-07-13 22.17.28.png

とりあえず自動ローテーションは無効にします。
スクリーンショット 2021-07-13 22.18.27.png

最後のステップでシークレットを取得するためのサンプルコードが表示されます。
"保存"を押します。
スクリーンショット 2021-07-13 22.19.39.png

作成したシークレットを開いて、シークレットのARNをコピーします。
作成したタスク定義を開いて、"新しいリビジョンの作成"を押します。
スクリーンショット 2021-07-13 22.22.27.png

コンテナの編集から環境変数を追加します。
値にはコピーしたARNをペーストします。
スクリーンショット 2021-07-13 22.30.44.png

サービスの設定で新しいリビジョン3(latest)を選択し、新しいデプロイの強制にチェックをつけて更新します。
スクリーンショット 2021-07-13 22.35.01.png

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

ここでECSのタスク定義から新しいリビジョンを作成します。
スクリーンショット 2021-07-18 22.22.19.png

”コンテナの定義”で環境ファイルを追加します。
ロケーションにはarn:aws:s3:::[バケット名]/environment-demo.envを記述します。
スクリーンショット 2021-07-18 22.25.41.png

サービスの更新を行います。
スクリーンショット 2021-07-18 22.28.24.png

リビジョンの変更と新しいデプロイの強制にチェックします。
スクリーンショット 2021-07-18 22.28.59.png

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を記述します。
スクリーンショット 2021-07-19 21.04.51.png

シークレットの名前を記述します。
スクリーンショット 2021-07-19 21.06.00.png

シークレット作成後、ARNをコピーします。
スクリーンショット 2021-07-19 21.07.44.png

新しくタスク定義を作成します。
スクリーンショット 2021-07-19 21.09.37.png

コンテナの追加でコンテナ名とイメージを記述します。
また、"プライベートレジストリの認証"にチェックをつけて、Secrets ManagerのARNをペーストします。
スクリーンショット 2021-07-19 21.15.41.png

クラスターから新しいタスクを実行します。
スクリーンショット 2021-07-19 21.16.56.png
スクリーンショット 2021-07-19 21.18.29.png

無事にタスクが実行されれば成功です。

参考資料

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3