mirror of
https://github.com/opentofu/terraform-provider-vault.git
synced 2026-01-11 19:46:35 +00:00
Do not panic on Vault PKI roles without the cn_validations field (#2398)
* Do not panic on Vault PKI roles without the cn_validations field
- When we added support for the cn_validations field within PR1820
the code was tested against Vault versions 1.12 and higher.
- If Vault is an earlier version than 1.12 TFVP will panic as we
attempt to cast the missing field to an []interface{} value.
- This fix hardens the parsing path for slice values within the
PKI role parsing to properly extract out a []string value
* Add changelog
This commit is contained in:
parent
4b26c7a2c3
commit
6af08b851b
4 changed files with 84 additions and 5 deletions
|
|
@ -1,5 +1,10 @@
|
|||
## Unreleased
|
||||
|
||||
BUGS:
|
||||
|
||||
* Do not panic on Vault PKI roles without the cn_validations field: ([#2398](https://github.com/hashicorp/terraform-provider-vault/pull/2398))
|
||||
|
||||
|
||||
## 4.6.0 (Jan 15, 2025)
|
||||
|
||||
FEATURES:
|
||||
|
|
|
|||
38
util/util.go
38
util/util.go
|
|
@ -14,6 +14,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/cenkalti/backoff/v4"
|
||||
"github.com/hashicorp/go-secure-stdlib/parseutil"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"github.com/hashicorp/vault/api"
|
||||
)
|
||||
|
|
@ -450,3 +451,40 @@ func RetryWrite(client *api.Client, path string, data map[string]interface{}, re
|
|||
log.Printf("[WARN] Writing to path %q failed, retrying in %s", path, duration)
|
||||
})
|
||||
}
|
||||
|
||||
// GetStringSliceFromSecret will return a string slice from the secret data within the provided field name if it exists.
|
||||
// The bool return value will be false if the field does not exist or is not a string slice. It will be true if the field
|
||||
// exists and was an empty slice.
|
||||
func GetStringSliceFromSecret(secret *api.Secret, fieldName string) ([]string, bool) {
|
||||
if secret == nil || secret.Data == nil {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
rawVal, exists := secret.Data[fieldName]
|
||||
if !exists {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
rv := reflect.ValueOf(rawVal)
|
||||
switch rv.Kind() {
|
||||
case reflect.Slice:
|
||||
if rv.IsNil() {
|
||||
return nil, false
|
||||
}
|
||||
case reflect.Array:
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
|
||||
output := make([]string, rv.Len())
|
||||
|
||||
for i := 0; i < rv.Len(); i++ {
|
||||
myStr, err := parseutil.ParseString(rv.Index(i).Interface())
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
output[i] = myStr
|
||||
}
|
||||
|
||||
return output, true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -871,3 +871,39 @@ func TestRetryWrite(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetStringSliceFromSecret(t *testing.T) {
|
||||
fieldName := "foo"
|
||||
var testArray [2]string
|
||||
testArray[0] = "1"
|
||||
testArray[1] = "2"
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
secretData map[string]interface{}
|
||||
want []string
|
||||
wantOk bool
|
||||
}{
|
||||
{"nil-data", nil, nil, false},
|
||||
{"field-missing", map[string]interface{}{}, nil, false},
|
||||
{"nil-element", map[string]interface{}{fieldName: nil}, nil, false},
|
||||
{"not-a-slice", map[string]interface{}{fieldName: "test-value"}, nil, false},
|
||||
{"array-val", map[string]interface{}{fieldName: testArray}, []string{"1", "2"}, true},
|
||||
{"mixed-slice", map[string]interface{}{fieldName: []interface{}{1, "2"}}, []string{"1", "2"}, true},
|
||||
{"int-slice", map[string]interface{}{fieldName: []int{1, 2}}, []string{"1", "2"}, true},
|
||||
{"string-slice", map[string]interface{}{fieldName: []string{"test1", "test2"}}, []string{"test1", "test2"}, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
secret := &api.Secret{Data: tt.secretData}
|
||||
got, gotOk := GetStringSliceFromSecret(secret, fieldName)
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("GetStringSliceFromSecret() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
if gotOk != tt.wantOk {
|
||||
t.Errorf("GetStringSliceFromSecret() gotOk = %v, wantOk %v", gotOk, tt.wantOk)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@ import (
|
|||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
||||
|
||||
"github.com/hashicorp/terraform-provider-vault/internal/consts"
|
||||
"github.com/hashicorp/terraform-provider-vault/internal/pki"
|
||||
"github.com/hashicorp/terraform-provider-vault/internal/provider"
|
||||
"github.com/hashicorp/terraform-provider-vault/util"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -575,10 +575,10 @@ func pkiSecretBackendRoleRead(_ context.Context, d *schema.ResourceData, meta in
|
|||
listFields := append(pkiSecretListFields, consts.FieldKeyUsage)
|
||||
// handle TypeList
|
||||
for _, k := range listFields {
|
||||
list := expandStringSlice(secret.Data[k].([]interface{}))
|
||||
|
||||
if len(list) > 0 {
|
||||
d.Set(k, list)
|
||||
if list, ok := util.GetStringSliceFromSecret(secret, k); ok {
|
||||
if len(list) > 0 {
|
||||
d.Set(k, list)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue