VaultでDynamic Secretsを試してみる

目次

  1. 初めに
  2. 環境情報
  3. Dynamic Secretsについて
  4. AWS Secrets Engineの準備
  5. Roleを定義する
  6. IAM Userを作成する
  7. まとめ

1. 初めに

VaultではDynamic Secretsという機能がありますので、今回はこちらの機能について触れていきたいと思います。 今回もHashiCorp Learnにそって進めていき、補足情報などを備忘録として残していこうと思います。

Vault Curriculum - HashiCorp Learn

2. 環境情報

3. Dynamic Secretsについて

まずはDynamic Secretsがどういうものなのかについて説明したいと思います。通常のSecretはCLIなどで追加をしていました。

例えば kv の場合ですと下記のようにしてSecretを追加します。

$ vault write kv/hello target=world  

ただこうして追加されたSecretは他のユーザから見られてしまうので、セキュリティ的によくないですね。

そこでDynamic Secretsを使うことでこの問題が解決されます。

Dynamic Secretsは動的にSecretを作成する方法です。Secretを動的に作成し使用後すぐに消すことも可能ですし、TTLを指定することができます。また、動的に作成され作成したものは後から見ることができないのでセキュアに扱うことができます。

文字だけで説明してもDynamic Secretの良さが伝わらないので実際にコマンドと一緒に確認していきたいと思います。

HashiCorp LearnではAWS Secrets Engineを使っています。これはAWSへアクセスるためのクレデンシャルを作成してくれるものになります。 ここも詳しくは実際のコマンドを見ながら確認していきましょう。

4. AWS Secrets Engineの準備

まずは AWS Secrets Engineをenableにしましょう

$ vault secrets enable -path=aws aws
Success! Enabled the aws secrets engine at: aws/

$ vault secrets list
Path          Type         Accessor              Description
----          ----         --------              -----------
aws/          aws          aws_df70dbb8          n/a
cubbyhole/    cubbyhole    cubbyhole_18f07d22    per-token private secret storage
identity/     identity     identity_5170f551     identity store
secret/       kv           kv_2fd4ecf6           key/value secret storage
sys/          system       system_4a94a9f3       system endpoints used for control, policy and debugging

これでenableになってるのが確認できました。ちなみにDescriptionが n/a になっているのはDescriptionを何も設定してないっということです。これはオプションで設定することができます。

$ vault secrets enable -path=aws -description="aws secrets engine" aws
Success! Enabled the aws secrets engine at: aws/

AWS Secrets Engineは上記でも記述した通り、動的にAWSへのアクセス権限を作成します。

次にAWS Secrets Engineのconfig設定をしていきます。

$ vault write aws/config/root access_key=XXXXXXXXXXXXXXXXXXXX secret_key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX region=ap-northeast-1
Success! Data written to: aws/config/root

access_keyとsecret_keyはVaultからAWSへアクセスするときに使用するものになります。

権限は以下のものを利用しました。

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

5. Roleを定義する

Roleを定義していきます。Roleの定義をVaultに保存していきます。 今回追加するRoleは以下のものになります。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1426528957000",
      "Effect": "Allow",
      "Action": ["ec2:*"],
      "Resource": ["*"]
    }
  ]
}

このRoleはすべてのEC2へすべてのAction権限があるPolicyになります。 ではこれをVaultに保存します。

$ vault write aws/roles/my-role \
        credential_type=iam_user \
        policy_document=-<<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1426528957000",
      "Effect": "Allow",
      "Action": [
        "ec2:*"
      ],
      "Resource": [
        "*"
      ]
    }
  ]
}
EOF

$ vault read aws/roles/my-role
Key                         Value
---                         -----
credential_type             iam_user
default_sts_ttl             0s
max_sts_ttl                 0s
permissions_boundary_arn    n/a
policy_arns                 <nil>
policy_document             {"Version":"2012-10-17","Statement":[{"Sid":"Stmt1426528957000","Effect":"Allow","Action":["ec2:*"],"Resource":["*"]}]}
role_arns                   <nil>
user_path                   n/a

ここれで credential_typeiam_user を指定しました。

これはIAM Userを作成するRoleとして定義しており、Policyはインラインポリシーとして定義されます。 iam_user 以外にも下記のようなものがあります。

タイプ 説明
assumed_role sts:AssumeRole
federation_token sts:GetFederationToken

それぞれの細かい説明は省きます。詳しく知りたい方は下記リンクを参照してください。

AWS - Secrets Engines - Vault by HashiCorp

初めてのAssumeRole | Developers.IO

GetFederationToken のアクセス権限

6. IAM Userを作成する

では先ほど作成したRoleでIAM Userを作成しようと思います。

IAM Userを作成するには aws/creds/[作成したRoleの名前] パスを読むことで作成されます。上記で my-role でRoleを作成したので今回は aws/creds/my-role を読むことで作成されます。

$ vault read aws/creds/my-role
Key                Value
---                -----
lease_id           aws/creds/my-role/nDPEvmAlgRUBdNx7ChuRuhRU
lease_duration     768h
lease_renewable    true
access_key         YYYYYYYYYYYYYYYYYYYY
secret_key         YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
security_token     <nil>

実際にAWSコンソールの画面で見てみると新規にIAM Userが作成されているのが確認できます。また出力された そしてもう一度実行すると新規でIAM Userが作られて新しい出力を得ることができます。

また -format=json を指定するだけで出力はJSON形式でも出力ができます。

$ vault read -format=json aws/creds/my-role
{
  "request_id": "d73d780e-a5cc-e30f-df5d-ae7e72e832f3",
  "lease_id": "aws/creds/my-role/eNmGkM06f3yzv9ZgvZVUx6Uh",
  "lease_duration": 2764800,
  "renewable": true,
  "data": {
    "access_key": "ZZZZZZZZZZZZZZZZZZZZ",
    "secret_key": "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ",
    "security_token": null
  },
  "warnings": null
}

最後に削除処理です。IAM Userを削除するときはIAM Userを作成したときに出力された lease_id 引数にして削除します。

$ vault lease revoke aws/creds/my-role/nDPEvmAlgRUBdNx7ChuRuhRU
All revocation operations queued successfully!

AWSコンソールからも削除されているのが確認できます。

7. まとめ

今回はAWS IAM Userを動的に作成し、access keyとsecret keyの取得までできるようになりました。

HashiCorp Learnをそって進めるだけでここまでできるので気になる方はぜひやってみてください。 AssumeRoleなどのほうが利便性も良さそうなので機会があるときにやってみようと思います。