grasys blog

HashiCorp Vault で期限付き AWS IAM Credential を作ってみた(Cloud Native Week2023春登壇)

※こちらの記事はCloud Native Week2023春のイベントに登壇した内容を元に作成しています!

お久しぶりでございます!よっしーです。

シークレット管理、そしてデータ暗号化用のセキュリティツールとして広く使われています、
HashiCorp Vault ですが、実際はどのようにアクセス対象となる各種サービスに対して
Vault から操作・設定されるのかを、AWS CLI でのアクセス許可のための IAM 設定
通して見ていきたいと思います!

HashiCorp Vault のインストール・初期設定

今回は Vault 自体の設定を簡易化するため、「開発モード」を使用します。

  • 開発モードでは、いくつかの Vault のセキュリティ機能が解除された状態で起動されるため、 Vault の動作検証には便利な機能ですが、決して本番環境では使用しないようにしましよう。

1、インストール

  以下のコマンドを実行。今回 Vault 起動サーバ の OS は CentOS7 を使用。

$ sudo yum install -y yum-utils
$ sudo yum-config-manager --add-repo https://rpm.releases.bashicorp.com/RHEL/bashicorp.repo
$ sudo yum -y install vault

  これでインストールは完了です。簡単ですね。
  正しくインストールできたかの確認は “vault” コマンドを実行。ヘルプが表示されれば OK!

2、「開発モード」で起動

  Vault を開発モードで起動するためには以下のコマンドを実行。

$ sudo vault server -dev (-dev-listen-address "0.0.0.0:8200") &
-----
 -dev : 開発モードで起動 (tlsを使用するには -dev-tls を使用。証明書も自動発行される)
 -dev-listen-address : 指定した IP からの接続が許可される。このオプションを省略すると
                       127.0.0.1:8200 が指定され、localhost からのみ接続が許可される。

  上記のコマンドを実行すると下記のような情報が表示される。

WARNING! dev mode is enabled! In this mode, Vault runs entirely in-memory
and starts unsealed with a single unseal key. The root token is already
authenticated to the CLI, so you can immediately begin using Vault.

You may need to set the following environment variables:

    $ export VAULT_ADDR='http://127.0.0.1:8200'

The unseal key and root token are displayed below in case you want to
seal/unseal the Vault or re-authenticate.

Unseal Key: jUAuIs7sXVK4/ftpWBV8G8RebH3V4nAoWkr2EB5rOMY=
Root Token: hvs.An6gQBYX587rxSXnYyKR07TY

Development mode should NOT be used in production installations!

  ここで重要なのは、”Root Token”。 メモに控えておきましょう。

  開発モードでは全ての登録データがメモリー上に保存されるため、
  vault プロセスの再起動を実行すると登録した全てのデータが消去されます!

3、vault にアクセスするための環境設定。

  Vault 起動サーバにて以下の環境変数を設定

$ export VAULT_ADDR='http://127.0.0.1:8200'
$ export VAULT_TOKEN='hvs.An6gQBYX587rxSXnYyKR07TY'
----
localhost 以外からのアクセスを許可した場合、'VAULT_ADDR' にはVault起動サーバのIPを指定。
例) export VAULT_ADDR='http://123.45.67.890:8200'

  以下のコマンドを実行し、status が表示されたらアクセス成功!

$ vault status
Key             Value
---             -----
Seal Type       shamir
Initialized     true
Sealed          false
Total Shares    1
Threshold       1
Version         1.13.2
Build Date      2023-04-25T13:02:50Z
Storage Type    inmem
Cluster Name    vault-cluster-08b1b449
Cluster ID      687fac1b-4b87-d7d3-e1e4-3bc0614c403e
HA Enabled      false

Vault 用 AWS ユーザの作成

Vault で期限付き AWS credential 発行のために、Vault で作成した IAM 情報を登録するための AWS ユーザを作成します。

1、AWS マネジメントコンソールの 「IAM → ユーザ → ユーザ追加」から新規ユーザを作成。

  • 「ポリシー」および「セキュリティ認証情報」を設定するためマネジメントコンソールアクセスを許可。

2、AWS マネジメントコンソールから作成したユーザにログインし、
  「セキュリティ認証情報」を開く。

  • アクセスキーを作成。
    • コマンドラインインターフェイス (CLI) 用を選択
    • 作成された ACCESS_KEY_ID と SECRET_ACCESS_KEY をメモに控える。
  • 必要であれば、「MFA」の設定も可能

