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

managed_hsm_role_*_ids: use specific resource id to replace generic nested item id #25323

Merged
merged 3 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func (m KeyVaultManagedHSMRoleAssignmentResource) Create() sdk.ResourceFunc {
locks.ByName(model.VaultBaseUrl, "azurerm_key_vault_managed_hardware_security_module")
defer locks.UnlockByName(model.VaultBaseUrl, "azurerm_key_vault_managed_hardware_security_module")

id, err := parse.NewNestedItemID(model.VaultBaseUrl, model.Scope, parse.RoleAssignmentType, model.Name)
id, err := parse.NewManagedHSMRoleAssignmentID(model.VaultBaseUrl, model.Scope, model.Name)
if err != nil {
return err
}
Expand Down Expand Up @@ -140,7 +140,7 @@ func (m KeyVaultManagedHSMRoleAssignmentResource) Read() sdk.ResourceFunc {
Func: func(ctx context.Context, meta sdk.ResourceMetaData) error {
client := meta.Client.ManagedHSMs.DataPlaneRoleAssignmentsClient

id, err := parse.NestedItemID(meta.ResourceData.Id())
id, err := parse.ManagedHSMRoleAssignmentID(meta.ResourceData.Id())
if err != nil {
return err
}
Expand Down Expand Up @@ -179,7 +179,7 @@ func (m KeyVaultManagedHSMRoleAssignmentResource) Delete() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 10 * time.Minute,
Func: func(ctx context.Context, meta sdk.ResourceMetaData) error {
id, err := parse.NestedItemID(meta.ResourceData.Id())
id, err := parse.ManagedHSMRoleAssignmentID(meta.ResourceData.Id())
if err != nil {
return err
}
Expand All @@ -197,5 +197,5 @@ func (m KeyVaultManagedHSMRoleAssignmentResource) Delete() sdk.ResourceFunc {
}

func (m KeyVaultManagedHSMRoleAssignmentResource) IDValidationFunc() pluginsdk.SchemaValidateFunc {
return validate.NestedItemId
return validate.ManagedHSMRoleAssignmentId
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type KeyVaultManagedHSMRoleAssignmentResource struct{}

// real test nested in TestAccKeyVaultManagedHardwareSecurityModule, only provide Exists logic here
func (k KeyVaultManagedHSMRoleAssignmentResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
id, err := parse.NestedItemID(state.ID)
id, err := parse.ManagedHSMRoleAssignmentID(state.ID)
if err != nil {
return nil, err
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ func (k KeyvaultMHSMRoleDefinitionDataSource) Read() sdk.ResourceFunc {
return err
}

id, err := parse.NewNestedItemID(model.VaultBaseUrl, roleDefinitionScope, parse.RoleDefinitionType, model.Name)
id, err := parse.NewManagedHSMRoleDefinitionID(model.VaultBaseUrl, roleDefinitionScope, model.Name)
if err != nil {
return err
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ func (k KeyVaultMHSMRoleDefinitionResource) Create() sdk.ResourceFunc {
locks.ByName(model.VaultBaseUrl, "azurerm_key_vault_managed_hardware_security_module")
defer locks.UnlockByName(model.VaultBaseUrl, "azurerm_key_vault_managed_hardware_security_module")

id, err := parse.NewNestedItemID(model.VaultBaseUrl, roleDefinitionScope, parse.RoleDefinitionType, model.Name)
id, err := parse.NewManagedHSMRoleDefinitionID(model.VaultBaseUrl, roleDefinitionScope, model.Name)
if err != nil {
return err
}
Expand Down Expand Up @@ -207,7 +207,7 @@ func (k KeyVaultMHSMRoleDefinitionResource) Read() sdk.ResourceFunc {
Timeout: 5 * time.Minute,
Func: func(ctx context.Context, meta sdk.ResourceMetaData) error {
// import has no model data but only id
id, err := parse.NestedItemID(meta.ResourceData.Id())
id, err := parse.ManagedHSMRoleDefinitionID(meta.ResourceData.Id())
if err != nil {
return err
}
Expand Down Expand Up @@ -258,7 +258,7 @@ func (k KeyVaultMHSMRoleDefinitionResource) Update() sdk.ResourceFunc {
return err
}

id, err := parse.NewNestedItemID(model.VaultBaseUrl, roleDefinitionScope, parse.RoleDefinitionType, model.Name)
id, err := parse.NewManagedHSMRoleDefinitionID(model.VaultBaseUrl, roleDefinitionScope, model.Name)
if err != nil {
return err
}
Expand Down Expand Up @@ -297,7 +297,7 @@ func (k KeyVaultMHSMRoleDefinitionResource) Delete() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 10 * time.Minute,
Func: func(ctx context.Context, meta sdk.ResourceMetaData) error {
id, err := parse.NestedItemID(meta.ResourceData.Id())
id, err := parse.ManagedHSMRoleDefinitionID(meta.ResourceData.Id())
if err != nil {
return err
}
Expand All @@ -314,7 +314,7 @@ func (k KeyVaultMHSMRoleDefinitionResource) Delete() sdk.ResourceFunc {
}

func (k KeyVaultMHSMRoleDefinitionResource) IDValidationFunc() pluginsdk.SchemaValidateFunc {
return validate.NestedItemId
return validate.ManagedHSMRoleDefinitionId
}

func expandKeyVaultMHSMRolePermissions(perms []Permission) *[]keyvault.Permission {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type KeyVaultMHSMRoleDefinitionResource struct{}
// real test nested in TestAccKeyVaultManagedHardwareSecurityModule, only provide Exists logic here
func (k KeyVaultMHSMRoleDefinitionResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
baseURL := state.Attributes["vault_base_url"]
id, err := parse.NestedItemID(state.ID)
id, err := parse.ManagedHSMRoleDefinitionID(state.ID)
if err != nil {
return nil, err
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package parse

import (
"fmt"
"net/url"
"strings"

"github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids"
)

var _ resourceids.Id = ManagedHSMRoleAssignmentId{}

type ManagedHSMRoleAssignmentId struct {
VaultBaseUrl string
Scope string
Name string
}

func NewManagedHSMRoleAssignmentID(hsmBaseUrl, scope string, name string) (*ManagedHSMRoleAssignmentId, error) {
keyVaultUrl, err := url.Parse(hsmBaseUrl)
if err != nil || hsmBaseUrl == "" {
return nil, fmt.Errorf("parsing managedHSM nested itemID %q: %+v", hsmBaseUrl, err)
}

return &ManagedHSMRoleAssignmentId{
VaultBaseUrl: keyVaultUrl.String(),
Scope: scope,
Name: name,
}, nil
}

func (n ManagedHSMRoleAssignmentId) ID() string {
// example: https://tharvey-keyvault.managedhsm.azure.net///RoleAssignment/uuid-idshifds-fks
segments := []string{
strings.TrimSuffix(n.VaultBaseUrl, "/"),
n.Scope,
"RoleAssignment",
n.Name,
}
return strings.TrimSuffix(strings.Join(segments, "/"), "/")
}

func (n ManagedHSMRoleAssignmentId) String() string {
return n.ID()
}

func ManagedHSMRoleAssignmentID(input string) (*ManagedHSMRoleAssignmentId, error) {
idURL, err := url.ParseRequestURI(input)
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, "/")

nameSep := strings.LastIndex(path, "/")
if nameSep <= 0 {
return nil, fmt.Errorf("no name speparate exist in %s", input)
}
scope, name := path[:nameSep], path[nameSep+1:]

typeSep := strings.LastIndex(scope, "/")
if typeSep <= 0 {
return nil, fmt.Errorf("no type speparate exist in %s", input)
}
scope, typ := scope[:typeSep], scope[typeSep+1:]
if typ != "RoleAssignment" {
return nil, fmt.Errorf("invalid type %s, must be 'RoleAssignment'", typ)
}

childId := ManagedHSMRoleAssignmentId{
VaultBaseUrl: fmt.Sprintf("%s://%s/", idURL.Scheme, idURL.Host),
Scope: scope,
Name: name,
}

return &childId, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import (
"testing"
)

func TestNewMHSMNestedItemID(t *testing.T) {
mhsmType := RoleDefinitionType
func TestNewManagedHSMRoleAssignmentID(t *testing.T) {
mhsmType := "RoleDefinition"
cases := []struct {
Scenario string
keyVaultBaseUrl string
Expand Down Expand Up @@ -42,7 +42,7 @@ func TestNewMHSMNestedItemID(t *testing.T) {
},
}
for idx, tc := range cases {
id, err := NewNestedItemID(tc.keyVaultBaseUrl, tc.Scope, mhsmType, tc.Name)
id, err := NewManagedHSMRoleDefinitionID(tc.keyVaultBaseUrl, tc.Scope, tc.Name)
if err != nil {
if !tc.ExpectError {
t.Fatalf("Got error for New Resource ID '%s': %+v", tc.keyVaultBaseUrl, err)
Expand All @@ -56,11 +56,11 @@ func TestNewMHSMNestedItemID(t *testing.T) {
}
}

func TestParseMHSMNestedItemID(t *testing.T) {
typ := RoleDefinitionType
func TestParseManagedHSMRoleAssignmentID(t *testing.T) {
typ := "RoleDefinition"
cases := []struct {
Input string
Expected NestedItemId
Expected ManagedHSMRoleDefinitionId
ExpectError bool
}{
{
Expand All @@ -70,7 +70,7 @@ func TestParseMHSMNestedItemID(t *testing.T) {
{
Input: fmt.Sprintf("https://my-keyvault.managedhsm.azure.net///%s/test", typ),
ExpectError: true,
Expected: NestedItemId{
Expected: ManagedHSMRoleDefinitionId{
Name: "test",
VaultBaseUrl: "https://my-keyvault.managedhsm.azure.net/",
Scope: "/",
Expand All @@ -79,7 +79,7 @@ func TestParseMHSMNestedItemID(t *testing.T) {
{
Input: fmt.Sprintf("https://my-keyvault.managedhsm.azure.net///%s/bird", typ),
ExpectError: true,
Expected: NestedItemId{
Expected: ManagedHSMRoleDefinitionId{
Name: "bird",
VaultBaseUrl: "https://my-keyvault.managedhsm.azure.net/",
Scope: "/",
Expand All @@ -88,7 +88,7 @@ func TestParseMHSMNestedItemID(t *testing.T) {
{
Input: fmt.Sprintf("https://my-keyvault.managedhsm.azure.net///%s/bird", typ),
ExpectError: false,
Expected: NestedItemId{
Expected: ManagedHSMRoleDefinitionId{
Name: "bird",
VaultBaseUrl: "https://my-keyvault.managedhsm.azure.net/",
Scope: "/",
Expand All @@ -97,7 +97,7 @@ func TestParseMHSMNestedItemID(t *testing.T) {
{
Input: fmt.Sprintf("https://my-keyvault.managedhsm.azure.net//keys/%s/world", typ),
ExpectError: false,
Expected: NestedItemId{
Expected: ManagedHSMRoleDefinitionId{
Name: "world",
VaultBaseUrl: "https://my-keyvault.managedhsm.azure.net/",
Scope: "/keys",
Expand All @@ -106,7 +106,7 @@ func TestParseMHSMNestedItemID(t *testing.T) {
{
Input: fmt.Sprintf("https://my-keyvault.managedhsm.azure.net//keys/%s/fdf067c93bbb4b22bff4d8b7a9a56217", typ),
ExpectError: true,
Expected: NestedItemId{
Expected: ManagedHSMRoleDefinitionId{
Name: "fdf067c93bbb4b22bff4d8b7a9a56217",
VaultBaseUrl: "https://my-keyvault.managedhsm.azure.net/",
Scope: "/keys",
Expand All @@ -115,7 +115,7 @@ func TestParseMHSMNestedItemID(t *testing.T) {
{
Input: "https://kvhsm23030816100222.managedhsm.azure.net///RoleDefinition/862d4d5e-bf01-11ed-a49d-00155d61ee9e",
ExpectError: true,
Expected: NestedItemId{
Expected: ManagedHSMRoleDefinitionId{
Name: "862d4d5e-bf01-11ed-a49d-00155d61ee9e",
VaultBaseUrl: "https://kvhsm23030816100222.managedhsm.azure.net/",
Scope: "/",
Expand All @@ -124,7 +124,7 @@ func TestParseMHSMNestedItemID(t *testing.T) {
}

for idx, tc := range cases {
secretId, err := NestedItemID(tc.Input)
roleId, err := ManagedHSMRoleDefinitionID(tc.Input)
if err != nil {
if tc.ExpectError {
continue
Expand All @@ -133,24 +133,24 @@ func TestParseMHSMNestedItemID(t *testing.T) {
t.Fatalf("Got error for ID '%s': %+v", tc.Input, err)
}

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

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

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

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

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