Skip to content

Commit

Permalink
allow syncing with out-of-band changes for kv v1 and v2 (#2207)
Browse files Browse the repository at this point in the history
* fixed resource vault_kv_secret_v2 : not reading data_json

* fixed resource vault_kv_secret : not reading data_json

* modified resource kv secret v2 test

* updated tests for kv secret and kv secret v2

* add changelog

---------

Co-authored-by: NightOwl998 <gf_hasnaoui@esi.dz>
  • Loading branch information
fairclothjm and NightOwl998 committed Mar 25, 2024
1 parent cd36775 commit b18d2d3
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,7 @@ FEATURES:

BUGS:
* fix `vault_approle_auth_backend_role_secret_id` regression to handle 404 errors ([#2204](https://github.com/hashicorp/terraform-provider-vault/pull/2204))
* fix `vault_kv_secret` and `vault_kv_secret_v2` failure to update secret data modified outside terraform ([#1933](https://github.com/hashicorp/terraform-provider-vault/pull/1933))

## 4.1.0 (Mar 20, 2024)

Expand Down
8 changes: 8 additions & 0 deletions vault/resource_kv_secret.go
Expand Up @@ -103,6 +103,14 @@ func kvSecretRead(_ context.Context, d *schema.ResourceData, meta interface{}) d
log.Printf("[DEBUG] secret: %#v", secret)

data := secret.Data
jsonData, err := json.Marshal(data)
if err != nil {
return diag.Errorf("error marshaling JSON for %q: %s", path, err)
}

if err := d.Set(consts.FieldDataJSON, string(jsonData)); err != nil {
return diag.FromErr(err)
}

if err := d.Set(consts.FieldData, serializeDataMapToString(data)); err != nil {
return diag.FromErr(err)
Expand Down
43 changes: 43 additions & 0 deletions vault/resource_kv_secret_test.go
Expand Up @@ -63,6 +63,49 @@ func TestAccKVSecret(t *testing.T) {
},
})
}
func TestAccKVSecret_UpdateOutsideTerraform(t *testing.T) {
t.Parallel()
resourceName := "vault_kv_secret.test"
mount := acctest.RandomWithPrefix("tf-kvv2")
name := acctest.RandomWithPrefix("tf-secret")

resource.Test(t, resource.TestCase{
ProviderFactories: providerFactories,
PreCheck: func() { testutil.TestAccPreCheck(t) },
Steps: []resource.TestStep{
{
Config: testKVSecretConfig_basic(mount, name),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, consts.FieldPath, fmt.Sprintf("%s/%s", mount, name)),
resource.TestCheckResourceAttr(resourceName, "data.%", "2"),
resource.TestCheckResourceAttr(resourceName, "data.zip", "zap"),
resource.TestCheckResourceAttr(resourceName, "data.foo", "bar"),
assertKVV1Data(resourceName),
),
},
{
PreConfig: func() {
client := testProvider.Meta().(*provider.ProviderMeta).MustGetClient()

// Simulate external change using Vault CLI for KV v1
path := fmt.Sprintf("%s/%s", mount, name)
_, err := client.Logical().Write(path, map[string]interface{}{"testkey3": "testvalue3"})
if err != nil {
t.Fatalf("error simulating external change; err=%s", err)
}
},
Config: testKVSecretConfig_basic(mount, name),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, consts.FieldPath, fmt.Sprintf("%s/%s", mount, name)),
resource.TestCheckResourceAttr(resourceName, "data.%", "2"),
resource.TestCheckResourceAttr(resourceName, "data.zip", "zap"),
resource.TestCheckResourceAttr(resourceName, "data.foo", "bar"),
assertKVV1Data(resourceName),
),
},
},
})
}

func kvV1MountConfig(path string) string {
ret := fmt.Sprintf(`
Expand Down
7 changes: 7 additions & 0 deletions vault/resource_kv_secret_v2.go
Expand Up @@ -287,7 +287,14 @@ func kvSecretV2Read(_ context.Context, d *schema.ResourceData, meta interface{})
log.Printf("[DEBUG] secret: %#v", secret)

data := secret.Data["data"]
jsonData, err := json.Marshal(data)
if err != nil {
return diag.Errorf("error marshaling JSON for %q: %s", path, err)
}

if err := d.Set(consts.FieldDataJSON, string(jsonData)); err != nil {
return diag.FromErr(err)
}
if v, ok := data.(map[string]interface{}); ok {
if err := d.Set(consts.FieldData, serializeDataMapToString(v)); err != nil {
return diag.FromErr(err)
Expand Down
53 changes: 53 additions & 0 deletions vault/resource_kv_secret_v2_test.go
Expand Up @@ -215,6 +215,58 @@ func TestAccKVSecretV2_DisableRead(t *testing.T) {
})
}

// Fadia u have added this
func TestAccKVSecretV2_UpdateOutsideTerraform(t *testing.T) {
resourceName := "vault_kv_secret_v2.test"
mount := acctest.RandomWithPrefix("tf-kv")
name := acctest.RandomWithPrefix("foo")

resource.Test(t, resource.TestCase{
ProviderFactories: providerFactories,
PreCheck: func() { testutil.TestAccPreCheck(t) },
Steps: []resource.TestStep{
{
Config: testKVSecretV2Config_initial(mount, name),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, consts.FieldMount, mount),
resource.TestCheckResourceAttr(resourceName, consts.FieldName, name),
resource.TestCheckResourceAttr(resourceName, consts.FieldPath, fmt.Sprintf("%s/data/%s", mount, name)),
resource.TestCheckResourceAttr(resourceName, "delete_all_versions", "true"),
resource.TestCheckResourceAttr(resourceName, "data.zip", "zap"),
resource.TestCheckResourceAttr(resourceName, "data.foo", "bar"),
resource.TestCheckResourceAttr(resourceName, "data.flag", "false"),
resource.TestCheckResourceAttr(resourceName, "metadata.version", "1"),
),
},
{
PreConfig: func() {
client := testProvider.Meta().(*provider.ProviderMeta).MustGetClient()

// Simulate external change using Vault CLI
path := fmt.Sprintf("%s/data/%s", mount, name)
_, err := client.Logical().Write(path, map[string]interface{}{"data": map[string]interface{}{"testkey3": "testvalue3"}})
if err != nil {
t.Fatalf(fmt.Sprintf("error simulating external change; err=%s", err))
}

},

Config: testKVSecretV2Config_initial(mount, name),

Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "data.zip", "zap"),
resource.TestCheckResourceAttr(resourceName, "data.foo", "bar"),
resource.TestCheckResourceAttr(resourceName, "data.flag", "false"),
resource.TestCheckResourceAttr(resourceName, "data_json", "{\"flag\":false,\"foo\":\"bar\",\"zip\":\"zap\"}"),
//we check that the provider updated vault to match the the terraform config therefor creating a new version the secret.
resource.TestCheckResourceAttr(resourceName, "metadata.version", "3"),
),
},
},
},
)
}

func readKVData(t *testing.T, mount, name string) {
t.Helper()
client := testProvider.Meta().(*provider.ProviderMeta).MustGetClient()
Expand All @@ -235,6 +287,7 @@ func readKVData(t *testing.T, mount, name string) {
if !reflect.DeepEqual(resp.Data["data"], testKVV2Data) {
t.Fatalf("kvv2 secret data does not match got: %#+v, want: %#+v", resp.Data["data"], testKVV2Data)
}

}

func writeKVData(t *testing.T, mount, name string) {
Expand Down

0 comments on commit b18d2d3

Please sign in to comment.