これは何?
Vault Secrets + Terraform Cloud でシークレット管理してみました。
Vault Secrets とは?
Vault Secrets とは、マルチプロバイダーにおけるシークレットを統合管理する機能になります。
以下の画像のように複数のプロバイダーをVault Secretsで統合的に管理することができます。
また、登録するシークレットの種類として、
- パスワード
- API トークン
- アクセスキー
が挙げられます。
AWS + Vault でシークレット同期
最初にHashicorp Cloud からVault Secretsアプリケーションを作成します。
[Create new app]からアプリケーションを作成します。
アプリケーション作成後、Integrationsタブを押下し、シークレットを同期したいプロバイダーを指定します。今回はVault -> AWSへシークレットを同期したいのでAWS を選択します。
その後、インテグレーションの詳細を設定します。ExternalIDが記載されているのでこちらの値をコピーします。
また、シークレット同期のため、AWS Secrets Managerの書き込み権限を持っているIAMロールのArnを指定します。
次に、上記で設定したRole Arnで設定したIAMロールを設定します。
上記でコピーしたExternalIDをAWS_EXTERNAL_IDに代入してIAMロールを作成します。
以下の内容はIAMロールの信頼関係になります。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::879554817125:role/HCPVaultSecrets_Sync"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "<AWS_EXTERNAL_ID>"
}
}
}
]
}
こちらの方は、ポリシーになります。IAMロールの下に以下のようなインラインポリシーを作成します。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "HCPVaultSecretsAccess",
"Effect": "Allow",
"Action": [
"secretsmanager:DescribeSecret",
"secretsmanager:GetSecretValue",
"secretsmanager:CreateSecret",
"secretsmanager:PutSecretValue",
"secretsmanager:UpdateSecret",
"secretsmanager:UpdateSecretVersionStage",
"secretsmanager:DeleteSecret",
"secretsmanager:RestoreSecret",
"secretsmanager:TagResource",
"secretsmanager:UntagResource"
],
"Resource": "*"
}
]
}
以上で下準備が完了しました。
最後に、Vault Secrets で作成したアプリケーション内でシークレットを登録していきます。
以下はRDSを作成する際のDBユーザー/パスワードを登録します。
上記で登録した結果、AWS Screts Managerコンソールにアクセスします。
その結果<Vault Application Name>/<シークレットキー>
としてシークレットが登録されていることが確認できます。
シークレットの中身も確認することができます。但し内容としては
- ローテーションなし
- KMSキー暗号化なし
のデフォルトの設定になっています。
注意して欲しい点として、このシークレットですが、Secrets Manager上でローテーションなどで値が変更された場合、 Secrets Manager → Vault Secrets に同期されないという注意書きがあります。
このシークレットはサードパーティのサービスプロバイダー (HCP Vault Secrets) によって管理されています。
AWS Secrets Manager で直接行われた変更は、HCP Vault Secrets と同期されません。このシークレットの管理の詳細については、HCP Vault Secrets ドキュメントを参照してください。
詳細はこちら
そのため、ローテーションなしで複数プロバイダーのシークレットを管理する目的であるならVault Secrets を利用できるということになります。
Vault Secrets + HCP Terraform とシークレット同期
次にVault Secrets + HCP Terraform でシークレットの同期を実施します。
イメージとしては以下の通りです。
Vault Secretsで登録したシークレット情報をTerraform Cloud上のWorkspace Variablesとして同期します。
まず初めにVault がTerraform Cloudへのアクセスを許可するためのトークンを生成します、
Terraform Cloud を開き API トークンを作成します。Teamの管理はStandard Edition以降で利用可能なのでFree Planでは、ownersチームのteam tokenを作成します。
アプリケーション作成後、Integrationsタブを押下し、シークレットを同期したいプロバイダーを指定します。今回はVault -> HCP Terraformへシークレットを同期したいのでHCP Terraformを選択します。
次にインテグレーションの詳細を設定します。
先ほど作成したトークンをメモして、インテグレーション設定を実施します。
以下のように同期したいワークスペースを選択し、変数の種類についても以下のように選択します。
これでインテグレーションの設定が完了しました。
動作確認としてシークレットを登録してみましょう。
以下のようにVault Secrets上のAppからシークレットを登録します。
Terraform Cloud についてワークスペース内のworkspace変数を確認します。
その結果、Vault Secrets で作成したパスワードがsensitive variableとして登録されていることが確認できました。
実践 RDS作成
Vault Secretsに登録したシークレットをHCP Terraform のWorkspace変数に同期し、その値を参照してインスタンスを作成します。
今回はRDSのDBユーザー/パスワードをシークレットとして登録しますします。
Vault Secrets 登録
今回はRDSを作成するとうい想定で、DBユーザー/パスワード名などのシークレットの管理をGit上で管理することなく実施したいと思います。
まず、Vault Secrets 上にDBユーザー名rds_username
とDBパスワードrds_password
に登録します。
登録後、Terraform Cloud に切り替えVaultで登録したシークレットがワークスペース変数として定義されていることを確認します。
Terraform ワークスペース作成
以前実施した手順を基にTerraform Workspaceを作成します。
ワーキングディレクトリについては、03_vault_secretsを指定します。
Terraform ワークスペースと紐づけるリポジトリは、こちらのように、Vault Secretsを参照するようにします。
variable "rds_password" {
type = string
}
variable "rds_username" {
type = string
}
module "rds-mysql" {
source = "app.terraform.io/atsuw0w-test-terraform/webapp-templates/aws//modules/rds_instance"
version = "1.0.0"
pj_tags = var.pj_tags
rds = {
prefix = "app"
subnet_group_ids = [for k, v in module.network-templates.subnet_pri_ids : v] #["subnet-xxx", "subnet-yyy"]
security_group_ids = [module.mariadb-sg.sg_id]
rds_instance_class = "db.t4g.micro"
rds_allocated_storage = 20
db_engine = "mysql"
db_engine_version = "8.0"
db_name = "fuga"
db_username = var.rds_username
db_password = var.rds_password
az = "a"
is_multi_az = false
is_ops = false
}
}
上記のように登録しプルリクエストを投げると、以下のようにPlanが実行されMergeするとApplyが実行されます。
これでVault Secrets + HCP Terraform でシークレットを管理しつつリソースを構築することができました。