3、ポリシーを設定。Vault による IAM の操作が必要となるための、以下のポリシーを追加。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "iam:DeleteAccessKey",
                "iam:AttachUserPolicy",
                "iam:DeleteUserPolicy",
                "iam:DeleteUser",
                "iam:ListUserPolicies",
                "iam:CreateUser",
                "iam:CreateAccessKey",
                "iam:RemoveUserFromGroup",
                "iam:AddUserToGroup",
                "iam:ListGroupsForUser",
                "iam:PutUserPolicy",
                "iam:ListAttachedUserPolicies",
                "iam:GetUser",
                "iam:DetachUserPolicy",
                "iam:ListAccessKeys"
            ],
            "Resource": [
                "arn:aws:iam::121467996308:user/*",
                "arn:aws:iam::121467996308:group/*"
            ]
        }
    ]
}

Vault で期限付き AWS IAM Credential を作成

それでは、vault 起動サーバにて、期限付き AWS IAM Credential を作成してみましょう!

1、vault で「AWS シークレットエンジン」を起動

  まずは vault で AWS credential を操作できるよう、以下のコマンドで
  シークレットエンジンを起動。

$ vault secrets enable -path=aws aws
------
Success! Enabled the aws secrets engine at: aws/
と表示されれば成功

2、Vault 用 AWS ユーザのアクセスキー情報を Vault に登録

$ vault write aws/config/root \
    access_key=<Vault用ユーザのACCESS_KEY_ID> \
    secret_key=<Vault用ユーザのSECRET_ACCESS_KEY> \
    region=ap-northeast-1

  Vault 用 AWS ユーザのアクセスキー情報は Vault サーバに保存されるため、
  サーバまたは、クラインアント側のファイル等に保存する必要はなし。

3、期限付き AWS IAM Credential に付与するロールの登録

  Vault で作成する期限付き AWS IAM Credential には個別に ロールを付与することが可能。
  今回は、

  • EC2 に対する全操作権限を持つロール
  • s3 に対する全操作権限を持つロール

  の2つのロールを登録。

EC2 に対する全操作権限を持つロール
$ vault write aws/roles/my-role-ec2 \
    credential_type=iam_user \
    policy_document=-<<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "ec2:*",
      "Resource": "*"
    }
  ]
}
EOF
------
Success! Data written to: aws/roles/my-role-ec2
と表示されれば成功
s3 に対する全操作権限を持つロール
$ vault write aws/roles/my-role-s3 \
    credential_type=iam_user \
    policy_document=-<<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": "*"
    }
  ]
}
EOF
------
Success! Data written to: aws/roles/my-role-s3
と表示されれば成功

4、期限付き AWS IAM Credential に対する期限の設定

  期限付き AWS IAM Credential の期限のデフォルト値および、最大値は共に
   768時間 (32日間)
  に設定。
  今回は検証のため以下のコマンドで、デフォルト値を 3 分、最大値を10 分に設定

$ vault write sys/mounts/aws/tune default_lease_ttl=3m max_lease_ttl=10m
------
Success! Data written to: sys/mounts/aws/tune
と表示されれば成功

5、期限付き AWS IAM Credential の作成
  以下のコマンドを実行

ロール「my-role-ec2」が付与された credential の作成
$ vault read aws/creds/my-role-ec2

------
Key                Value
---                -----
lease_id           aws/creds/my-role-ec2/gGKtCpjqY46azXfVFICN1OKk
lease_duration     3m
lease_renewable    true
access_key         AKIARYSAORCKHHJFJX57
secret_key         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
security_token     <nil>
------
 と表示されれば成功

  ここに表示された access_key および secret_key が期限付き AWS IAM Credential となる
  同様に、

ロール「my-role-s3」が付与された credential の作成
$ vault read aws/creds/my-role-s3

------
Key                Value
---                -----
lease_id           aws/creds/my-role-s3/y3o8Z4qZ1tOrDhrwGJoKZbLS
lease_duration     3m
lease_renewable    true
access_key         AKIARYSAORCKAOKN26GM
secret_key         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
security_token     <nil>
------
と表示されれば成功

期限付き AWS IAM Credential を使ってみる

作成された期限付き AWS IAM Credential を使うには、出力された access_key と secret_key を
AWS CLI を実行するクライアントに登録し、aws コマンドを実行する。

・ロール「my-role-ec2」が付与された credential の使用

 1、環境変数に access_key と secret_key を登録
   以下のコマンドを実行

