結論
terraformで以下のリソースを作成し、手動などでシークレットの値を更新した後、再度terraformコマンドを実行すると、
- Secrets Manager
- terraform refreshをしても、tfstateに変更はありません。
- terraform applyをしても、changedになりません。
- Parameter Store
- terraform refreshをすると、tfstateが更新されます。
- terraform applyをすると、changedになります。
はじめに
Terraformで作成したSecretsManagerとParameterStoreのそれぞれの値について、tfstateでの管理に差異があったので書き留めておきます。
Resource: aws_secretsmanager_secret
リソース:aws_secretsmanager_secret
シークレットマネージャは、AWSマネジメントコンソールからは即削除できませんが、
Terraformではrecovery_window_in_days = 0
を設定することで即削除できます。
recovery_window_in_days - (Optional) Number of days that AWS Secrets Manager waits before it can delete the secret. This value can be 0 to force deletion without recovery or range from 7 to 30 days. The default value is 30.
SecretsManager作成のTFファイル
シークレット名web_password
を作成し、key:valueでpassword:test1234
を登録します。
resource "aws_secretsmanager_secret" "asm_secret_web" { name = "web_password" recovery_window_in_days = 0 } resource "aws_secretsmanager_secret_version" "asm_secret_web_version" { secret_id = aws_secretsmanager_secret.asm_secret_web.id secret_string = jsonencode({"password" = "test1234"}) }
terraform applyの実行
terraform applyを実行し、シークレットマネージャにリソースを作成します。
$ terraform apply Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create (略) Plan: 2 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes aws_secretsmanager_secret.asm_secret_web: Creating... aws_secretsmanager_secret.asm_secret_web: Creation complete after 1s [id=arn:aws:secretsmanager:ap-northeast-1:*****:secret:web_password-7fD0bZ] aws_secretsmanager_secret_version.asm_secret_web_version: Creating... aws_secretsmanager_secret_version.asm_secret_web_version: Creation complete after 0s [id=arn:aws:secretsmanager:ap-northeast-1:*****:secret:web_password-7fD0bZ|********] Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
tfstateには、以下が記載されています。
"name": "web_password", "secret_string": "{\"password\":\"test1234\"}",
passwordの書き換え
ansibleでpasswordをtest1234
から、oioioioioi
に更新します。
Playbook例
[Ansible][AWS] SecretsManagerモジュールでユーザとパスワードを登録する(更新2023.02.13) - mito’s blog
$ ansible-playbook add_secretmanager.yml [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all' PLAY [localhost] *********************************************************** TASK [debug] *************************************************************** ok: [localhost] => { "msg": { "password": "test1234" } } TASK [Update Secrets Manager] ************************************************* changed: [localhost] TASK [debug] *************************************************************** ok: [localhost] => { "msg": { "password": "oioioioioi" } } PLAY RECAP ***************************************************************** localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 $
terraform apply -refresh-onlyの実行
terraform apply -refresh-onlyを実行しても、tfstateには変更ありません。
$ terraform apply -refresh-only aws_secretsmanager_secret.asm_secret_web: Refreshing state... [id=arn:aws:secretsmanager:ap-northeast-1:*****:secret:web_password-7fD0bZ] aws_secretsmanager_secret_version.asm_secret_web_version: Refreshing state... [id=arn:aws:secretsmanager:ap-northeast-1:*****:secret:web_password-7fD0bZ|********] No changes. Your infrastructure still matches the configuration. Terraform has checked that the real remote objects still match the result of your most recent changes, and found no differences. Apply complete! Resources: 0 added, 0 changed, 0 destroyed. $
tfstateのpasswordは、test1234
のままです。
"secret_string": "{\"password\":\"test1234\"}",
terraform applyの実行
terraform applyの実行でも変更はありません。
$ terraform apply aws_secretsmanager_secret.asm_secret_web: Refreshing state... [id=arn:aws:secretsmanager:ap-northeast-1:*****:secret:web_password-7fD0bZ] aws_secretsmanager_secret_version.asm_secret_web_version: Refreshing state... [id=arn:aws:secretsmanager:ap-northeast-1:*****:secret:web_password-7fD0bZ|********] No changes. Your infrastructure matches the configuration. Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed. Apply complete! Resources: 0 added, 0 changed, 0 destroyed. $
リソース:ssm_parameter
ParameterStore作成のTFファイル
パラメータ名web_password
を作成し、valueにtest1234
を登録します。
resource "aws_ssm_parameter" "ssm_parameter_web_password" { name = "web_password" type = "SecureString" value = "tes1234" }
terraform applyの実行
terraform applyを実行し、パラメータストアにリソースを作成します。
$ terraform apply Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create (略) Plan: 1 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes aws_ssm_parameter.ssm_parameter_web_password: Creating... aws_ssm_parameter.ssm_parameter_web_password: Creation complete after 0s [id=web_password] Apply complete! Resources: 1 added, 0 changed, 0 destroyed. $
tfstateには、以下が記載されています。
"name": "web_password", "value": "tes1234",
passwordの書き換え
ansibleでpasswordをtest1234
から、oioioioioi
に更新します。
Playbook例
[Ansible][AWS] ParameterStoreモジュールでユーザとパスワードを登録する - mito’s blog
$ ansible-playbook add_paramater.yml [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all' PLAY [localhost] *************************************************************** TASK [debug] ******************************************************************* ok: [localhost] => { "msg": "tes1234" } TASK [Update SSM parameter store] ************************ changed: [localhost] TASK [debug] ******************************************************************* ok: [localhost] => { "msg": "oioioioi" } PLAY RECAP ********************************************************************* localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 $
terraform apply -refresh-onlyの実行
terraform apply -refresh-onlyを実行すると、tfstateに変更が入ります。
また、-refresh-only
を付けているためapplyは実行しておらず、0 changed
になります。
$ terraform apply -refresh-only aws_ssm_parameter.ssm_parameter_web_password: Refreshing state... [id=web_password] Note: Objects have changed outside of Terraform Terraform detected the following changes made outside of Terraform since the last "terraform apply": # aws_ssm_parameter.ssm_parameter_web_password has changed ~ resource "aws_ssm_parameter" "ssm_parameter_web_password" { id = "web_password" name = "web_password" + tags = {} ~ value = (sensitive value) ~ version = 1 -> 2 # (6 unchanged attributes hidden) } This is a refresh-only plan, so Terraform will not take any actions to undo these. If you were expecting these changes then you can apply this plan to record the updated values in the Terraform state without changing any remote objects. Would you like to update the Terraform state to reflect these detected changes? Terraform will write these changes to the state without modifying any real infrastructure. There is no undo. Only 'yes' will be accepted to confirm. Enter a value: yes Apply complete! Resources: 0 added, 0 changed, 0 destroyed. $
tfstateには、差分が見受けられます。
passwordやversionが更新されています。
$ diff -u terraform.tfstate.backup terraform.tfstate --- terraform.tfstate.backup 2023-03-04 21:22:36.243115094 +0900 +++ terraform.tfstate 2023-03-04 21:22:36.243115094 +0900 @@ -1,7 +1,7 @@ - "serial": 8, + "serial": 9, @@ -23,12 +23,12 @@ - "tags": null, + "tags": {}, - "value": "tes1234", - "version": 1 + "value": "oioioioi", + "version": 2
terraform applyの実行
terraform applyを実行すると、passwordが書き換え前に変更されます。
$ terraform apply aws_ssm_parameter.ssm_parameter_web_password: Refreshing state... [id=web_password] Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: ~ update in-place Terraform will perform the following actions: # aws_ssm_parameter.ssm_parameter_web_password will be updated in-place ~ resource "aws_ssm_parameter" "ssm_parameter_web_password" { id = "web_password" + insecure_value = (known after apply) name = "web_password" tags = {} ~ value = (sensitive value) ~ version = 2 -> (known after apply) # (6 unchanged attributes hidden) } Plan: 0 to add, 1 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes aws_ssm_parameter.ssm_parameter_web_password: Modifying... [id=web_password] aws_ssm_parameter.ssm_parameter_web_password: Modifications complete after 0s [id=web_password] Apply complete! Resources: 0 added, 1 changed, 0 destroyed. $
passwordが書き換える前の値(TFファイルの値)に変わりました。
$ diff -u terraform.tfstate.backup terraform.tfstate --- terraform.tfstate.backup 2023-03-04 21:29:22.879912086 +0900 +++ terraform.tfstate 2023-03-04 21:29:22.895912433 +0900 @@ -1,7 +1,7 @@ - "serial": 9, + "serial": 11, @@ -27,8 +27,8 @@ - "value": "oioioioi", - "version": 2 + "value": "tes1234", + "version": 3 $
備考
Secrets ManagerとParameter Storeのどちらを使用するかは、運用に応じて選択するのが良いかと思います。
ただし、terraform外での値の変更が予想される場合には、terraform applyの実行では値が変更されないSecretsManagerをお勧めします。課金されるけど。