Skip to content

Commit

Permalink
Support versionless Key Vault Child ID in azurerm_api_management
Browse files Browse the repository at this point in the history
Signed-off-by: Sune Keller <absukl@almbrand.dk>
  • Loading branch information
sirlatrom committed May 11, 2020
1 parent b2bc8ea commit b5517d9
Show file tree
Hide file tree
Showing 3 changed files with 191 additions and 1 deletion.
53 changes: 53 additions & 0 deletions azurerm/helpers/azure/key_vault_child.go
Expand Up @@ -42,6 +42,38 @@ func ParseKeyVaultChildID(id string) (*KeyVaultChildID, error) {
return &childId, nil
}

func ParseKeyVaultChildIDVersionOptional(id string) (*KeyVaultChildID, error) {
// example: https://tharvey-keyvault.vault.azure.net/type/bird/fdf067c93bbb4b22bff4d8b7a9a56217
idURL, err := url.ParseRequestURI(id)
if err != nil {
return nil, fmt.Errorf("Cannot parse Azure KeyVault Child Id: %s", err)
}

path := idURL.Path

path = strings.TrimPrefix(path, "/")
path = strings.TrimSuffix(path, "/")

components := strings.Split(path, "/")

if len(components) != 2 && len(components) != 3 {
return nil, fmt.Errorf("Azure KeyVault Child Id should have 2 or 3 segments, got %d: '%s'", len(components), path)
}

version := ""
if len(components) == 3 {
version = components[2]
}

childId := KeyVaultChildID{
KeyVaultBaseUrl: fmt.Sprintf("%s://%s/", idURL.Scheme, idURL.Host),
Name: components[1],
Version: version,
}

return &childId, nil
}

func ValidateKeyVaultChildName(v interface{}, k string) (warnings []string, errors []error) {
value := v.(string)

Expand Down Expand Up @@ -72,3 +104,24 @@ func ValidateKeyVaultChildId(i interface{}, k string) (warnings []string, errors

return warnings, errors
}

// Unfortunately this can't (easily) go in the Validate package
// since there's a circular reference on this package
func ValidateKeyVaultChildIdVersionOptional(i interface{}, k string) (warnings []string, errors []error) {
if warnings, errors = validation.StringIsNotEmpty(i, k); len(errors) > 0 {
return warnings, errors
}

v, ok := i.(string)
if !ok {
errors = append(errors, fmt.Errorf("Expected %s to be a string!", k))
return warnings, errors
}

if _, err := ParseKeyVaultChildIDVersionOptional(v); err != nil {
errors = append(errors, fmt.Errorf("Error parsing Key Vault Child ID: %s", err))
return warnings, errors
}

return warnings, errors
}
137 changes: 137 additions & 0 deletions azurerm/helpers/azure/key_vault_child_test.go
Expand Up @@ -55,6 +55,59 @@ func TestAccAzureRMValidateKeyVaultChildID(t *testing.T) {
}
}

func TestAccAzureRMValidateKeyVaultChildIDVersionOptional(t *testing.T) {
cases := []struct {
Input string
ExpectError bool
}{
{
Input: "",
ExpectError: true,
},
{
Input: "https://my-keyvault.vault.azure.net/secrets",
ExpectError: true,
},
{
Input: "https://my-keyvault.vault.azure.net/secrets/bird",
ExpectError: false,
},
{
Input: "https://my-keyvault.vault.azure.net/secrets/bird/fdf067c93bbb4b22bff4d8b7a9a56217",
ExpectError: false,
},
{
Input: "https://my-keyvault.vault.azure.net/certificates/hello/world",
ExpectError: false,
},
{
Input: "https://my-keyvault.vault.azure.net/keys/castle/1492",
ExpectError: false,
},
{
Input: "https://my-keyvault.vault.azure.net/secrets/bird/fdf067c93bbb4b22bff4d8b7a9a56217/XXX",
ExpectError: true,
},
}

for _, tc := range cases {
warnings, err := ValidateKeyVaultChildIdVersionOptional(tc.Input, "example")
if err != nil {
if !tc.ExpectError {
t.Fatalf("Got error for input %q: %+v", tc.Input, err)
}

return
}

if tc.ExpectError && len(warnings) == 0 {
t.Fatalf("Got no errors for input %q but expected some", tc.Input)
} else if !tc.ExpectError && len(warnings) > 0 {
t.Fatalf("Got %d errors for input %q when didn't expect any", len(warnings), tc.Input)
}
}
}

