-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
New Resource: azurerm_key_vault_managed_hardware_security_module_role_definition
and azurerm_key_vault_managed_hardware_security_module_role_assignment
for managed HSM
#22332
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,196 @@ | ||||||
package keyvault | ||||||
|
||||||
import ( | ||||||
"context" | ||||||
"fmt" | ||||||
"regexp" | ||||||
"time" | ||||||
|
||||||
"github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2022-04-01/roledefinitions" | ||||||
|
||||||
"github.com/hashicorp/terraform-provider-azurerm/internal/locks" | ||||||
|
||||||
"github.com/hashicorp/go-azure-helpers/lang/pointer" | ||||||
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk" | ||||||
"github.com/hashicorp/terraform-provider-azurerm/internal/services/keyvault/parse" | ||||||
"github.com/hashicorp/terraform-provider-azurerm/internal/services/keyvault/validate" | ||||||
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" | ||||||
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" | ||||||
"github.com/hashicorp/terraform-provider-azurerm/utils" | ||||||
"github.com/tombuildsstuff/kermit/sdk/keyvault/7.4/keyvault" | ||||||
) | ||||||
|
||||||
type ManagedHSMRoleAssignmentModel struct { | ||||||
VaultBaseUrl string `tfschema:"vault_base_url"` | ||||||
Name string `tfschema:"name"` | ||||||
Scope string `tfschema:"scope"` | ||||||
RoleDefinitionId string `tfschema:"role_definition_id"` | ||||||
PrincipalId string `tfschema:"principal_id"` | ||||||
ResourceId string `tfschema:"resource_id"` | ||||||
} | ||||||
|
||||||
type KeyVaultRoleAssignmentResource struct{} | ||||||
|
||||||
var _ sdk.Resource = (*KeyVaultRoleAssignmentResource)(nil) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @wuxu92 you missed this |
||||||
|
||||||
func (m KeyVaultRoleAssignmentResource) Arguments() map[string]*pluginsdk.Schema { | ||||||
return map[string]*pluginsdk.Schema{ | ||||||
"vault_base_url": { | ||||||
Type: pluginsdk.TypeString, | ||||||
Required: true, | ||||||
ForceNew: true, | ||||||
ValidateFunc: validation.StringIsNotEmpty, | ||||||
}, | ||||||
|
||||||
"name": { | ||||||
Type: pluginsdk.TypeString, | ||||||
Required: true, | ||||||
ForceNew: true, | ||||||
ValidateFunc: validation.StringIsNotEmpty, | ||||||
}, | ||||||
|
||||||
"scope": { | ||||||
Type: pluginsdk.TypeString, | ||||||
Required: true, | ||||||
ForceNew: true, | ||||||
ValidateFunc: validation.StringMatch(regexp.MustCompile(`^(/|/keys|/keys/.+)$`), "scope should be one of `/`, `/keys', `/keys/<key_name>`"), | ||||||
}, | ||||||
|
||||||
"role_definition_id": { | ||||||
Type: pluginsdk.TypeString, | ||||||
Required: true, | ||||||
ForceNew: true, | ||||||
ValidateFunc: roledefinitions.ValidateScopedRoleDefinitionID, | ||||||
}, | ||||||
|
||||||
"principal_id": { | ||||||
Type: pluginsdk.TypeString, | ||||||
Required: true, | ||||||
ForceNew: true, | ||||||
ValidateFunc: validation.StringIsNotEmpty, | ||||||
}, | ||||||
} | ||||||
} | ||||||
|
||||||
func (m KeyVaultRoleAssignmentResource) Attributes() map[string]*pluginsdk.Schema { | ||||||
return map[string]*pluginsdk.Schema{ | ||||||
"resource_id": { | ||||||
Type: pluginsdk.TypeString, | ||||||
Computed: true, | ||||||
}, | ||||||
} | ||||||
} | ||||||
|
||||||
func (m KeyVaultRoleAssignmentResource) ModelObject() interface{} { | ||||||
return &ManagedHSMRoleAssignmentModel{} | ||||||
} | ||||||
|
||||||
func (m KeyVaultRoleAssignmentResource) ResourceType() string { | ||||||
return "azurerm_key_vault_managed_hardware_security_module_role_assignment" | ||||||
} | ||||||
|
||||||
func (m KeyVaultRoleAssignmentResource) Create() sdk.ResourceFunc { | ||||||
return sdk.ResourceFunc{ | ||||||
Timeout: 30 * time.Minute, | ||||||
Func: func(ctx context.Context, meta sdk.ResourceMetaData) (err error) { | ||||||
client := meta.Client.KeyVault.MHSMRoleAssignmentsClient | ||||||
|
||||||
var model ManagedHSMRoleAssignmentModel | ||||||
if err := meta.Decode(&model); err != nil { | ||||||
return err | ||||||
} | ||||||
|
||||||
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.NewMHSMNestedItemID(model.VaultBaseUrl, model.Scope, parse.RoleAssignmentType, model.Name) | ||||||
if err != nil { | ||||||
return err | ||||||
} | ||||||
|
||||||
existing, err := client.Get(ctx, model.VaultBaseUrl, model.Scope, model.Name) | ||||||
if !utils.ResponseWasNotFound(existing.Response) { | ||||||
if err != nil { | ||||||
return fmt.Errorf("retrieving %s: %v", id.ID(), err) | ||||||
} | ||||||
return meta.ResourceRequiresImport(m.ResourceType(), id) | ||||||
} | ||||||
|
||||||
var param keyvault.RoleAssignmentCreateParameters | ||||||
param.Properties = &keyvault.RoleAssignmentProperties{ | ||||||
PrincipalID: pointer.FromString(model.PrincipalId), | ||||||
RoleDefinitionID: pointer.FromString(model.RoleDefinitionId), | ||||||
} | ||||||
_, err = client.Create(ctx, model.VaultBaseUrl, model.Scope, model.Name, param) | ||||||
if err != nil { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. lines can be combined |
||||||
return fmt.Errorf("creating %s: %v", id.ID(), err) | ||||||
} | ||||||
|
||||||
meta.SetID(id) | ||||||
return nil | ||||||
}, | ||||||
} | ||||||
} | ||||||
|
||||||
func (m KeyVaultRoleAssignmentResource) Read() sdk.ResourceFunc { | ||||||
return sdk.ResourceFunc{ | ||||||
Timeout: 5 * time.Minute, | ||||||
Func: func(ctx context.Context, meta sdk.ResourceMetaData) error { | ||||||
client := meta.Client.KeyVault.MHSMRoleAssignmentsClient | ||||||
|
||||||
id, err := parse.MHSMNestedItemID(meta.ResourceData.Id()) | ||||||
if err != nil { | ||||||
return err | ||||||
} | ||||||
|
||||||
result, err := client.Get(ctx, id.VaultBaseUrl, id.Scope, id.Name) | ||||||
if err != nil { | ||||||
if utils.ResponseWasNotFound(result.Response) { | ||||||
return meta.MarkAsGone(id) | ||||||
} | ||||||
return err | ||||||
} | ||||||
|
||||||
var model ManagedHSMRoleAssignmentModel | ||||||
if err := meta.Decode(&model); err != nil { | ||||||
return err | ||||||
} | ||||||
|
||||||
prop := result.Properties | ||||||
model.Name = pointer.From(result.Name) | ||||||
model.VaultBaseUrl = id.VaultBaseUrl | ||||||
model.Scope = id.Scope | ||||||
|
||||||
model.RoleDefinitionId = pointer.ToString(prop.RoleDefinitionID) | ||||||
model.PrincipalId = pointer.ToString(prop.PrincipalID) | ||||||
model.ResourceId = pointer.ToString(result.ID) | ||||||
|
||||||
return meta.Encode(&model) | ||||||
}, | ||||||
} | ||||||
} | ||||||
|
||||||
func (m KeyVaultRoleAssignmentResource) Delete() sdk.ResourceFunc { | ||||||
return sdk.ResourceFunc{ | ||||||
Timeout: 10 * time.Minute, | ||||||
Func: func(ctx context.Context, meta sdk.ResourceMetaData) error { | ||||||
id, err := parse.MHSMNestedItemID(meta.ResourceData.Id()) | ||||||
if err != nil { | ||||||
return err | ||||||
} | ||||||
|
||||||
meta.Logger.Infof("deleting %s", id) | ||||||
|
||||||
locks.ByName(id.VaultBaseUrl, "azurerm_key_vault_managed_hardware_security_module") | ||||||
defer locks.UnlockByName(id.VaultBaseUrl, "azurerm_key_vault_managed_hardware_security_module") | ||||||
if _, err := meta.Client.KeyVault.MHSMRoleAssignmentsClient.Delete(ctx, id.VaultBaseUrl, id.Scope, id.Name); err != nil { | ||||||
return fmt.Errorf("deleting %s: %v", id.ID(), err) | ||||||
} | ||||||
return nil | ||||||
}, | ||||||
} | ||||||
} | ||||||
|
||||||
func (m KeyVaultRoleAssignmentResource) IDValidationFunc() pluginsdk.SchemaValidateFunc { | ||||||
return validate.MHSMNestedItemId | ||||||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,82 @@ | ||||||
package keyvault_test | ||||||
|
||||||
import ( | ||||||
"context" | ||||||
"fmt" | ||||||
|
||||||
"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" | ||||||
|
||||||
"github.com/hashicorp/terraform-provider-azurerm/internal/clients" | ||||||
"github.com/hashicorp/terraform-provider-azurerm/internal/services/keyvault/parse" | ||||||
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" | ||||||
"github.com/hashicorp/terraform-provider-azurerm/utils" | ||||||
) | ||||||
|
||||||
type KeyVaultRoleAssignmentResource struct{} | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should this be something like
Suggested change
|
||||||
|
||||||
// real test nested in TestAccKeyVaultManagedHardwareSecurityModule, only provide Exists logic here | ||||||
func (k KeyVaultRoleAssignmentResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { | ||||||
id, err := parse.MHSMNestedItemID(state.ID) | ||||||
if err != nil { | ||||||
return nil, err | ||||||
} | ||||||
resp, err := client.KeyVault.MHSMRoleAssignmentsClient.Get(ctx, id.VaultBaseUrl, id.Scope, id.Name) | ||||||
if err != nil { | ||||||
return nil, fmt.Errorf("retrieving Type %s: %+v", id, err) | ||||||
} | ||||||
return utils.Bool(resp.Properties != nil), nil | ||||||
} | ||||||
|
||||||
func (k KeyVaultRoleAssignmentResource) withRoleAssignment(data acceptance.TestData) string { | ||||||
roleDef := KeyVaultMHSMRoleDefinitionResource{}.withRoleDefinition(data) | ||||||
|
||||||
return fmt.Sprintf(` | ||||||
|
||||||
|
||||||
%s | ||||||
|
||||||
locals { | ||||||
assignmentTestName = "1e243909-064c-6ac3-84e9-1c8bf8d6ad52" | ||||||
} | ||||||
|
||||||
data "azurerm_key_vault_managed_hardware_security_module_role_definition" "test" { | ||||||
name = azurerm_key_vault_managed_hardware_security_module_role_definition.test.name | ||||||
vault_base_url = azurerm_key_vault_managed_hardware_security_module.test.hsm_uri | ||||||
} | ||||||
|
||||||
resource "azurerm_key_vault_managed_hardware_security_module_role_assignment" "test" { | ||||||
vault_base_url = azurerm_key_vault_managed_hardware_security_module.test.hsm_uri | ||||||
name = local.assignmentTestName | ||||||
scope = "/keys" | ||||||
role_definition_id = data.azurerm_key_vault_managed_hardware_security_module_role_definition.test.resource_manager_id | ||||||
principal_id = data.azurerm_client_config.current.object_id | ||||||
} | ||||||
`, roleDef) | ||||||
} | ||||||
|
||||||
func (k KeyVaultRoleAssignmentResource) withBuiltInRoleAssignment(data acceptance.TestData) string { | ||||||
roleDef := k.withRoleAssignment(data) | ||||||
|
||||||
return fmt.Sprintf(` | ||||||
|
||||||
|
||||||
%s | ||||||
|
||||||
locals { | ||||||
assignmentOfficerName = "706c03c7-69ad-33e5-2796-b3380d3a6e1a" | ||||||
} | ||||||
|
||||||
data "azurerm_key_vault_managed_hardware_security_module_role_definition" "officer" { | ||||||
vault_base_url = azurerm_key_vault_managed_hardware_security_module.test.hsm_uri | ||||||
name = "515eb02d-2335-4d2d-92f2-b1cbdf9c3778" | ||||||
} | ||||||
|
||||||
resource "azurerm_key_vault_managed_hardware_security_module_role_assignment" "officer" { | ||||||
vault_base_url = azurerm_key_vault_managed_hardware_security_module.test.hsm_uri | ||||||
name = local.assignmentOfficerName | ||||||
scope = "/keys" | ||||||
role_definition_id = data.azurerm_key_vault_managed_hardware_security_module_role_definition.officer.resource_manager_id | ||||||
principal_id = data.azurerm_client_config.current.object_id | ||||||
} | ||||||
`, roleDef) | ||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shoudln't these all be