Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

azurerm_api_management - support key_vault_id's without a version #6723

Merged
merged 2 commits into from May 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 @@ -1139,7 +1139,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