func TestAccAzureRMKeyVaultChild_parseID(t *testing.T) {
cases := []struct {
Input string
Expand Down Expand Up @@ -134,6 +187,90 @@ func TestAccAzureRMKeyVaultChild_parseID(t *testing.T) {
}
}

func TestAccAzureRMKeyVaultChild_parseIDVersionOptional(t *testing.T) {
cases := []struct {
Input string
Expected KeyVaultChildID
ExpectError bool
}{
{
Input: "",
ExpectError: true,
},
{
Input: "https://my-keyvault.vault.azure.net/secrets",
ExpectError: true,
},
{
Input: "https://my-keyvault.vault.azure.net/secrets/bird",
ExpectError: false,
Expected: KeyVaultChildID{
Name: "bird",
KeyVaultBaseUrl: "https://my-keyvault.vault.azure.net/",
Version: "",
},
},
{
Input: "https://my-keyvault.vault.azure.net/secrets/bird/fdf067c93bbb4b22bff4d8b7a9a56217",
ExpectError: false,
Expected: KeyVaultChildID{
Name: "bird",
KeyVaultBaseUrl: "https://my-keyvault.vault.azure.net/",
Version: "fdf067c93bbb4b22bff4d8b7a9a56217",
},
},
{
Input: "https://my-keyvault.vault.azure.net/certificates/hello/world",
ExpectError: false,
Expected: KeyVaultChildID{
Name: "hello",
KeyVaultBaseUrl: "https://my-keyvault.vault.azure.net/",
Version: "world",
},
},
{
Input: "https://my-keyvault.vault.azure.net/keys/castle/1492",
ExpectError: false,
Expected: KeyVaultChildID{
Name: "castle",
KeyVaultBaseUrl: "https://my-keyvault.vault.azure.net/",
Version: "1492",
},
},
{
Input: "https://my-keyvault.vault.azure.net/secrets/bird/fdf067c93bbb4b22bff4d8b7a9a56217/XXX",
ExpectError: true,
},
}

for _, tc := range cases {
secretId, err := ParseKeyVaultChildIDVersionOptional(tc.Input)
if err != nil {
if !tc.ExpectError {
t.Fatalf("Got error for ID '%s': %+v", tc.Input, err)
}

return
}

if secretId == nil {
t.Fatalf("Expected a SecretID to be parsed for ID '%s', got nil.", tc.Input)
}

if tc.Expected.KeyVaultBaseUrl != secretId.KeyVaultBaseUrl {
t.Fatalf("Expected 'KeyVaultBaseUrl' to be '%s', got '%s' for ID '%s'", tc.Expected.KeyVaultBaseUrl, secretId.KeyVaultBaseUrl, tc.Input)
}

if tc.Expected.Name != secretId.Name {
t.Fatalf("Expected 'Version' to be '%s', got '%s' for ID '%s'", tc.Expected.Name, secretId.Name, tc.Input)
}

if tc.Expected.Version != secretId.Version {
t.Fatalf("Expected 'Version' to be '%s', got '%s' for ID '%s'", tc.Expected.Version, secretId.Version, tc.Input)
}
}
}

func TestAccAzureRMKeyVaultChild_validateName(t *testing.T) {
cases := []struct {
Input string
Expand Down
Expand Up @@ -1058,7 +1058,7 @@ func apiManagementResourceHostnameSchema(schemaName string) map[string]*schema.S
"key_vault_id": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: azure.ValidateKeyVaultChildId,
ValidateFunc: azure.ValidateKeyVaultChildIdVersionOptional,
ConflictsWith: []string{
fmt.Sprintf("hostname_configuration.0.%s.0.certificate", schemaName),
fmt.Sprintf("hostname_configuration.0.%s.0.certificate_password", schemaName),
Expand Down

0 comments on commit b5517d9

Please sign in to comment.