$ export AWS_ACCESS_KEY_ID=AKIARYSAORCKHHJFJX57
$ export AWS_SECRET_ACCESS_KEY=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

 2、aws コマンドを実行する

$ aws ec2 describe-instances --output=table --query 'Reservations[].Instances[].{InstanceId: InstanceId}'
-------------------------
|   DescribeInstances   |
+-----------------------+
|      InstanceId       |
+-----------------------+
|  i-0c0a56ddfxxxxxxxx  |
|  i-0ca5a69b2xxxxxxxx  |
|  i-0fa881c65xxxxxxxx  |
|  i-037a5f514xxxxxxxx  |
|  i-020134377xxxxxxxx  |                                                                                             |  i-06447b09cxxxxxxxx  |
|  i-0aa819774xxxxxxxx  |
+-----------------------+
ーーーー
EC2 のリストが表示された

$ aws s3 ls

An error occurred (AccessDenied) when calling the ListBuckets operation: Access Denied
ーーーー
s3 にはアクセスできない

〜〜〜
credential 作成後 3 分経過
〜〜〜

$ aws ec2 describe-instances --output=table --query 'Reservations[].Instances[].{InstanceId: InstanceId}'

An error occurred (AuthFailure) when calling the DescribeInstances operation: AWS was not able to validate the provided access credentials
ーーーー
EC2 にアクセスできない

・ロール「my-role-s3」が付与された credential の使用

 1、環境変数に access_key と secret_key を登録
   以下のコマンドを実行

$ export AWS_ACCESS_KEY_ID=AKIARYSAORCKAOKN26GM
$ export AWS_SECRET_ACCESS_KEY=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

 2、aws コマンドを実行する

$ aws s3 ls
2021-01-27 13:38:39 aaaaaa
2020-08-28 14:07:37 bbbbbb
2020-06-19 03:07:21 cccccc
2020-06-19 03:08:38 dddddd
2021-03-02 12:33:00 eeeeee
2020-06-19 03:28:47 ffffff
2020-10-08 18:06:08 gggggg
ーーーー
s3 のバケットリストが表示された

$ aws ec2 describe-instances --output=table --query 'Reservations[].Instances[].{InstanceId: InstanceId}'

An error occurred (UnauthorizedOperation) when calling the DescribeInstances operation: You are not authorized to perform this operation.
ーーーー
EC2 にはアクセスできない

〜〜〜
credential 作成後 3 分経過
〜〜〜

$ aws s3 ls

An error occurred (InvalidAccessKeyId) when calling the ListBuckets operation: The AWS Access Key Id you provided does not exist in our records.
ーーーー
s3 にアクセスできない

AWS では何が起こっている?

Vault による 期限付き AWS IAM Credential が作成されると、
Vault により IAM ユーザが作成される

・ロール「my-role-ec2」が付与された credential 作成時
 下図のように、「vault-root-my-role-ec2」から始まる IAM ユーザが作成される

 このユーザには、

  • ポリシー 「my-role-ec2」がインラインポリシーとして設定
  • “vault read” 実行時に表示されたアクセスキー情報が登録

 されている。また、ポリシー「my-role-ec2」には

 EC2 に対する全操作権限を持つロールが付与されている。

・ロール「my-role-s3」が付与された credential 作成時
 下図のように、「vault-root-my-role-s3」から始まる IAM ユーザが作成される

 このユーザには、

  • / ポリシー 「my-role-s3」がインラインポリシーとして設定
  • “vault read” 実行時に表示されたアクセスキー情報が登録

 されている。また、ポリシー「my-role-s3」には

 s3 に対する全操作権限を持つロールが付与されている。

また、これらの IAM ユーザは
“lease_duration” で設定されている期間が過ぎると、
Vault により自動的に削除されるため、
期限が過ぎた AWS IAM Credential は使用できなくなる。

更に、これらの IAM ユーザは以下のコマンドにより手動で削除も可能

$ vault lease revoke <lease_id>
例) $ vault lease revoke aws/creds/my-role-s3/y3o8Z4qZ1tOrDhrwGJoKZbLS

まとめ

シークレット管理のために多くの機能をもつ HashiCorp Vault ですが、シークレット管理の手順は意外と分かりやすく、シンプルな構造でした。

今回ご紹介した 期限付き AWS IAM Credential は一時的に AWS で作業したいゲストユーザにアクセス権を提供できる有効な手段となると思われます。

また、Vault では Google Cloud (GCP) や Microsoft Azure にも同様な機能が提供できるため、幅広く活用できるでしょう。


採用情報
お問い合わせ