diff --git a/internal/services/authorization/client/client.go b/internal/services/authorization/client/client.go index 6d4de793afe1..6fb9cecbb716 100644 --- a/internal/services/authorization/client/client.go +++ b/internal/services/authorization/client/client.go @@ -15,6 +15,8 @@ import ( "github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/roleeligibilityscheduleinstances" "github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/roleeligibilityschedulerequests" "github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/roleeligibilityschedules" + "github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies" + "github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments" "github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2022-04-01/roleassignments" "github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2022-05-01-preview/roledefinitions" "github.com/hashicorp/terraform-provider-azurerm/internal/common" @@ -28,6 +30,8 @@ type Client struct { RoleEligibilityScheduleRequestClient *roleeligibilityschedulerequests.RoleEligibilityScheduleRequestsClient RoleEligibilityScheduleInstancesClient *roleeligibilityscheduleinstances.RoleEligibilityScheduleInstancesClient RoleEligibilitySchedulesClient *roleeligibilityschedules.RoleEligibilitySchedulesClient + RoleManagementPoliciesClient *rolemanagementpolicies.RoleManagementPoliciesClient + RoleManagementPolicyAssignmentsClient *rolemanagementpolicyassignments.RoleManagementPolicyAssignmentsClient ScopedRoleAssignmentsClient *roleassignments.RoleAssignmentsClient ScopedRoleDefinitionsClient *roledefinitions.RoleDefinitionsClient } @@ -73,6 +77,18 @@ func NewClient(o *common.ClientOptions) (*Client, error) { } o.Configure(roleEligibilitySchedulesClient.Client, o.Authorizers.ResourceManager) + roleManagementPoliciesClient, err := rolemanagementpolicies.NewRoleManagementPoliciesClientWithBaseURI(o.Environment.ResourceManager) + if err != nil { + return nil, fmt.Errorf("creating roleManagementPoliciesClient: %+v", err) + } + o.Configure(roleManagementPoliciesClient.Client, o.Authorizers.ResourceManager) + + roleManagementPolicyAssignmentClient, err := rolemanagementpolicyassignments.NewRoleManagementPolicyAssignmentsClientWithBaseURI(o.Environment.ResourceManager) + if err != nil { + return nil, fmt.Errorf("creating roleManagementPolicyAssignmentClient: %+v", err) + } + o.Configure(roleManagementPolicyAssignmentClient.Client, o.Authorizers.ResourceManager) + scopedRoleAssignmentsClient, err := roleassignments.NewRoleAssignmentsClientWithBaseURI(o.Environment.ResourceManager) if err != nil { return nil, fmt.Errorf("building Role Assignment Client: %+v", err) @@ -93,6 +109,8 @@ func NewClient(o *common.ClientOptions) (*Client, error) { RoleEligibilityScheduleRequestClient: roleEligibilityScheduleRequestClient, RoleEligibilityScheduleInstancesClient: roleEligibilityScheduleInstancesClient, RoleEligibilitySchedulesClient: roleEligibilitySchedulesClient, + RoleManagementPoliciesClient: roleManagementPoliciesClient, + RoleManagementPolicyAssignmentsClient: roleManagementPolicyAssignmentClient, ScopedRoleAssignmentsClient: scopedRoleAssignmentsClient, ScopedRoleDefinitionsClient: scopedRoleDefinitionsClient, }, nil diff --git a/internal/services/authorization/parse/role_management_policy.go b/internal/services/authorization/parse/role_management_policy.go new file mode 100644 index 000000000000..9b2a68c93a04 --- /dev/null +++ b/internal/services/authorization/parse/role_management_policy.go @@ -0,0 +1,66 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package parse + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +type RoleManagementPolicyId struct { + RoleDefinitionId string + Scope string +} + +var _ resourceids.Id = RoleManagementPolicyId{} + +func NewRoleManagementPolicyId(roleDefinitionId string, scope string) RoleManagementPolicyId { + return RoleManagementPolicyId{ + RoleDefinitionId: roleDefinitionId, + Scope: scope, + } +} + +// RoleManagementPolicyID parses 'input' into a RoleManagementPolicyId +func RoleManagementPolicyID(input string) (*RoleManagementPolicyId, error) { + parts := strings.Split(input, "|") + if len(parts) != 2 { + return nil, fmt.Errorf("could not parse Role Management Policy ID, invalid format %q", input) + } + + return &RoleManagementPolicyId{ + RoleDefinitionId: parts[0], + Scope: parts[1], + }, nil +} + +func (id RoleManagementPolicyId) ID() string { + return fmt.Sprintf("%s|%s", id.RoleDefinitionId, id.Scope) +} + +func (id RoleManagementPolicyId) String() string { + components := []string{ + fmt.Sprintf("Role Definition ID: %q", id.RoleDefinitionId), + } + if id.Scope != "" { + components = append(components, fmt.Sprintf("Scope: %q", id.Scope)) + } + return fmt.Sprintf("Role Definition (%s)", strings.Join(components, "\n")) +} + +func ValidateRoleManagementPolicyId(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := RoleManagementPolicyID(v); err != nil { + errors = append(errors, err) + } + + return +} diff --git a/internal/services/authorization/registration.go b/internal/services/authorization/registration.go index d849dffdbba9..09affdbac457 100644 --- a/internal/services/authorization/registration.go +++ b/internal/services/authorization/registration.go @@ -48,6 +48,7 @@ func (r Registration) SupportedResources() map[string]*pluginsdk.Resource { func (r Registration) DataSources() []sdk.DataSource { return []sdk.DataSource{ RoleDefinitionDataSource{}, + RoleManagementPolicyDataSource{}, } } @@ -57,6 +58,7 @@ func (r Registration) Resources() []sdk.Resource { PimEligibleRoleAssignmentResource{}, RoleAssignmentMarketplaceResource{}, RoleDefinitionResource{}, + RoleManagementPolicyResource{}, } return resources } diff --git a/internal/services/authorization/role_management_policy.go b/internal/services/authorization/role_management_policy.go new file mode 100644 index 000000000000..8f98b960f5ec --- /dev/null +++ b/internal/services/authorization/role_management_policy.go @@ -0,0 +1,632 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package authorization + +import ( + "context" + "fmt" + + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" + "github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies" + "github.com/hashicorp/go-azure-sdk/sdk/odata" + "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" +) + +func FindRoleManagementPolicyId(ctx context.Context, client *rolemanagementpolicies.RoleManagementPoliciesClient, scope string, roleDefinitionId string) (*rolemanagementpolicies.ScopedRoleManagementPolicyId, error) { + // List role management policies to find the latest policy for the provided scope and role definition + options := rolemanagementpolicies.ListForScopeOperationOptions{ + Filter: pointer.To(fmt.Sprintf("roleDefinitionId eq '%s'", odata.EscapeSingleQuote(roleDefinitionId))), + } + scopeId, err := commonids.ParseScopeID(scope) + if err != nil { + return nil, err + } + resp, err := client.ListForScope(ctx, *scopeId, options) + if err != nil { + return nil, fmt.Errorf("listing Role Management Policies for %s and Role Definition %q: %+v", scope, roleDefinitionId, err) + } + + // There should be one policy to represent a given scope and role definition + if resp.Model == nil { + return nil, fmt.Errorf("listing Role Management Policies for %s and Role Definition %q: result was nil", scope, roleDefinitionId) + } + if len(*resp.Model) != 1 { + return nil, fmt.Errorf("more than one Role Management Policy returned for %s and Role Definition %q", scope, roleDefinitionId) + } + + policy := (*resp.Model)[0] + if policy.Name == nil { + return nil, fmt.Errorf("retrieving Role Management Policy for %s and Role Definition %q: `name` was nil", scope, roleDefinitionId) + } + + // Note: the "Name" is actually a UUID that changes each time the policy is updated + id := rolemanagementpolicies.NewScopedRoleManagementPolicyID(scope, *policy.Name) + + return &id, nil +} + +func buildRoleManagementPolicyForUpdate(metadata *sdk.ResourceMetaData, rolePolicy *rolemanagementpolicies.RoleManagementPolicy) (*rolemanagementpolicies.RoleManagementPolicy, error) { + if rolePolicy == nil { + return nil, fmt.Errorf("existing Role Management Policy was nil") + } + + var model RoleManagementPolicyModel + if err := metadata.Decode(&model); err != nil { + return nil, fmt.Errorf("decoding: %+v", err) + } + + // Take the slice of rules and convert it to a map with the ID as the key + existingRules := make(map[string]rolemanagementpolicies.RawRoleManagementPolicyRuleImpl) + if props := rolePolicy.Properties; props != nil { + if props.Rules != nil { + for _, r := range *rolePolicy.Properties.Rules { // TODO + rule := r.(rolemanagementpolicies.RawRoleManagementPolicyRuleImpl) + existingRules[rule.Values["id"].(string)] = rule + } + } + } + updatedRules := make([]rolemanagementpolicies.RoleManagementPolicyRule, 0) + + if metadata.ResourceData.HasChange("eligible_assignment_rules") { + if expirationAdminEligibility, ok := existingRules["Expiration_Admin_Eligibility"]; ok && expirationAdminEligibility.Values != nil { + var expirationRequired bool + if expirationRequiredRaw, ok := expirationAdminEligibility.Values["isExpirationRequired"]; ok { + expirationRequired = expirationRequiredRaw.(bool) + } + + var maximumDuration string + if maximumDurationRaw, ok := expirationAdminEligibility.Values["maximumDuration"]; ok { + maximumDuration = maximumDurationRaw.(string) + } + + if len(model.EligibleAssignmentRules) == 1 { + if expirationRequired != model.EligibleAssignmentRules[0].ExpirationRequired { + expirationRequired = model.EligibleAssignmentRules[0].ExpirationRequired + } + if maximumDuration != model.EligibleAssignmentRules[0].ExpireAfter && + model.EligibleAssignmentRules[0].ExpireAfter != "" { + maximumDuration = model.EligibleAssignmentRules[0].ExpireAfter + } + } + + var id, ruleType string + var target map[string]interface{} + if idRaw, ok := expirationAdminEligibility.Values["id"]; ok { + id = idRaw.(string) + } + if ruleTypeRaw, ok := expirationAdminEligibility.Values["ruleType"]; ok { + ruleType = ruleTypeRaw.(string) + } + if targetRaw, ok := expirationAdminEligibility.Values["target"]; ok { + target = targetRaw.(map[string]interface{}) + } + + updatedRules = append(updatedRules, map[string]interface{}{ + "id": id, + "ruleType": ruleType, + "target": target, + "isExpirationRequired": expirationRequired, + "maximumDuration": maximumDuration, + }) + } + } + + if metadata.ResourceData.HasChange("active_assignment_rules.0.require_multifactor_authentication") || + metadata.ResourceData.HasChange("active_assignment_rules.0.require_justification") || + metadata.ResourceData.HasChange("active_assignment_rules.0.require_ticket_info") { + if enablementAdminEligibility, ok := existingRules["Enablement_Admin_Assignment"]; ok && enablementAdminEligibility.Values != nil { + enabledRules := make([]string, 0) + + if len(model.ActiveAssignmentRules) == 1 { + if model.ActiveAssignmentRules[0].RequireMultiFactorAuth { + enabledRules = append(enabledRules, "MultiFactorAuthentication") + } + if model.ActiveAssignmentRules[0].RequireJustification { + enabledRules = append(enabledRules, "Justification") + } + if model.ActiveAssignmentRules[0].RequireTicketInfo { + enabledRules = append(enabledRules, "Ticketing") + } + } + + var id, ruleType string + var target map[string]interface{} + if idRaw, ok := enablementAdminEligibility.Values["id"]; ok { + id = idRaw.(string) + } + if ruleTypeRaw, ok := enablementAdminEligibility.Values["ruleType"]; ok { + ruleType = ruleTypeRaw.(string) + } + if targetRaw, ok := enablementAdminEligibility.Values["target"]; ok { + target = targetRaw.(map[string]interface{}) + } + + updatedRules = append(updatedRules, map[string]interface{}{ + "id": id, + "ruleType": ruleType, + "target": target, + "enabledRules": enabledRules, + }) + } + } + + if metadata.ResourceData.HasChange("active_assignment_rules.0.expiration_required") || + metadata.ResourceData.HasChange("active_assignment_rules.0.expire_after") { + if expirationAdminAssignment, ok := existingRules["Expiration_Admin_Assignment"]; ok && expirationAdminAssignment.Values != nil { + var expirationRequired bool + if expirationRequiredRaw, ok := expirationAdminAssignment.Values["isExpirationRequired"]; ok { + expirationRequired = expirationRequiredRaw.(bool) + } + + var maximumDuration string + if maximumDurationRaw, ok := expirationAdminAssignment.Values["maximumDuration"]; ok { + maximumDuration = maximumDurationRaw.(string) + } + + if len(model.ActiveAssignmentRules) == 1 { + if expirationRequired != model.ActiveAssignmentRules[0].ExpirationRequired { + expirationRequired = model.ActiveAssignmentRules[0].ExpirationRequired + } + if maximumDuration != model.ActiveAssignmentRules[0].ExpireAfter && + model.ActiveAssignmentRules[0].ExpireAfter != "" { + maximumDuration = model.ActiveAssignmentRules[0].ExpireAfter + } + } + + var id, ruleType string + var target map[string]interface{} + if idRaw, ok := expirationAdminAssignment.Values["id"]; ok { + id = idRaw.(string) + } + if ruleTypeRaw, ok := expirationAdminAssignment.Values["ruleType"]; ok { + ruleType = ruleTypeRaw.(string) + } + if targetRaw, ok := expirationAdminAssignment.Values["target"]; ok { + target = targetRaw.(map[string]interface{}) + } + + updatedRules = append(updatedRules, map[string]interface{}{ + "id": id, + "ruleType": ruleType, + "target": target, + "isExpirationRequired": expirationRequired, + "maximumDuration": maximumDuration, + }) + } + } + + if metadata.ResourceData.HasChange("activation_rules.0.maximum_duration") { + if expirationEndUserAssignment, ok := existingRules["Expiration_EndUser_Assignment"]; ok && expirationEndUserAssignment.Values != nil { + var id, ruleType, maximumDuration string + var target map[string]interface{} + if idRaw, ok := expirationEndUserAssignment.Values["id"]; ok { + id = idRaw.(string) + } + if ruleTypeRaw, ok := expirationEndUserAssignment.Values["ruleType"]; ok { + ruleType = ruleTypeRaw.(string) + } + if targetRaw, ok := expirationEndUserAssignment.Values["target"]; ok { + target = targetRaw.(map[string]interface{}) + } + if len(model.ActivationRules) == 1 { + maximumDuration = model.ActivationRules[0].MaximumDuration + } + + updatedRules = append(updatedRules, map[string]interface{}{ + "id": id, + "ruleType": ruleType, + "target": target, + "maximumDuration": maximumDuration, + }) + } + } + + if metadata.ResourceData.HasChange("activation_rules.0.require_approval") || + metadata.ResourceData.HasChange("activation_rules.0.approval_stage") { + if approvalEndUserAssignment, ok := existingRules["Approval_EndUser_Assignment"]; ok && approvalEndUserAssignment.Values != nil { + if len(model.ActivationRules) == 1 { + if model.ActivationRules[0].RequireApproval && len(model.ActivationRules[0].ApprovalStages) != 1 { + return nil, fmt.Errorf("require_approval is true, but no approval_stages are provided") + } + } + + var approvalReqd bool + var approvalStages []map[string]interface{} + + if settingsRaw, ok := approvalEndUserAssignment.Values["setting"]; ok { + settings := settingsRaw.(map[string]interface{}) + + if approvalReqdRaw, ok := settings["isApprovalRequired"]; ok { + approvalReqd = approvalReqdRaw.(bool) + } + + if len(model.ActivationRules) == 1 { + if approvalReqd != model.ActivationRules[0].RequireApproval { + approvalReqd = model.ActivationRules[0].RequireApproval + } + } + + if metadata.ResourceData.HasChange("activation_rules.0.approval_stage") { + if len(model.ActivationRules) == 1 { + approvalStages = make([]map[string]interface{}, len(model.ActivationRules[0].ApprovalStages)) + for i, stage := range model.ActivationRules[0].ApprovalStages { + primaryApprovers := make([]map[string]interface{}, len(stage.PrimaryApprovers)) + for ia, approver := range stage.PrimaryApprovers { + primaryApprovers[ia] = map[string]interface{}{ + "id": approver.ID, + "userType": approver.Type, + } + } + + approvalStages[i] = map[string]interface{}{ + "PrimaryApprovers": primaryApprovers, + } + } + } + } else { + if approvalStagesRaw, ok := settings["approvalStages"]; ok { + approvalStages = approvalStagesRaw.([]map[string]interface{}) + } + } + } + + var id, ruleType string + var target map[string]interface{} + if idRaw, ok := approvalEndUserAssignment.Values["id"]; ok { + id = idRaw.(string) + } + if ruleTypeRaw, ok := approvalEndUserAssignment.Values["ruleType"]; ok { + ruleType = ruleTypeRaw.(string) + } + if targetRaw, ok := approvalEndUserAssignment.Values["target"]; ok { + target = targetRaw.(map[string]interface{}) + } + + updatedRules = append(updatedRules, map[string]interface{}{ + "id": id, + "ruleType": ruleType, + "target": target, + "setting": map[string]interface{}{ + "isApprovalRequired": approvalReqd, + "approvalStages": approvalStages, + }, + }) + } + } + + if metadata.ResourceData.HasChange("activation_rules.0.required_conditional_access_authentication_context") { + if authEndUserAssignment, ok := existingRules["AuthenticationContext_EndUser_Assignment"]; ok && authEndUserAssignment.Values != nil { + var claimValue string + if claimValueRaw, ok := authEndUserAssignment.Values["claimValue"]; ok { + claimValue = claimValueRaw.(string) + } + + var isEnabled bool + if _, ok = metadata.ResourceData.GetOk("activation_rules.0.required_conditional_access_authentication_context"); ok { + isEnabled = true + if len(model.ActivationRules) == 1 { + claimValue = model.ActivationRules[0].RequireConditionalAccessContext + } + } + + var id, ruleType string + var target map[string]interface{} + if idRaw, ok := authEndUserAssignment.Values["id"]; ok { + id = idRaw.(string) + } + if ruleTypeRaw, ok := authEndUserAssignment.Values["ruleType"]; ok { + ruleType = ruleTypeRaw.(string) + } + if targetRaw, ok := authEndUserAssignment.Values["target"]; ok { + target = targetRaw.(map[string]interface{}) + } + + updatedRules = append(updatedRules, map[string]interface{}{ + "id": id, + "ruleType": ruleType, + "target": target, + "isEnabled": isEnabled, + "claimValue": claimValue, + }) + } + } + + if metadata.ResourceData.HasChange("activation_rules.0.require_multifactor_authentication") || + metadata.ResourceData.HasChange("activation_rules.0.require_justification") || + metadata.ResourceData.HasChange("activation_rules.0.require_ticket_info") { + if enablementEndUserAssignment, ok := existingRules["Enablement_EndUser_Assignment"]; ok && enablementEndUserAssignment.Values != nil { + enabledRules := make([]string, 0) + if len(model.ActivationRules) == 1 { + if model.ActivationRules[0].RequireMultiFactorAuth { + enabledRules = append(enabledRules, "MultiFactorAuthentication") + } + if model.ActivationRules[0].RequireJustification { + enabledRules = append(enabledRules, "Justification") + } + if model.ActivationRules[0].RequireTicketInfo { + enabledRules = append(enabledRules, "Ticketing") + } + } + + var id, ruleType string + var target map[string]interface{} + if idRaw, ok := enablementEndUserAssignment.Values["id"]; ok { + id = idRaw.(string) + } + if ruleTypeRaw, ok := enablementEndUserAssignment.Values["ruleType"]; ok { + ruleType = ruleTypeRaw.(string) + } + if targetRaw, ok := enablementEndUserAssignment.Values["target"]; ok { + target = targetRaw.(map[string]interface{}) + } + + updatedRules = append(updatedRules, map[string]interface{}{ + "id": id, + "ruleType": ruleType, + "target": target, + "enabledRules": enabledRules, + }) + } + } + + if metadata.ResourceData.HasChange("notification_rules.0.eligible_assignments.0.admin_notifications") { + if notificationAdminAdminEligibility, ok := existingRules["Notification_Admin_Admin_Eligibility"]; ok && notificationAdminAdminEligibility.Values != nil { + if len(model.NotificationRules) == 1 { + if len(model.NotificationRules[0].EligibleAssignments) == 1 { + if len(model.NotificationRules[0].EligibleAssignments[0].AdminNotifications) == 1 { + updatedRules = append(updatedRules, + expandNotificationSettings( + notificationAdminAdminEligibility, + model.NotificationRules[0].EligibleAssignments[0].AdminNotifications[0], + metadata.ResourceData.HasChange("notification_rules.0.eligible_assignments.0.admin_notifications.0.additional_recipients"), + ), + ) + } + } + } + } + } + + if metadata.ResourceData.HasChange("notification_rules.0.active_assignments.0.admin_notifications") { + if notificationAdminAdminAssignment, ok := existingRules["Notification_Admin_Admin_Assignment"]; ok && notificationAdminAdminAssignment.Values != nil { + if len(model.NotificationRules) == 1 { + if len(model.NotificationRules[0].ActiveAssignments) == 1 { + if len(model.NotificationRules[0].ActiveAssignments[0].AdminNotifications) == 1 { + updatedRules = append(updatedRules, + expandNotificationSettings( + notificationAdminAdminAssignment, + model.NotificationRules[0].ActiveAssignments[0].AdminNotifications[0], + metadata.ResourceData.HasChange("notification_rules.0.active_assignments.0.admin_notifications.0.additional_recipients"), + ), + ) + } + } + } + } + } + + if metadata.ResourceData.HasChange("notification_rules.0.eligible_activations.0.admin_notifications") { + if notificationAdminEndUserAssignment, ok := existingRules["Notification_Admin_EndUser_Assignment"]; ok && notificationAdminEndUserAssignment.Values != nil { + if len(model.NotificationRules) == 1 { + if len(model.NotificationRules[0].EligibleActivations) == 1 { + if len(model.NotificationRules[0].EligibleActivations[0].AdminNotifications) == 1 { + updatedRules = append(updatedRules, + expandNotificationSettings( + notificationAdminEndUserAssignment, + model.NotificationRules[0].EligibleActivations[0].AdminNotifications[0], + metadata.ResourceData.HasChange("notification_rules.0.eligible_activations.0.admin_notifications.0.additional_recipients"), + ), + ) + } + } + } + } + } + + if metadata.ResourceData.HasChange("notification_rules.0.eligible_assignments.0.approver_notifications") { + if notificationApproverAdminEligibility, ok := existingRules["Notification_Approver_Admin_Eligibility"]; ok && notificationApproverAdminEligibility.Values != nil { + if len(model.NotificationRules) == 1 { + if len(model.NotificationRules[0].EligibleAssignments) == 1 { + if len(model.NotificationRules[0].EligibleAssignments[0].ApproverNotifications) == 1 { + updatedRules = append(updatedRules, + expandNotificationSettings( + notificationApproverAdminEligibility, + model.NotificationRules[0].EligibleAssignments[0].ApproverNotifications[0], + metadata.ResourceData.HasChange("notification_rules.0.eligible_assignments.0.approver_notifications.0.additional_recipients"), + ), + ) + } + } + } + } + } + + if metadata.ResourceData.HasChange("notification_rules.0.active_assignments.0.approver_notifications") { + if notificationApproverAdminAssignment, ok := existingRules["Notification_Approver_Admin_Assignment"]; ok && notificationApproverAdminAssignment.Values != nil { + if len(model.NotificationRules) == 1 { + if len(model.NotificationRules[0].ActiveAssignments) == 1 { + if len(model.NotificationRules[0].ActiveAssignments[0].ApproverNotifications) == 1 { + updatedRules = append(updatedRules, + expandNotificationSettings( + notificationApproverAdminAssignment, + model.NotificationRules[0].ActiveAssignments[0].ApproverNotifications[0], + metadata.ResourceData.HasChange("notification_rules.0.active_assignments.0.approver_notifications.0.additional_recipients"), + ), + ) + } + } + } + } + } + + if metadata.ResourceData.HasChange("notification_rules.0.eligible_activations.0.approver_notifications") { + if notificationApproverEndUserAssignment, ok := existingRules["Notification_Approver_EndUser_Assignment"]; ok && notificationApproverEndUserAssignment.Values != nil { + if len(model.NotificationRules) == 1 { + if len(model.NotificationRules[0].EligibleActivations) == 1 { + if len(model.NotificationRules[0].EligibleActivations[0].ApproverNotifications) == 1 { + updatedRules = append(updatedRules, + expandNotificationSettings( + notificationApproverEndUserAssignment, + model.NotificationRules[0].EligibleActivations[0].ApproverNotifications[0], + metadata.ResourceData.HasChange("notification_rules.0.eligible_activations.0.approver_notifications.0.additional_recipients"), + ), + ) + } + } + } + } + } + + if metadata.ResourceData.HasChange("notification_rules.0.eligible_assignments.0.assignee_notifications") { + if notificationRequestorAdminEligibility, ok := existingRules["Notification_Requestor_Admin_Eligibility"]; ok && notificationRequestorAdminEligibility.Values != nil { + if len(model.NotificationRules) == 1 { + if len(model.NotificationRules[0].EligibleAssignments) == 1 { + if len(model.NotificationRules[0].EligibleAssignments[0].AssigneeNotifications) == 1 { + updatedRules = append(updatedRules, + expandNotificationSettings( + notificationRequestorAdminEligibility, + model.NotificationRules[0].EligibleAssignments[0].AssigneeNotifications[0], + metadata.ResourceData.HasChange("notification_rules.0.eligible_assignments.0.assignee_notifications.0.additional_recipients"), + ), + ) + } + } + } + } + } + + if metadata.ResourceData.HasChange("notification_rules.0.active_assignments.0.assignee_notifications") { + if notificationRequestorAdminAssignment, ok := existingRules["Notification_Requestor_Admin_Assignment"]; ok && notificationRequestorAdminAssignment.Values != nil { + if len(model.NotificationRules) == 1 { + if len(model.NotificationRules[0].ActiveAssignments) == 1 { + if len(model.NotificationRules[0].ActiveAssignments[0].AssigneeNotifications) == 1 { + updatedRules = append(updatedRules, + expandNotificationSettings( + notificationRequestorAdminAssignment, + model.NotificationRules[0].ActiveAssignments[0].AssigneeNotifications[0], + metadata.ResourceData.HasChange("notification_rules.0.active_assignments.0.assignee_notifications.0.additional_recipients"), + ), + ) + } + } + } + } + } + + if metadata.ResourceData.HasChange("notification_rules.0.eligible_activations.0.assignee_notifications") { + if notificationRequestorEndUserAssignment, ok := existingRules["Notification_Requestor_EndUser_Assignment"]; ok && notificationRequestorEndUserAssignment.Values != nil { + if len(model.NotificationRules) == 1 { + if len(model.NotificationRules[0].EligibleActivations) == 1 { + if len(model.NotificationRules[0].EligibleActivations[0].AssigneeNotifications) == 1 { + updatedRules = append(updatedRules, + expandNotificationSettings( + notificationRequestorEndUserAssignment, + model.NotificationRules[0].EligibleActivations[0].AssigneeNotifications[0], + metadata.ResourceData.HasChange("notification_rules.0.eligible_activations.0.assignee_notifications.0.additional_recipients"), + ), + ) + } + } + } + } + } + + return &rolemanagementpolicies.RoleManagementPolicy{ + Id: rolePolicy.Id, + Name: rolePolicy.Name, + Type: rolePolicy.Type, + Properties: &rolemanagementpolicies.RoleManagementPolicyProperties{ + Rules: pointer.To(updatedRules), + }, + }, nil +} + +func expandNotificationSettings(rule rolemanagementpolicies.RawRoleManagementPolicyRuleImpl, data RoleManagementPolicyNotificationSettings, recipientChange bool) rolemanagementpolicies.RoleManagementPolicyRule { + var level string + if levelRaw, ok := rule.Values["notificationLevel"]; ok { + level = levelRaw.(string) + } + + var defaultRecipients bool + if defaultRecipientsRaw, ok := rule.Values["isDefaultRecipientsEnabled"]; ok { + defaultRecipients = defaultRecipientsRaw.(bool) + } + + var additionalRecipients []string + if v, ok := rule.Values["notificationRecipients"]; ok { + additionalRecipientsRaw := v.([]interface{}) + additionalRecipients = make([]string, len(additionalRecipientsRaw)) + for i, r := range additionalRecipientsRaw { + additionalRecipients[i] = r.(string) + } + } + + if level != data.NotificationLevel { + level = data.NotificationLevel + } + if defaultRecipients != data.DefaultRecipients { + defaultRecipients = data.DefaultRecipients + } + if recipientChange { + additionalRecipients = data.AdditionalRecipients + } + + var id, ruleType, recipientType, notificationType string + var target map[string]interface{} + if idRaw, ok := rule.Values["id"]; ok { + id = idRaw.(string) + } + if ruleTypeRaw, ok := rule.Values["ruleType"]; ok { + ruleType = ruleTypeRaw.(string) + } + if targetRaw, ok := rule.Values["target"]; ok { + target = targetRaw.(map[string]interface{}) + } + if recipientTypeRaw, ok := rule.Values["recipientType"]; ok { + recipientType = recipientTypeRaw.(string) + } + if notificationTypeRaw, ok := rule.Values["notificationType"]; ok { + notificationType = notificationTypeRaw.(string) + } + + return map[string]interface{}{ + "id": id, + "ruleType": ruleType, + "target": target, + "recipientType": recipientType, + "notificationType": notificationType, + "notificationLevel": level, + "isDefaultRecipientsEnabled": defaultRecipients, + "notificationRecipients": additionalRecipients, + } +} + +func flattenNotificationSettings(rule map[string]interface{}) *RoleManagementPolicyNotificationSettings { + if rule == nil { + return nil + } + + var notificationLevel string + var defaultRecipients bool + var additionalRecipients []string + + if v, ok := rule["notificationLevel"].(string); ok { + notificationLevel = v + } + if v, ok := rule["isDefaultRecipientsEnabled"].(bool); ok { + defaultRecipients = v + } + if v, ok := rule["notificationRecipients"].([]interface{}); ok { + additionalRecipients = make([]string, len(v)) + for i, r := range v { + additionalRecipients[i] = r.(string) + } + } + return &RoleManagementPolicyNotificationSettings{ + NotificationLevel: notificationLevel, + DefaultRecipients: defaultRecipients, + AdditionalRecipients: additionalRecipients, + } +} diff --git a/internal/services/authorization/role_management_policy_data_source.go b/internal/services/authorization/role_management_policy_data_source.go new file mode 100644 index 000000000000..35f485cf69b9 --- /dev/null +++ b/internal/services/authorization/role_management_policy_data_source.go @@ -0,0 +1,573 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package authorization + +import ( + "context" + "fmt" + "regexp" + "time" + + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" + "github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies" + "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" +) + +type RoleManagementPolicyDataSource struct{} + +var _ sdk.DataSource = RoleManagementPolicyDataSource{} + +type RoleManagementPolicyDataSourceModel struct { + Scope string `tfschema:"scope"` + RoleDefinitionId string `tfschema:"role_definition_id"` + Name string `tfschema:"name"` + Description string `tfschema:"description"` + ActiveAssignmentRules []RoleManagementPolicyDataSourceActiveAssignmentRules `tfschema:"active_assignment_rules"` + EligibleAssignmentRules []RoleManagementPolicyDataSourceEligibleAssignmentRules `tfschema:"eligible_assignment_rules"` + ActivationRules []RoleManagementPolicyDataSourceActivationRules `tfschema:"activation_rules"` + NotificationRules []RoleManagementPolicyDataSourceNotificationEvents `tfschema:"notification_rules"` +} + +type RoleManagementPolicyDataSourceActiveAssignmentRules struct { + ExpirationRequired bool `tfschema:"expiration_required"` + ExpireAfter string `tfschema:"expire_after"` + RequireMultiFactorAuth bool `tfschema:"require_multifactor_authentication"` + RequireJustification bool `tfschema:"require_justification"` + RequireTicketInfo bool `tfschema:"require_ticket_info"` +} + +type RoleManagementPolicyDataSourceEligibleAssignmentRules struct { + ExpirationRequired bool `tfschema:"expiration_required"` + ExpireAfter string `tfschema:"expire_after"` +} + +type RoleManagementPolicyDataSourceActivationRules struct { + MaximumDuration string `tfschema:"maximum_duration"` + RequireApproval bool `tfschema:"require_approval"` + ApprovalStages []RoleManagementPolicyDataSourceApprovalStage `tfschema:"approval_stage"` + RequireConditionalAccessContext string `tfschema:"required_conditional_access_authentication_context"` + RequireMultiFactorAuth bool `tfschema:"require_multifactor_authentication"` + RequireJustification bool `tfschema:"require_justification"` + RequireTicketInfo bool `tfschema:"require_ticket_info"` +} + +type RoleManagementPolicyDataSourceApprovalStage struct { + PrimaryApprovers []RoleManagementPolicyDataSourceApprover `tfschema:"primary_approver"` +} + +type RoleManagementPolicyDataSourceApprover struct { + ID string `tfschema:"object_id"` + Type string `tfschema:"type"` +} + +type RoleManagementPolicyDataSourceNotificationEvents struct { + ActiveAssignments []RoleManagementPolicyDataSourceNotificationRule `tfschema:"active_assignments"` + EligibleActivations []RoleManagementPolicyDataSourceNotificationRule `tfschema:"eligible_activations"` + EligibleAssignments []RoleManagementPolicyDataSourceNotificationRule `tfschema:"eligible_assignments"` +} + +type RoleManagementPolicyDataSourceNotificationRule struct { + AdminNotifications []RoleManagementPolicyDataSourceNotificationSettings `tfschema:"admin_notifications"` + ApproverNotifications []RoleManagementPolicyDataSourceNotificationSettings `tfschema:"approver_notifications"` + AssigneeNotifications []RoleManagementPolicyDataSourceNotificationSettings `tfschema:"assignee_notifications"` +} + +type RoleManagementPolicyDataSourceNotificationSettings struct { + NotificationLevel string `tfschema:"notification_level"` + DefaultRecipients bool `tfschema:"default_recipients"` + AdditionalRecipients []string `tfschema:"additional_recipients"` +} + +func (r RoleManagementPolicyDataSource) IDValidationFunc() pluginsdk.SchemaValidateFunc { + return rolemanagementpolicies.ValidateScopedRoleManagementPolicyID +} + +func (r RoleManagementPolicyDataSource) ResourceType() string { + return "azurerm_role_management_policy" +} + +func (r RoleManagementPolicyDataSource) ModelObject() interface{} { + return &RoleManagementPolicyDataSourceModel{} +} + +func (r RoleManagementPolicyDataSource) Arguments() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "role_definition_id": { + Description: "ID of the Azure Role to which this policy is assigned", + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringMatch(regexp.MustCompile("/providers/Microsoft.Authorization/roleDefinitions/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"), "should be in the format /providers/Microsoft.Authorization/roleDefinitions/00000000-0000-0000-0000-000000000000"), + }, + + "scope": { + Description: "The scope of the role to which this policy will apply", + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.Any( + commonids.ValidateManagementGroupID, + commonids.ValidateResourceGroupID, + commonids.ValidateSubscriptionID, + ), + }, + } +} + +func (r RoleManagementPolicyDataSource) Attributes() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "name": { + Description: "The name of the policy", + Type: pluginsdk.TypeString, + Computed: true, + }, + + "description": { + Description: "The Description of the policy", + Type: pluginsdk.TypeString, + Computed: true, + }, + + "eligible_assignment_rules": { + Description: "The rules for eligible assignment of the policy", + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "expiration_required": { + Description: "Must the assignment have an expiry date", + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "expire_after": { + Description: "The duration after which assignments expire", + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + }, + }, + + "active_assignment_rules": { + Description: "The rules for active assignment of the policy", + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "expiration_required": { + Description: "Must the assignment have an expiry date", + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "expire_after": { + Description: "The duration after which assignments expire", + Type: pluginsdk.TypeString, + Computed: true, + }, + + "require_multifactor_authentication": { + Description: "Whether multi-factor authentication is required to make an assignment", + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "require_justification": { + Description: "Whether a justification is required to make an assignment", + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "require_ticket_info": { + Description: "Whether ticket information is required to make an assignment", + Type: pluginsdk.TypeBool, + Computed: true, + }, + }, + }, + }, + + "activation_rules": { + Description: "The activation rules of the policy", + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "maximum_duration": { + Description: "The time after which the an activation can be valid for", + Type: pluginsdk.TypeString, + Computed: true, + }, + + "require_approval": { + Description: "Whether an approval is required for activation", + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "approval_stage": { + Description: "The approval stages for the activation", + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "primary_approver": { + Description: "The IDs of the users or groups who can approve the activation", + Type: pluginsdk.TypeSet, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "object_id": { + Description: "The ID of the object to act as an approver", + Type: pluginsdk.TypeString, + Computed: true, + }, + + "type": { + Description: "The type of object acting as an approver", + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + }, + }, + }, + }, + }, + + "required_conditional_access_authentication_context": { + Description: "Whether a conditional access context is required during activation", + Type: pluginsdk.TypeString, + Computed: true, + }, + + "require_multifactor_authentication": { + Description: "Whether multi-factor authentication is required during activation", + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "require_justification": { + Description: "Whether a justification is required during activation", + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "require_ticket_info": { + Description: "Whether ticket information is required during activation", + Type: pluginsdk.TypeBool, + Computed: true, + }, + }, + }, + }, + + "notification_rules": { + Description: "The notification rules of the policy", + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "active_assignments": { + Description: "Notifications about active assignments", + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: notificationRuleDataSourceSchema(), + }, + }, + + "eligible_activations": { + Description: "Notifications about activations of eligible assignments", + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: notificationRuleDataSourceSchema(), + }, + }, + + "eligible_assignments": { + Description: "Notifications about eligible assignments", + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: notificationRuleDataSourceSchema(), + }, + }, + }, + }, + }, + } +} + +func (r RoleManagementPolicyDataSource) Read() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 5 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.Authorization.RoleManagementPoliciesClient + + var config RoleManagementPolicyModel + if err := metadata.Decode(&config); err != nil { + return fmt.Errorf("decoding %+v", err) + } + + id, err := FindRoleManagementPolicyId(ctx, metadata.Client.Authorization.RoleManagementPoliciesClient, config.Scope, config.RoleDefinitionId) + if err != nil { + return err + } + + resp, err := client.Get(ctx, *id) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + return fmt.Errorf("could not find Role Management Policy for Role Definition %q and Scope %q", config.RoleDefinitionId, config.Scope) + } + + return fmt.Errorf("retrieving Role Management Policy for Role Definition %q and Scope %q: %+v", config.RoleDefinitionId, config.Scope, err) + } + + state := RoleManagementPolicyDataSourceModel{ + Scope: config.Scope, + RoleDefinitionId: config.RoleDefinitionId, + } + + if model := resp.Model; model != nil { + state.Name = pointer.From(model.Name) + + if prop := model.Properties; prop != nil { + state.Description = pointer.From(prop.Description) + + // Create the rules structure so we can populate them + if len(state.EligibleAssignmentRules) == 0 { + state.EligibleAssignmentRules = make([]RoleManagementPolicyDataSourceEligibleAssignmentRules, 1) + } + if len(state.ActiveAssignmentRules) == 0 { + state.ActiveAssignmentRules = make([]RoleManagementPolicyDataSourceActiveAssignmentRules, 1) + } + if len(state.ActivationRules) == 0 { + state.ActivationRules = make([]RoleManagementPolicyDataSourceActivationRules, 1) + } + if len(state.NotificationRules) == 0 { + state.NotificationRules = make([]RoleManagementPolicyDataSourceNotificationEvents, 1) + } + if len(state.NotificationRules[0].EligibleActivations) == 0 { + state.NotificationRules[0].EligibleActivations = make([]RoleManagementPolicyDataSourceNotificationRule, 1) + } + if len(state.NotificationRules[0].ActiveAssignments) == 0 { + state.NotificationRules[0].ActiveAssignments = make([]RoleManagementPolicyDataSourceNotificationRule, 1) + } + if len(state.NotificationRules[0].EligibleAssignments) == 0 { + state.NotificationRules[0].EligibleAssignments = make([]RoleManagementPolicyDataSourceNotificationRule, 1) + } + + for _, r := range *prop.Rules { + rule := r.(rolemanagementpolicies.RawRoleManagementPolicyRuleImpl) + switch rule.Values["id"].(string) { + case "AuthenticationContext_EndUser_Assignment": + if claimValue, ok := rule.Values["claimValue"].(string); ok && claimValue != "" { + state.ActivationRules[0].RequireConditionalAccessContext = claimValue + } + + case "Approval_EndUser_Assignment": + if settings, ok := rule.Values["setting"].(map[string]interface{}); ok { + state.ActivationRules[0].RequireApproval = settings["isApprovalRequired"].(bool) + + if approvalStages, ok := settings["approvalStages"].([]interface{}); ok { + state.ActivationRules[0].ApprovalStages = make([]RoleManagementPolicyDataSourceApprovalStage, 1) + approvalStage := approvalStages[0].(map[string]interface{}) + + if primaryApprovers, ok := approvalStage["primaryApprovers"].([]interface{}); ok && len(primaryApprovers) > 0 { + state.ActivationRules[0].ApprovalStages[0].PrimaryApprovers = make([]RoleManagementPolicyDataSourceApprover, len(primaryApprovers)) + + for ia, pa := range primaryApprovers { + approver := pa.(map[string]interface{}) + state.ActivationRules[0].ApprovalStages[0].PrimaryApprovers[ia] = RoleManagementPolicyDataSourceApprover{ + ID: approver["id"].(string), + Type: approver["userType"].(string), + } + } + } + } + } + + case "Enablement_Admin_Assignment": + state.ActiveAssignmentRules[0].RequireMultiFactorAuth = false + state.ActiveAssignmentRules[0].RequireJustification = false + + if enabledRules, ok := rule.Values["enabledRules"].([]interface{}); ok { + for _, enabledRule := range enabledRules { + switch enabledRule.(string) { + case "MultiFactorAuthentication": + state.ActiveAssignmentRules[0].RequireMultiFactorAuth = true + case "Justification": + state.ActiveAssignmentRules[0].RequireJustification = true + } + } + } + + case "Enablement_EndUser_Assignment": + state.ActivationRules[0].RequireMultiFactorAuth = false + state.ActivationRules[0].RequireJustification = false + state.ActivationRules[0].RequireTicketInfo = false + + if enabledRules, ok := rule.Values["enabledRules"].([]interface{}); ok { + for _, enabledRule := range enabledRules { + switch enabledRule.(string) { + case "MultiFactorAuthentication": + state.ActivationRules[0].RequireMultiFactorAuth = true + case "Justification": + state.ActivationRules[0].RequireJustification = true + case "Ticketing": + state.ActivationRules[0].RequireTicketInfo = true + } + } + } + + case "Expiration_Admin_Eligibility": + state.EligibleAssignmentRules[0].ExpirationRequired = rule.Values["isExpirationRequired"].(bool) + state.EligibleAssignmentRules[0].ExpireAfter = rule.Values["maximumDuration"].(string) + + case "Expiration_Admin_Assignment": + state.ActiveAssignmentRules[0].ExpirationRequired = rule.Values["isExpirationRequired"].(bool) + state.ActiveAssignmentRules[0].ExpireAfter = rule.Values["maximumDuration"].(string) + + case "Expiration_EndUser_Assignment": + state.ActivationRules[0].MaximumDuration = rule.Values["maximumDuration"].(string) + + case "Notification_Admin_Admin_Assignment": + state.NotificationRules[0].ActiveAssignments[0].AdminNotifications = []RoleManagementPolicyDataSourceNotificationSettings{ + *flattenNotificationDataSourceSettings(pointer.To(rule.Values)), + } + + case "Notification_Admin_Admin_Eligibility": + state.NotificationRules[0].EligibleAssignments[0].AdminNotifications = []RoleManagementPolicyDataSourceNotificationSettings{ + *flattenNotificationDataSourceSettings(pointer.To(rule.Values)), + } + + case "Notification_Admin_EndUser_Assignment": + state.NotificationRules[0].EligibleActivations[0].AdminNotifications = []RoleManagementPolicyDataSourceNotificationSettings{ + *flattenNotificationDataSourceSettings(pointer.To(rule.Values)), + } + + case "Notification_Approver_Admin_Assignment": + state.NotificationRules[0].ActiveAssignments[0].ApproverNotifications = []RoleManagementPolicyDataSourceNotificationSettings{ + *flattenNotificationDataSourceSettings(pointer.To(rule.Values)), + } + + case "Notification_Approver_Admin_Eligibility": + state.NotificationRules[0].EligibleAssignments[0].ApproverNotifications = []RoleManagementPolicyDataSourceNotificationSettings{ + *flattenNotificationDataSourceSettings(pointer.To(rule.Values)), + } + + case "Notification_Approver_EndUser_Assignment": + state.NotificationRules[0].EligibleActivations[0].ApproverNotifications = []RoleManagementPolicyDataSourceNotificationSettings{ + *flattenNotificationDataSourceSettings(pointer.To(rule.Values)), + } + + case "Notification_Requestor_Admin_Assignment": + state.NotificationRules[0].ActiveAssignments[0].AssigneeNotifications = []RoleManagementPolicyDataSourceNotificationSettings{ + *flattenNotificationDataSourceSettings(pointer.To(rule.Values)), + } + + case "Notification_Requestor_Admin_Eligibility": + state.NotificationRules[0].EligibleAssignments[0].AssigneeNotifications = []RoleManagementPolicyDataSourceNotificationSettings{ + *flattenNotificationDataSourceSettings(pointer.To(rule.Values)), + } + + case "Notification_Requestor_EndUser_Assignment": + state.NotificationRules[0].EligibleActivations[0].AssigneeNotifications = []RoleManagementPolicyDataSourceNotificationSettings{ + *flattenNotificationDataSourceSettings(pointer.To(rule.Values)), + } + } + } + } + } + + metadata.SetID(id) + return metadata.Encode(&state) + }, + } +} + +func flattenNotificationDataSourceSettings(rule *map[string]interface{}) *RoleManagementPolicyDataSourceNotificationSettings { + var notificationLevel string + var defaultRecipients bool + var additionalRecipients []string + + if v, ok := (*rule)["notificationLevel"].(string); ok { + notificationLevel = v + } + if v, ok := (*rule)["isDefaultRecipientsEnabled"].(bool); ok { + defaultRecipients = v + } + if v, ok := (*rule)["notificationRecipients"].([]interface{}); ok { + additionalRecipients = make([]string, len(v)) + for i, r := range v { + additionalRecipients[i] = r.(string) + } + } + return &RoleManagementPolicyDataSourceNotificationSettings{ + NotificationLevel: notificationLevel, + DefaultRecipients: defaultRecipients, + AdditionalRecipients: additionalRecipients, + } +} + +func notificationRuleDataSourceSchema() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "admin_notifications": { + Description: "Admin notification settings", + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: notificationSettingsDataSourceSchema(), + }, + }, + + "approver_notifications": { + Description: "Approver notification settings", + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: notificationSettingsDataSourceSchema(), + }, + }, + + "assignee_notifications": { + Description: "Assignee notification settings", + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: notificationSettingsDataSourceSchema(), + }, + }, + } +} + +func notificationSettingsDataSourceSchema() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "notification_level": { + Description: "What level of notifications are sent", + Type: pluginsdk.TypeString, + Computed: true, + }, + + "default_recipients": { + Description: "Whether the default recipients are notified", + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "additional_recipients": { + Description: "The additional recipients to notify", + Type: pluginsdk.TypeSet, + Computed: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + }, + }, + } +} diff --git a/internal/services/authorization/role_management_policy_data_source_test.go b/internal/services/authorization/role_management_policy_data_source_test.go new file mode 100644 index 000000000000..804c2b42e919 --- /dev/null +++ b/internal/services/authorization/role_management_policy_data_source_test.go @@ -0,0 +1,118 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package authorization_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" +) + +type RoleManagementPolicyDataSource struct{} + +func TestAccRoleManagementPolicyDataSource_managementGroup(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azurerm_role_management_policy", "test") + r := RoleManagementPolicyDataSource{} + + data.DataSourceTest(t, []acceptance.TestStep{ + { + Config: r.managementGroup(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).Key("name").Exists(), + ), + }, + }) +} + +func TestAccRoleManagementPolicyDataSource_resourceGroup(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azurerm_role_management_policy", "test") + r := RoleManagementPolicyDataSource{} + + data.DataSourceTest(t, []acceptance.TestStep{ + { + Config: r.resourceGroup(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).Key("name").Exists(), + ), + }, + }) +} + +func TestAccRoleManagementPolicyDataSource_subscription(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azurerm_role_management_policy", "test") + r := RoleManagementPolicyDataSource{} + + data.DataSourceTest(t, []acceptance.TestStep{ + { + Config: r.subscription(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).Key("name").Exists(), + ), + }, + }) +} + +func (RoleManagementPolicyDataSource) managementGroup(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" {} + +data "azurerm_client_config" "current" { +} + +resource "azurerm_management_group" "test" { + name = "acctest%[1]s" +} + +data "azurerm_role_definition" "contributor" { + name = "Contributor" + scope = azurerm_management_group.test.id +} + +data "azurerm_role_management_policy" "test" { + role_definition_id = data.azurerm_role_definition.contributor.id + scope = azurerm_management_group.test.id +} +`, data.RandomString) +} + +func (RoleManagementPolicyDataSource) resourceGroup(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" {} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%[1]s" + location = "%[2]s" +} + +data "azurerm_role_definition" "contributor" { + name = "Contributor" + scope = azurerm_resource_group.test.id +} + +data "azurerm_role_management_policy" "test" { + role_definition_id = data.azurerm_role_definition.contributor.id + scope = azurerm_resource_group.test.id +} +`, data.RandomString, data.Locations.Primary) +} + +func (RoleManagementPolicyDataSource) subscription(data acceptance.TestData) string { + return ` +provider "azurerm" {} + +data "azurerm_subscription" "test" {} + +data "azurerm_role_definition" "contributor" { + name = "Contributor" + scope = data.azurerm_subscription.test.id +} + +data "azurerm_role_management_policy" "test" { + role_definition_id = data.azurerm_role_definition.contributor.id + scope = data.azurerm_subscription.test.id +} +` +} diff --git a/internal/services/authorization/role_management_policy_resource.go b/internal/services/authorization/role_management_policy_resource.go new file mode 100644 index 000000000000..cac16bfc0e89 --- /dev/null +++ b/internal/services/authorization/role_management_policy_resource.go @@ -0,0 +1,698 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package authorization + +import ( + "context" + "fmt" + "time" + + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" + "github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies" + "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/authorization/parse" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" +) + +type RoleManagementPolicyResource struct{} + +var _ sdk.Resource = RoleManagementPolicyResource{} + +type RoleManagementPolicyModel struct { + Scope string `tfschema:"scope"` + RoleDefinitionId string `tfschema:"role_definition_id"` + Name string `tfschema:"name"` + Description string `tfschema:"description"` + ActiveAssignmentRules []RoleManagementPolicyActiveAssignmentRules `tfschema:"active_assignment_rules"` + EligibleAssignmentRules []RoleManagementPolicyEligibleAssignmentRules `tfschema:"eligible_assignment_rules"` + ActivationRules []RoleManagementPolicyActivationRules `tfschema:"activation_rules"` + NotificationRules []RoleManagementPolicyNotificationEvents `tfschema:"notification_rules"` +} + +type RoleManagementPolicyActiveAssignmentRules struct { + ExpirationRequired bool `tfschema:"expiration_required"` + ExpireAfter string `tfschema:"expire_after"` + RequireMultiFactorAuth bool `tfschema:"require_multifactor_authentication"` + RequireJustification bool `tfschema:"require_justification"` + RequireTicketInfo bool `tfschema:"require_ticket_info"` +} + +type RoleManagementPolicyEligibleAssignmentRules struct { + ExpirationRequired bool `tfschema:"expiration_required"` + ExpireAfter string `tfschema:"expire_after"` +} + +type RoleManagementPolicyActivationRules struct { + MaximumDuration string `tfschema:"maximum_duration"` + RequireApproval bool `tfschema:"require_approval"` + ApprovalStages []RoleManagementPolicyApprovalStage `tfschema:"approval_stage"` + RequireConditionalAccessContext string `tfschema:"required_conditional_access_authentication_context"` + RequireMultiFactorAuth bool `tfschema:"require_multifactor_authentication"` + RequireJustification bool `tfschema:"require_justification"` + RequireTicketInfo bool `tfschema:"require_ticket_info"` +} + +type RoleManagementPolicyApprovalStage struct { + PrimaryApprovers []RoleManagementPolicyApprover `tfschema:"primary_approver"` +} + +type RoleManagementPolicyApprover struct { + ID string `tfschema:"object_id"` + Type string `tfschema:"type"` +} + +type RoleManagementPolicyNotificationEvents struct { + ActiveAssignments []RoleManagementPolicyNotificationRule `tfschema:"active_assignments"` + EligibleActivations []RoleManagementPolicyNotificationRule `tfschema:"eligible_activations"` + EligibleAssignments []RoleManagementPolicyNotificationRule `tfschema:"eligible_assignments"` +} + +type RoleManagementPolicyNotificationRule struct { + AdminNotifications []RoleManagementPolicyNotificationSettings `tfschema:"admin_notifications"` + ApproverNotifications []RoleManagementPolicyNotificationSettings `tfschema:"approver_notifications"` + AssigneeNotifications []RoleManagementPolicyNotificationSettings `tfschema:"assignee_notifications"` +} + +type RoleManagementPolicyNotificationSettings struct { + NotificationLevel string `tfschema:"notification_level"` + DefaultRecipients bool `tfschema:"default_recipients"` + AdditionalRecipients []string `tfschema:"additional_recipients"` +} + +func (r RoleManagementPolicyResource) IDValidationFunc() pluginsdk.SchemaValidateFunc { + return parse.ValidateRoleManagementPolicyId +} + +func (r RoleManagementPolicyResource) ResourceType() string { + return "azurerm_role_management_policy" +} + +func (r RoleManagementPolicyResource) ModelObject() interface{} { + return &RoleManagementPolicyModel{} +} + +func (r RoleManagementPolicyResource) Arguments() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "role_definition_id": { + Description: "ID of the Azure Role to which this policy is assigned", + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, // TODO: validate this once we have consolidated the existing role_definition_id ID types across this package, and can also support those with no scope at all + }, + + "scope": { + Description: "The scope of the role to which this policy will apply", + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.Any( + commonids.ValidateManagementGroupID, + commonids.ValidateResourceGroupID, + commonids.ValidateSubscriptionID, + ), + }, + + "eligible_assignment_rules": { + Description: "The rules for eligible assignment of the policy", + Type: pluginsdk.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "expiration_required": { + Description: "Must the assignment have an expiry date", + Type: pluginsdk.TypeBool, + Optional: true, + Computed: true, + }, + + "expire_after": { + Description: "The duration after which assignments expire", + Type: pluginsdk.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice([]string{"P15D", "P30D", "P90D", "P180D", "P365D"}, false), + }, + }, + }, + }, + + "active_assignment_rules": { + Description: "The rules for active assignment of the policy", + Type: pluginsdk.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "expiration_required": { + Description: "Must the assignment have an expiry date", + Type: pluginsdk.TypeBool, + Optional: true, + Computed: true, + }, + + "expire_after": { + Description: "The duration after which assignments expire", + Type: pluginsdk.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice([]string{"P15D", "P30D", "P90D", "P180D", "P365D"}, false), + }, + + "require_multifactor_authentication": { + Description: "Whether multi-factor authentication is required to make an assignment", + Type: pluginsdk.TypeBool, + Optional: true, + Computed: true, + }, + + "require_justification": { + Description: "Whether a justification is required to make an assignment", + Type: pluginsdk.TypeBool, + Optional: true, + Computed: true, + }, + + "require_ticket_info": { + Description: "Whether ticket information is required to make an assignment", + Type: pluginsdk.TypeBool, + Optional: true, + Computed: true, + }, + }, + }, + }, + + "activation_rules": { + Description: "The activation rules of the policy", + Type: pluginsdk.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "maximum_duration": { + Description: "The time after which the an activation can be valid for", + Type: pluginsdk.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice([]string{ + "PT30M", "PT1H", "PT1H30M", "PT2H", "PT2H30M", "PT3H", "PT3H30M", "PT4H", "PT4H30M", "PT5H", "PT5H30M", "PT6H", + "PT6H30M", "PT7H", "PT7H30M", "PT8H", "PT8H30M", "PT9H", "PT9H30M", "PT10H", "PT10H30M", "PT11H", "PT11H30M", "PT12H", + "PT12H30M", "PT13H", "PT13H30M", "PT14H", "PT14H30M", "PT15H", "PT15H30M", "PT16H", "PT16H30M", "PT17H", "PT17H30M", "PT18H", + "PT18H30M", "PT19H", "PT19H30M", "PT20H", "PT20H30M", "PT21H", "PT21H30M", "PT22H", "PT22H30M", "PT23H", "PT23H30M", "P1D", + }, false), + }, + + "require_approval": { + Description: "Whether an approval is required for activation", + Type: pluginsdk.TypeBool, + Optional: true, + Computed: true, + }, + + "approval_stage": { + Description: "The approval stages for the activation", + Type: pluginsdk.TypeList, + Optional: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "primary_approver": { + Description: "The IDs of the users or groups who can approve the activation", + Type: pluginsdk.TypeSet, + Required: true, + MinItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "object_id": { + Description: "The ID of the object to act as an approver", + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.IsUUID, + }, + + "type": { + Description: "The type of object acting as an approver", + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"User", "Group"}, false), + }, + }, + }, + }, + }, + }, + }, + + "required_conditional_access_authentication_context": { + Description: "Whether a conditional access context is required during activation", + Type: pluginsdk.TypeString, + Optional: true, + Computed: true, + ConflictsWith: []string{"activation_rules.0.require_multifactor_authentication"}, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "require_multifactor_authentication": { + Description: "Whether multi-factor authentication is required during activation", + Type: pluginsdk.TypeBool, + Optional: true, + Computed: true, + ConflictsWith: []string{"activation_rules.0.required_conditional_access_authentication_context"}, + }, + + "require_justification": { + Description: "Whether a justification is required during activation", + Type: pluginsdk.TypeBool, + Optional: true, + Computed: true, + }, + + "require_ticket_info": { + Description: "Whether ticket information is required during activation", + Type: pluginsdk.TypeBool, + Optional: true, + Computed: true, + }, + }, + }, + }, + + "notification_rules": { + Description: "The notification rules of the policy", + Type: pluginsdk.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "active_assignments": { + Description: "Notifications about active assignments", + Type: pluginsdk.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: notificationRuleSchema(), + }, + }, + + "eligible_activations": { + Description: "Notifications about activations of eligible assignments", + Type: pluginsdk.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: notificationRuleSchema(), + }, + }, + + "eligible_assignments": { + Description: "Notifications about eligible assignments", + Type: pluginsdk.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: notificationRuleSchema(), + }, + }, + }, + }, + }, + } +} + +func (r RoleManagementPolicyResource) Attributes() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "name": { + Description: "The name of the policy", + Type: pluginsdk.TypeString, + Computed: true, + }, + + "description": { + Description: "The Description of the policy", + Type: pluginsdk.TypeString, + Computed: true, + }, + } +} + +func (r RoleManagementPolicyResource) Create() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.Authorization.RoleManagementPoliciesClient + + var config RoleManagementPolicyModel + if err := metadata.Decode(&config); err != nil { + return fmt.Errorf("decoding %+v", err) + } + + // Resources already have a default policy, so retrieve its ID in order that we can update it + policyId, err := FindRoleManagementPolicyId(ctx, metadata.Client.Authorization.RoleManagementPoliciesClient, config.Scope, config.RoleDefinitionId) + if err != nil { + return err + } + + existing, err := client.Get(ctx, *policyId) + if err != nil { + return fmt.Errorf("retrieving existing %s: %+v", policyId, err) + } + + if existing.Model == nil { + return fmt.Errorf("retrieving existing %s: model was nil", policyId) + } + + model, err := buildRoleManagementPolicyForUpdate(pointer.To(metadata), existing.Model) + if err != nil { + return err + } + + if _, err = client.Update(ctx, *policyId, *model); err != nil { + return fmt.Errorf("updating %s: %+v", policyId, err) + } + + // We are using a custom type parse.RoleManagementPolicyId as the ID type for this resource, because the actual + // resource ID type (ScopedRoleManagementPolicyId) changes each time the policy is updated, so this allows us + // to search for the latest policy at Read time. + id := parse.NewRoleManagementPolicyId(config.RoleDefinitionId, config.Scope) + + metadata.SetID(id) + return nil + }, + } +} + +func (r RoleManagementPolicyResource) Read() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 5 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.Authorization.RoleManagementPoliciesClient + + id, err := parse.RoleManagementPolicyID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + policyId, err := FindRoleManagementPolicyId(ctx, metadata.Client.Authorization.RoleManagementPoliciesClient, id.Scope, id.RoleDefinitionId) + if err != nil { + return err + } + + resp, err := client.Get(ctx, *policyId) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + return metadata.MarkAsGone(id) + } + + return fmt.Errorf("retrieving %s: %+v", id, err) + } + + state := RoleManagementPolicyModel{ + Scope: id.Scope, + RoleDefinitionId: id.RoleDefinitionId, + Name: policyId.RoleManagementPolicyName, + } + + if model := resp.Model; model != nil { + if prop := model.Properties; prop != nil { + state.Description = pointer.From(prop.Description) + + // Create the rules structure so we can populate them + if len(state.EligibleAssignmentRules) == 0 { + state.EligibleAssignmentRules = make([]RoleManagementPolicyEligibleAssignmentRules, 1) + } + if len(state.ActiveAssignmentRules) == 0 { + state.ActiveAssignmentRules = make([]RoleManagementPolicyActiveAssignmentRules, 1) + } + if len(state.ActivationRules) == 0 { + state.ActivationRules = make([]RoleManagementPolicyActivationRules, 1) + } + if len(state.NotificationRules) == 0 { + state.NotificationRules = make([]RoleManagementPolicyNotificationEvents, 1) + } + if len(state.NotificationRules[0].EligibleActivations) == 0 { + state.NotificationRules[0].EligibleActivations = make([]RoleManagementPolicyNotificationRule, 1) + } + if len(state.NotificationRules[0].ActiveAssignments) == 0 { + state.NotificationRules[0].ActiveAssignments = make([]RoleManagementPolicyNotificationRule, 1) + } + if len(state.NotificationRules[0].EligibleAssignments) == 0 { + state.NotificationRules[0].EligibleAssignments = make([]RoleManagementPolicyNotificationRule, 1) + } + + for _, r := range *prop.Rules { + rule := r.(rolemanagementpolicies.RawRoleManagementPolicyRuleImpl) + switch rule.Values["id"].(string) { + case "AuthenticationContext_EndUser_Assignment": + if claimValue, ok := rule.Values["claimValue"].(string); ok && claimValue != "" { + state.ActivationRules[0].RequireConditionalAccessContext = claimValue + } + + case "Approval_EndUser_Assignment": + if settings, ok := rule.Values["setting"].(map[string]interface{}); ok { + state.ActivationRules[0].RequireApproval = settings["isApprovalRequired"].(bool) + + if approvalStages, ok := settings["approvalStages"].([]interface{}); ok { + state.ActivationRules[0].ApprovalStages = make([]RoleManagementPolicyApprovalStage, 1) + approvalStage := approvalStages[0].(map[string]interface{}) + + if primaryApprovers, ok := approvalStage["primaryApprovers"].([]interface{}); ok && len(primaryApprovers) > 0 { + state.ActivationRules[0].ApprovalStages[0].PrimaryApprovers = make([]RoleManagementPolicyApprover, len(primaryApprovers)) + + for ia, pa := range primaryApprovers { + approver := pa.(map[string]interface{}) + state.ActivationRules[0].ApprovalStages[0].PrimaryApprovers[ia] = RoleManagementPolicyApprover{ + ID: approver["id"].(string), + Type: approver["userType"].(string), + } + } + } + } + } + + case "Enablement_Admin_Assignment": + state.ActiveAssignmentRules[0].RequireMultiFactorAuth = false + state.ActiveAssignmentRules[0].RequireJustification = false + + if enabledRules, ok := rule.Values["enabledRules"].([]interface{}); ok { + for _, enabledRule := range enabledRules { + switch enabledRule.(string) { + case "MultiFactorAuthentication": + state.ActiveAssignmentRules[0].RequireMultiFactorAuth = true + case "Justification": + state.ActiveAssignmentRules[0].RequireJustification = true + } + } + } + + case "Enablement_EndUser_Assignment": + state.ActivationRules[0].RequireMultiFactorAuth = false + state.ActivationRules[0].RequireJustification = false + state.ActivationRules[0].RequireTicketInfo = false + + if enabledRules, ok := rule.Values["enabledRules"].([]interface{}); ok { + for _, enabledRule := range enabledRules { + switch enabledRule.(string) { + case "MultiFactorAuthentication": + state.ActivationRules[0].RequireMultiFactorAuth = true + case "Justification": + state.ActivationRules[0].RequireJustification = true + case "Ticketing": + state.ActivationRules[0].RequireTicketInfo = true + } + } + } + + case "Expiration_Admin_Eligibility": + state.EligibleAssignmentRules[0].ExpirationRequired = rule.Values["isExpirationRequired"].(bool) + state.EligibleAssignmentRules[0].ExpireAfter = rule.Values["maximumDuration"].(string) + + case "Expiration_Admin_Assignment": + state.ActiveAssignmentRules[0].ExpirationRequired = rule.Values["isExpirationRequired"].(bool) + state.ActiveAssignmentRules[0].ExpireAfter = rule.Values["maximumDuration"].(string) + + case "Expiration_EndUser_Assignment": + state.ActivationRules[0].MaximumDuration = rule.Values["maximumDuration"].(string) + + case "Notification_Admin_Admin_Assignment": + state.NotificationRules[0].ActiveAssignments[0].AdminNotifications = []RoleManagementPolicyNotificationSettings{ + *flattenNotificationSettings(rule.Values), + } + + case "Notification_Admin_Admin_Eligibility": + state.NotificationRules[0].EligibleAssignments[0].AdminNotifications = []RoleManagementPolicyNotificationSettings{ + *flattenNotificationSettings(rule.Values), + } + + case "Notification_Admin_EndUser_Assignment": + state.NotificationRules[0].EligibleActivations[0].AdminNotifications = []RoleManagementPolicyNotificationSettings{ + *flattenNotificationSettings(rule.Values), + } + + case "Notification_Approver_Admin_Assignment": + state.NotificationRules[0].ActiveAssignments[0].ApproverNotifications = []RoleManagementPolicyNotificationSettings{ + *flattenNotificationSettings(rule.Values), + } + + case "Notification_Approver_Admin_Eligibility": + state.NotificationRules[0].EligibleAssignments[0].ApproverNotifications = []RoleManagementPolicyNotificationSettings{ + *flattenNotificationSettings(rule.Values), + } + + case "Notification_Approver_EndUser_Assignment": + state.NotificationRules[0].EligibleActivations[0].ApproverNotifications = []RoleManagementPolicyNotificationSettings{ + *flattenNotificationSettings(rule.Values), + } + + case "Notification_Requestor_Admin_Assignment": + state.NotificationRules[0].ActiveAssignments[0].AssigneeNotifications = []RoleManagementPolicyNotificationSettings{ + *flattenNotificationSettings(rule.Values), + } + + case "Notification_Requestor_Admin_Eligibility": + state.NotificationRules[0].EligibleAssignments[0].AssigneeNotifications = []RoleManagementPolicyNotificationSettings{ + *flattenNotificationSettings(rule.Values), + } + + case "Notification_Requestor_EndUser_Assignment": + state.NotificationRules[0].EligibleActivations[0].AssigneeNotifications = []RoleManagementPolicyNotificationSettings{ + *flattenNotificationSettings(rule.Values), + } + } + } + } + } + + return metadata.Encode(&state) + }, + } +} + +func (r RoleManagementPolicyResource) Update() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.Authorization.RoleManagementPoliciesClient + + id, err := parse.RoleManagementPolicyID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + policyId, err := FindRoleManagementPolicyId(ctx, metadata.Client.Authorization.RoleManagementPoliciesClient, id.Scope, id.RoleDefinitionId) + if err != nil { + return err + } + + existing, err := client.Get(ctx, *policyId) + if err != nil { + return fmt.Errorf("retrieving existing %s: %+v", policyId, err) + } + + if existing.Model == nil { + return fmt.Errorf("retrieving %s: model was nil", id) + } + + model, err := buildRoleManagementPolicyForUpdate(pointer.To(metadata), existing.Model) + if err != nil { + return fmt.Errorf("could not build update request, %+v", err) + } + + if _, err = client.Update(ctx, *policyId, *model); err != nil { + return fmt.Errorf("updating %s: %+v", policyId, err) + } + + return nil + }, + } +} + +func (r RoleManagementPolicyResource) Delete() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 5 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + if _, err := parse.RoleManagementPolicyID(metadata.ResourceData.Id()); err != nil { + return err + } + + // Role Management Policies cannot be deleted, so we'll just return without doing anything + return nil + }, + } +} + +func notificationRuleSchema() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "admin_notifications": { + Description: "Admin notification settings", + Type: pluginsdk.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: notificationSettingsSchema(), + }, + }, + + "approver_notifications": { + Description: "Approver notification settings", + Type: pluginsdk.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: notificationSettingsSchema(), + }, + }, + + "assignee_notifications": { + Description: "Assignee notification settings", + Type: pluginsdk.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: notificationSettingsSchema(), + }, + }, + } +} + +func notificationSettingsSchema() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "notification_level": { + Description: "What level of notifications are sent", + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"All", "Critical"}, false), + }, + + "default_recipients": { + Description: "Whether the default recipients are notified", + Type: pluginsdk.TypeBool, + Required: true, + }, + + "additional_recipients": { + Description: "The additional recipients to notify", + Type: pluginsdk.TypeSet, + Optional: true, + Computed: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + }, + }, + } +} diff --git a/internal/services/authorization/role_management_policy_resource_test.go b/internal/services/authorization/role_management_policy_resource_test.go new file mode 100644 index 000000000000..44314cad17a7 --- /dev/null +++ b/internal/services/authorization/role_management_policy_resource_test.go @@ -0,0 +1,385 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package authorization_test + +import ( + "context" + "fmt" + "testing" + + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/authorization" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/authorization/parse" +) + +type RoleManagementPolicyResource struct{} + +func TestAccRoleManagementPolicy_managementGroup(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_role_management_policy", "test") + r := RoleManagementPolicyResource{} + + // Ignore the dangling resource post-test as the policy remains while the management group exists, or is in a pending deletion state + data.ResourceTestSkipCheckDestroyed(t, []acceptance.TestStep{ + { + Config: r.managementGroup(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("active_assignment_rules.0.expire_after").HasValue("P90D"), + check.That(data.ResourceName).Key("eligible_assignment_rules.0.expiration_required").HasValue("false"), + check.That(data.ResourceName).Key("notification_rules.0.active_assignments.0.admin_notifications.0.notification_level").HasValue("Critical"), + ), + }, + data.ImportStep(), + }) +} + +func TestAccRoleManagementPolicy_resourceGroup(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_role_management_policy", "test") + r := RoleManagementPolicyResource{} + + // Ignore the dangling resource post-test as the policy remains while the resource group exists, or is in a pending deletion state + data.ResourceTestSkipCheckDestroyed(t, []acceptance.TestStep{ + { + Config: r.resourceGroup(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("active_assignment_rules.0.expire_after").HasValue("P30D"), + check.That(data.ResourceName).Key("eligible_assignment_rules.0.expiration_required").HasValue("false"), + check.That(data.ResourceName).Key("notification_rules.0.eligible_assignments.0.approver_notifications.0.notification_level").HasValue("All"), + ), + }, + data.ImportStep(), + { + Config: r.resourceGroupUpdate(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("active_assignment_rules.0.expire_after").HasValue("P15D"), + check.That(data.ResourceName).Key("eligible_assignment_rules.0.expiration_required").HasValue("true"), + check.That(data.ResourceName).Key("activation_rules.0.approval_stage.0.primary_approver.0.type").HasValue("Group"), + check.That(data.ResourceName).Key("notification_rules.0.eligible_assignments.0.approver_notifications.0.notification_level").HasValue("Critical"), + ), + }, + data.ImportStep(), + }) +} + +func TestAccRoleManagementPolicy_subscription(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_role_management_policy", "test") + r := RoleManagementPolicyResource{} + + // Ignore the dangling resource post-test as the policy remains while the subscription exists, or is in a pending deletion state + data.ResourceTestSkipCheckDestroyed(t, []acceptance.TestStep{ + { + Config: r.subscription(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("active_assignment_rules.0.expire_after").HasValue("P180D"), + check.That(data.ResourceName).Key("eligible_assignment_rules.0.expiration_required").HasValue("false"), + check.That(data.ResourceName).Key("notification_rules.0.eligible_assignments.0.approver_notifications.0.notification_level").HasValue("Critical"), + ), + }, + data.ImportStep(), + { + Config: r.subscriptionUpdate(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("active_assignment_rules.0.expire_after").HasValue("P365D"), + check.That(data.ResourceName).Key("eligible_assignment_rules.0.expiration_required").HasValue("false"), + check.That(data.ResourceName).Key("activation_rules.0.approval_stage.0.primary_approver.0.type").HasValue("Group"), + check.That(data.ResourceName).Key("notification_rules.0.eligible_assignments.0.approver_notifications.0.notification_level").HasValue("Critical"), + ), + }, + data.ImportStep(), + }) +} + +func (RoleManagementPolicyResource) Exists(ctx context.Context, clients *clients.Client, state *terraform.InstanceState) (*bool, error) { + client := clients.Authorization.RoleManagementPoliciesClient + + id, err := parse.RoleManagementPolicyID(state.ID) + if err != nil { + return nil, err + } + + policyId, err := authorization.FindRoleManagementPolicyId(ctx, clients.Authorization.RoleManagementPoliciesClient, id.Scope, id.RoleDefinitionId) + if err != nil { + return nil, err + } + + resp, err := client.Get(ctx, *policyId) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + return pointer.To(false), nil + } + return nil, fmt.Errorf("retrieving %s: %+v", policyId, err) + } + + return pointer.To(true), nil +} + +func (RoleManagementPolicyResource) managementGroup(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" {} + +provider "azuread" {} + +data "azuread_domains" "test" { + only_initial = true +} + +resource "azuread_user" "approver" { + user_principal_name = "pam-approver-%[1]s@${data.azuread_domains.test.domains.0.domain_name}" + display_name = "PAM Approver Test %[1]s" + password = "p@$$Wd%[1]s" +} + +data "azurerm_client_config" "current" { +} + +resource "azurerm_management_group" "test" { + name = "acctest%[1]s" +} + +data "azurerm_role_definition" "contributor" { + name = "Contributor" + scope = azurerm_management_group.test.id +} + +resource "azurerm_role_management_policy" "test" { + scope = azurerm_management_group.test.id + role_definition_id = data.azurerm_role_definition.contributor.id + + eligible_assignment_rules { + expiration_required = false + } + + active_assignment_rules { + expire_after = "P90D" + } + + activation_rules { + maximum_duration = "PT1H" + require_approval = true + approval_stage { + primary_approver { + object_id = azuread_user.approver.object_id + type = "User" + } + } + } + + notification_rules { + active_assignments { + admin_notifications { + notification_level = "Critical" + default_recipients = false + additional_recipients = ["someone@example.com"] + } + } + } +} +`, data.RandomString) +} + +func (RoleManagementPolicyResource) resourceGroupTemplate(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" {} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%[1]s" + location = "%[2]s" +} + +data "azurerm_role_definition" "contributor" { + name = "Contributor" + scope = azurerm_resource_group.test.id +} +`, data.RandomString, data.Locations.Primary) +} + +func (r RoleManagementPolicyResource) resourceGroup(data acceptance.TestData) string { + return fmt.Sprintf(` +%[1]s + +resource "azurerm_role_management_policy" "test" { + scope = azurerm_resource_group.test.id + role_definition_id = data.azurerm_role_definition.contributor.id + + active_assignment_rules { + expire_after = "P30D" + } + + eligible_assignment_rules { + expiration_required = false + } + + notification_rules { + eligible_assignments { + approver_notifications { + notification_level = "All" + default_recipients = false + additional_recipients = ["someone@example.com"] + } + } + } +} +`, r.resourceGroupTemplate(data), data.RandomString) +} + +func (r RoleManagementPolicyResource) resourceGroupUpdate(data acceptance.TestData) string { + return fmt.Sprintf(` +%[1]s + +provider "azuread" {} + +resource "azuread_group" "approver" { + display_name = "PIM Approver Test %[2]s" + mail_enabled = false + security_enabled = true +} + +resource "azurerm_role_management_policy" "test" { + scope = azurerm_resource_group.test.id + role_definition_id = data.azurerm_role_definition.contributor.id + + active_assignment_rules { + expire_after = "P15D" + } + + eligible_assignment_rules { + expiration_required = true + } + + activation_rules { + maximum_duration = "PT1H" + require_approval = true + approval_stage { + primary_approver { + object_id = azuread_group.approver.object_id + type = "Group" + } + } + } + + notification_rules { + eligible_assignments { + approver_notifications { + notification_level = "Critical" + default_recipients = false + additional_recipients = ["someone@example.com"] + } + } + eligible_activations { + assignee_notifications { + notification_level = "All" + default_recipients = true + additional_recipients = ["someone.else@example.com"] + } + } + } +} +`, r.resourceGroupTemplate(data), data.RandomString) +} + +func (RoleManagementPolicyResource) subscriptionTemplate(data acceptance.TestData) string { + return ` +provider "azurerm" {} + +data "azurerm_subscription" "test" {} + +data "azurerm_role_definition" "contributor" { + name = "Contributor" + scope = data.azurerm_subscription.test.id +} +` +} + +func (r RoleManagementPolicyResource) subscription(data acceptance.TestData) string { + return fmt.Sprintf(` +%[1]s + +resource "azurerm_role_management_policy" "test" { + scope = data.azurerm_subscription.test.id + role_definition_id = data.azurerm_role_definition.contributor.id + + active_assignment_rules { + expire_after = "P180D" + } + + eligible_assignment_rules { + expiration_required = false + } + + notification_rules { + eligible_assignments { + approver_notifications { + notification_level = "Critical" + default_recipients = false + additional_recipients = ["someone@example.com"] + } + } + } +} +`, r.subscriptionTemplate(data), data.RandomString) +} + +func (r RoleManagementPolicyResource) subscriptionUpdate(data acceptance.TestData) string { + return fmt.Sprintf(` +%[1]s + +provider "azuread" {} + +resource "azuread_group" "approver" { + display_name = "PIM Approver Test %[2]s" + mail_enabled = false + security_enabled = true +} + +resource "azurerm_role_management_policy" "test" { + scope = data.azurerm_subscription.test.id + role_definition_id = data.azurerm_role_definition.contributor.id + + active_assignment_rules { + expire_after = "P365D" + } + + eligible_assignment_rules { + expiration_required = false + } + + activation_rules { + maximum_duration = "PT1H" + require_approval = true + approval_stage { + primary_approver { + object_id = azuread_group.approver.object_id + type = "Group" + } + } + } + + notification_rules { + eligible_assignments { + approver_notifications { + notification_level = "Critical" + default_recipients = false + additional_recipients = ["someone@example.com"] + } + } + eligible_activations { + assignee_notifications { + notification_level = "All" + default_recipients = true + additional_recipients = ["someone.else@example.com"] + } + } + } +} +`, r.subscriptionTemplate(data), data.RandomString) +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/README.md b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/README.md new file mode 100644 index 000000000000..1727ff6c07ac --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/README.md @@ -0,0 +1,91 @@ + +## `github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies` Documentation + +The `rolemanagementpolicies` SDK allows for interaction with the Azure Resource Manager Service `authorization` (API Version `2020-10-01`). + +This readme covers example usages, but further information on [using this SDK can be found in the project root](https://github.com/hashicorp/go-azure-sdk/tree/main/docs). + +### Import Path + +```go +import "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" +import "github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies" +``` + + +### Client Initialization + +```go +client := rolemanagementpolicies.NewRoleManagementPoliciesClientWithBaseURI("https://management.azure.com") +client.Client.Authorizer = authorizer +``` + + +### Example Usage: `RoleManagementPoliciesClient.Delete` + +```go +ctx := context.TODO() +id := rolemanagementpolicies.NewScopedRoleManagementPolicyID("/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group", "roleManagementPolicyValue") + +read, err := client.Delete(ctx, id) +if err != nil { + // handle the error +} +if model := read.Model; model != nil { + // do something with the model/response object +} +``` + + +### Example Usage: `RoleManagementPoliciesClient.Get` + +```go +ctx := context.TODO() +id := rolemanagementpolicies.NewScopedRoleManagementPolicyID("/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group", "roleManagementPolicyValue") + +read, err := client.Get(ctx, id) +if err != nil { + // handle the error +} +if model := read.Model; model != nil { + // do something with the model/response object +} +``` + + +### Example Usage: `RoleManagementPoliciesClient.ListForScope` + +```go +ctx := context.TODO() +id := commonids.NewScopeID("/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group") + +// alternatively `client.ListForScope(ctx, id, rolemanagementpolicies.DefaultListForScopeOperationOptions())` can be used to do batched pagination +items, err := client.ListForScopeComplete(ctx, id, rolemanagementpolicies.DefaultListForScopeOperationOptions()) +if err != nil { + // handle the error +} +for _, item := range items { + // do something +} +``` + + +### Example Usage: `RoleManagementPoliciesClient.Update` + +```go +ctx := context.TODO() +id := rolemanagementpolicies.NewScopedRoleManagementPolicyID("/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group", "roleManagementPolicyValue") + +payload := rolemanagementpolicies.RoleManagementPolicy{ + // ... +} + + +read, err := client.Update(ctx, id, payload) +if err != nil { + // handle the error +} +if model := read.Model; model != nil { + // do something with the model/response object +} +``` diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/client.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/client.go new file mode 100644 index 000000000000..89e8d75169ce --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/client.go @@ -0,0 +1,26 @@ +package rolemanagementpolicies + +import ( + "fmt" + + "github.com/hashicorp/go-azure-sdk/sdk/client/resourcemanager" + sdkEnv "github.com/hashicorp/go-azure-sdk/sdk/environments" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type RoleManagementPoliciesClient struct { + Client *resourcemanager.Client +} + +func NewRoleManagementPoliciesClientWithBaseURI(sdkApi sdkEnv.Api) (*RoleManagementPoliciesClient, error) { + client, err := resourcemanager.NewResourceManagerClient(sdkApi, "rolemanagementpolicies", defaultApiVersion) + if err != nil { + return nil, fmt.Errorf("instantiating RoleManagementPoliciesClient: %+v", err) + } + + return &RoleManagementPoliciesClient{ + Client: client, + }, nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/constants.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/constants.go new file mode 100644 index 000000000000..34d30a7f0494 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/constants.go @@ -0,0 +1,60 @@ +package rolemanagementpolicies + +import ( + "encoding/json" + "fmt" + "strings" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type RoleManagementPolicyRuleType string + +const ( + RoleManagementPolicyRuleTypeRoleManagementPolicyApprovalRule RoleManagementPolicyRuleType = "RoleManagementPolicyApprovalRule" + RoleManagementPolicyRuleTypeRoleManagementPolicyAuthenticationContextRule RoleManagementPolicyRuleType = "RoleManagementPolicyAuthenticationContextRule" + RoleManagementPolicyRuleTypeRoleManagementPolicyEnablementRule RoleManagementPolicyRuleType = "RoleManagementPolicyEnablementRule" + RoleManagementPolicyRuleTypeRoleManagementPolicyExpirationRule RoleManagementPolicyRuleType = "RoleManagementPolicyExpirationRule" + RoleManagementPolicyRuleTypeRoleManagementPolicyNotificationRule RoleManagementPolicyRuleType = "RoleManagementPolicyNotificationRule" +) + +func PossibleValuesForRoleManagementPolicyRuleType() []string { + return []string{ + string(RoleManagementPolicyRuleTypeRoleManagementPolicyApprovalRule), + string(RoleManagementPolicyRuleTypeRoleManagementPolicyAuthenticationContextRule), + string(RoleManagementPolicyRuleTypeRoleManagementPolicyEnablementRule), + string(RoleManagementPolicyRuleTypeRoleManagementPolicyExpirationRule), + string(RoleManagementPolicyRuleTypeRoleManagementPolicyNotificationRule), + } +} + +func (s *RoleManagementPolicyRuleType) UnmarshalJSON(bytes []byte) error { + var decoded string + if err := json.Unmarshal(bytes, &decoded); err != nil { + return fmt.Errorf("unmarshaling: %+v", err) + } + out, err := parseRoleManagementPolicyRuleType(decoded) + if err != nil { + return fmt.Errorf("parsing %q: %+v", decoded, err) + } + *s = *out + return nil +} + +func parseRoleManagementPolicyRuleType(input string) (*RoleManagementPolicyRuleType, error) { + vals := map[string]RoleManagementPolicyRuleType{ + "rolemanagementpolicyapprovalrule": RoleManagementPolicyRuleTypeRoleManagementPolicyApprovalRule, + "rolemanagementpolicyauthenticationcontextrule": RoleManagementPolicyRuleTypeRoleManagementPolicyAuthenticationContextRule, + "rolemanagementpolicyenablementrule": RoleManagementPolicyRuleTypeRoleManagementPolicyEnablementRule, + "rolemanagementpolicyexpirationrule": RoleManagementPolicyRuleTypeRoleManagementPolicyExpirationRule, + "rolemanagementpolicynotificationrule": RoleManagementPolicyRuleTypeRoleManagementPolicyNotificationRule, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := RoleManagementPolicyRuleType(input) + return &out, nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/id_scopedrolemanagementpolicy.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/id_scopedrolemanagementpolicy.go new file mode 100644 index 000000000000..dc31cd1db978 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/id_scopedrolemanagementpolicy.go @@ -0,0 +1,120 @@ +package rolemanagementpolicies + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/recaser" + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +func init() { + recaser.RegisterResourceId(&ScopedRoleManagementPolicyId{}) +} + +var _ resourceids.ResourceId = &ScopedRoleManagementPolicyId{} + +// ScopedRoleManagementPolicyId is a struct representing the Resource ID for a Scoped Role Management Policy +type ScopedRoleManagementPolicyId struct { + Scope string + RoleManagementPolicyName string +} + +// NewScopedRoleManagementPolicyID returns a new ScopedRoleManagementPolicyId struct +func NewScopedRoleManagementPolicyID(scope string, roleManagementPolicyName string) ScopedRoleManagementPolicyId { + return ScopedRoleManagementPolicyId{ + Scope: scope, + RoleManagementPolicyName: roleManagementPolicyName, + } +} + +// ParseScopedRoleManagementPolicyID parses 'input' into a ScopedRoleManagementPolicyId +func ParseScopedRoleManagementPolicyID(input string) (*ScopedRoleManagementPolicyId, error) { + parser := resourceids.NewParserFromResourceIdType(&ScopedRoleManagementPolicyId{}) + parsed, err := parser.Parse(input, false) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + id := ScopedRoleManagementPolicyId{} + if err := id.FromParseResult(*parsed); err != nil { + return nil, err + } + + return &id, nil +} + +// ParseScopedRoleManagementPolicyIDInsensitively parses 'input' case-insensitively into a ScopedRoleManagementPolicyId +// note: this method should only be used for API response data and not user input +func ParseScopedRoleManagementPolicyIDInsensitively(input string) (*ScopedRoleManagementPolicyId, error) { + parser := resourceids.NewParserFromResourceIdType(&ScopedRoleManagementPolicyId{}) + parsed, err := parser.Parse(input, true) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + id := ScopedRoleManagementPolicyId{} + if err := id.FromParseResult(*parsed); err != nil { + return nil, err + } + + return &id, nil +} + +func (id *ScopedRoleManagementPolicyId) FromParseResult(input resourceids.ParseResult) error { + var ok bool + + if id.Scope, ok = input.Parsed["scope"]; !ok { + return resourceids.NewSegmentNotSpecifiedError(id, "scope", input) + } + + if id.RoleManagementPolicyName, ok = input.Parsed["roleManagementPolicyName"]; !ok { + return resourceids.NewSegmentNotSpecifiedError(id, "roleManagementPolicyName", input) + } + + return nil +} + +// ValidateScopedRoleManagementPolicyID checks that 'input' can be parsed as a Scoped Role Management Policy ID +func ValidateScopedRoleManagementPolicyID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := ParseScopedRoleManagementPolicyID(v); err != nil { + errors = append(errors, err) + } + + return +} + +// ID returns the formatted Scoped Role Management Policy ID +func (id ScopedRoleManagementPolicyId) ID() string { + fmtString := "/%s/providers/Microsoft.Authorization/roleManagementPolicies/%s" + return fmt.Sprintf(fmtString, strings.TrimPrefix(id.Scope, "/"), id.RoleManagementPolicyName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Scoped Role Management Policy ID +func (id ScopedRoleManagementPolicyId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.ScopeSegment("scope", "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group"), + resourceids.StaticSegment("staticProviders", "providers", "providers"), + resourceids.ResourceProviderSegment("staticMicrosoftAuthorization", "Microsoft.Authorization", "Microsoft.Authorization"), + resourceids.StaticSegment("staticRoleManagementPolicies", "roleManagementPolicies", "roleManagementPolicies"), + resourceids.UserSpecifiedSegment("roleManagementPolicyName", "roleManagementPolicyValue"), + } +} + +// String returns a human-readable description of this Scoped Role Management Policy ID +func (id ScopedRoleManagementPolicyId) String() string { + components := []string{ + fmt.Sprintf("Scope: %q", id.Scope), + fmt.Sprintf("Role Management Policy Name: %q", id.RoleManagementPolicyName), + } + return fmt.Sprintf("Scoped Role Management Policy (%s)", strings.Join(components, "\n")) +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/method_delete.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/method_delete.go new file mode 100644 index 000000000000..568436b022d2 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/method_delete.go @@ -0,0 +1,47 @@ +package rolemanagementpolicies + +import ( + "context" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type DeleteOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData +} + +// Delete ... +func (c RoleManagementPoliciesClient) Delete(ctx context.Context, id ScopedRoleManagementPolicyId) (result DeleteOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusNoContent, + http.StatusOK, + }, + HttpMethod: http.MethodDelete, + Path: id.ID(), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/method_get.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/method_get.go new file mode 100644 index 000000000000..ea14ce67cea3 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/method_get.go @@ -0,0 +1,54 @@ +package rolemanagementpolicies + +import ( + "context" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type GetOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData + Model *RoleManagementPolicy +} + +// Get ... +func (c RoleManagementPoliciesClient) Get(ctx context.Context, id ScopedRoleManagementPolicyId) (result GetOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusOK, + }, + HttpMethod: http.MethodGet, + Path: id.ID(), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + var model RoleManagementPolicy + result.Model = &model + + if err = resp.Unmarshal(result.Model); err != nil { + return + } + + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/method_listforscope.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/method_listforscope.go new file mode 100644 index 000000000000..253412ca2195 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/method_listforscope.go @@ -0,0 +1,121 @@ +package rolemanagementpolicies + +import ( + "context" + "fmt" + "net/http" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type ListForScopeOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData + Model *[]RoleManagementPolicy +} + +type ListForScopeCompleteResult struct { + LatestHttpResponse *http.Response + Items []RoleManagementPolicy +} + +type ListForScopeOperationOptions struct { + Filter *string +} + +func DefaultListForScopeOperationOptions() ListForScopeOperationOptions { + return ListForScopeOperationOptions{} +} + +func (o ListForScopeOperationOptions) ToHeaders() *client.Headers { + out := client.Headers{} + + return &out +} + +func (o ListForScopeOperationOptions) ToOData() *odata.Query { + out := odata.Query{} + return &out +} + +func (o ListForScopeOperationOptions) ToQuery() *client.QueryParams { + out := client.QueryParams{} + if o.Filter != nil { + out.Append("$filter", fmt.Sprintf("%v", *o.Filter)) + } + return &out +} + +// ListForScope ... +func (c RoleManagementPoliciesClient) ListForScope(ctx context.Context, id commonids.ScopeId, options ListForScopeOperationOptions) (result ListForScopeOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusOK, + }, + HttpMethod: http.MethodGet, + Path: fmt.Sprintf("%s/providers/Microsoft.Authorization/roleManagementPolicies", id.ID()), + OptionsObject: options, + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + var resp *client.Response + resp, err = req.ExecutePaged(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + var values struct { + Values *[]RoleManagementPolicy `json:"value"` + } + if err = resp.Unmarshal(&values); err != nil { + return + } + + result.Model = values.Values + + return +} + +// ListForScopeComplete retrieves all the results into a single object +func (c RoleManagementPoliciesClient) ListForScopeComplete(ctx context.Context, id commonids.ScopeId, options ListForScopeOperationOptions) (ListForScopeCompleteResult, error) { + return c.ListForScopeCompleteMatchingPredicate(ctx, id, options, RoleManagementPolicyOperationPredicate{}) +} + +// ListForScopeCompleteMatchingPredicate retrieves all the results and then applies the predicate +func (c RoleManagementPoliciesClient) ListForScopeCompleteMatchingPredicate(ctx context.Context, id commonids.ScopeId, options ListForScopeOperationOptions, predicate RoleManagementPolicyOperationPredicate) (result ListForScopeCompleteResult, err error) { + items := make([]RoleManagementPolicy, 0) + + resp, err := c.ListForScope(ctx, id, options) + if err != nil { + result.LatestHttpResponse = resp.HttpResponse + err = fmt.Errorf("loading results: %+v", err) + return + } + if resp.Model != nil { + for _, v := range *resp.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + + result = ListForScopeCompleteResult{ + LatestHttpResponse: resp.HttpResponse, + Items: items, + } + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/method_update.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/method_update.go new file mode 100644 index 000000000000..fbc5442aac46 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/method_update.go @@ -0,0 +1,58 @@ +package rolemanagementpolicies + +import ( + "context" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type UpdateOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData + Model *RoleManagementPolicy +} + +// Update ... +func (c RoleManagementPoliciesClient) Update(ctx context.Context, id ScopedRoleManagementPolicyId, input RoleManagementPolicy) (result UpdateOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusOK, + }, + HttpMethod: http.MethodPatch, + Path: id.ID(), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + if err = req.Marshal(input); err != nil { + return + } + + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + var model RoleManagementPolicy + result.Model = &model + + if err = resp.Unmarshal(result.Model); err != nil { + return + } + + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/model_policyproperties.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/model_policyproperties.go new file mode 100644 index 000000000000..af2bc58ecd1d --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/model_policyproperties.go @@ -0,0 +1,8 @@ +package rolemanagementpolicies + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type PolicyProperties struct { + Scope *PolicyPropertiesScope `json:"scope,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/model_policypropertiesscope.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/model_policypropertiesscope.go new file mode 100644 index 000000000000..5a70ff199bd6 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/model_policypropertiesscope.go @@ -0,0 +1,10 @@ +package rolemanagementpolicies + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type PolicyPropertiesScope struct { + DisplayName *string `json:"displayName,omitempty"` + Id *string `json:"id,omitempty"` + Type *string `json:"type,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/model_principal.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/model_principal.go new file mode 100644 index 000000000000..ad3771f02ce0 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/model_principal.go @@ -0,0 +1,11 @@ +package rolemanagementpolicies + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type Principal struct { + DisplayName *string `json:"displayName,omitempty"` + Email *string `json:"email,omitempty"` + Id *string `json:"id,omitempty"` + Type *string `json:"type,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/model_rolemanagementpolicy.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/model_rolemanagementpolicy.go new file mode 100644 index 000000000000..9c5cc478fd16 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/model_rolemanagementpolicy.go @@ -0,0 +1,11 @@ +package rolemanagementpolicies + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type RoleManagementPolicy struct { + Id *string `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Properties *RoleManagementPolicyProperties `json:"properties,omitempty"` + Type *string `json:"type,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/model_rolemanagementpolicyproperties.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/model_rolemanagementpolicyproperties.go new file mode 100644 index 000000000000..310d9b0cf682 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/model_rolemanagementpolicyproperties.go @@ -0,0 +1,94 @@ +package rolemanagementpolicies + +import ( + "encoding/json" + "fmt" + "time" + + "github.com/hashicorp/go-azure-helpers/lang/dates" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type RoleManagementPolicyProperties struct { + Description *string `json:"description,omitempty"` + DisplayName *string `json:"displayName,omitempty"` + EffectiveRules *[]RoleManagementPolicyRule `json:"effectiveRules,omitempty"` + IsOrganizationDefault *bool `json:"isOrganizationDefault,omitempty"` + LastModifiedBy *Principal `json:"lastModifiedBy,omitempty"` + LastModifiedDateTime *string `json:"lastModifiedDateTime,omitempty"` + PolicyProperties *PolicyProperties `json:"policyProperties,omitempty"` + Rules *[]RoleManagementPolicyRule `json:"rules,omitempty"` + Scope *string `json:"scope,omitempty"` +} + +func (o *RoleManagementPolicyProperties) GetLastModifiedDateTimeAsTime() (*time.Time, error) { + if o.LastModifiedDateTime == nil { + return nil, nil + } + return dates.ParseAsFormat(o.LastModifiedDateTime, "2006-01-02T15:04:05Z07:00") +} + +func (o *RoleManagementPolicyProperties) SetLastModifiedDateTimeAsTime(input time.Time) { + formatted := input.Format("2006-01-02T15:04:05Z07:00") + o.LastModifiedDateTime = &formatted +} + +var _ json.Unmarshaler = &RoleManagementPolicyProperties{} + +func (s *RoleManagementPolicyProperties) UnmarshalJSON(bytes []byte) error { + type alias RoleManagementPolicyProperties + var decoded alias + if err := json.Unmarshal(bytes, &decoded); err != nil { + return fmt.Errorf("unmarshaling into RoleManagementPolicyProperties: %+v", err) + } + + s.Description = decoded.Description + s.DisplayName = decoded.DisplayName + s.IsOrganizationDefault = decoded.IsOrganizationDefault + s.LastModifiedBy = decoded.LastModifiedBy + s.LastModifiedDateTime = decoded.LastModifiedDateTime + s.PolicyProperties = decoded.PolicyProperties + s.Scope = decoded.Scope + + var temp map[string]json.RawMessage + if err := json.Unmarshal(bytes, &temp); err != nil { + return fmt.Errorf("unmarshaling RoleManagementPolicyProperties into map[string]json.RawMessage: %+v", err) + } + + if v, ok := temp["effectiveRules"]; ok { + var listTemp []json.RawMessage + if err := json.Unmarshal(v, &listTemp); err != nil { + return fmt.Errorf("unmarshaling EffectiveRules into list []json.RawMessage: %+v", err) + } + + output := make([]RoleManagementPolicyRule, 0) + for i, val := range listTemp { + impl, err := unmarshalRoleManagementPolicyRuleImplementation(val) + if err != nil { + return fmt.Errorf("unmarshaling index %d field 'EffectiveRules' for 'RoleManagementPolicyProperties': %+v", i, err) + } + output = append(output, impl) + } + s.EffectiveRules = &output + } + + if v, ok := temp["rules"]; ok { + var listTemp []json.RawMessage + if err := json.Unmarshal(v, &listTemp); err != nil { + return fmt.Errorf("unmarshaling Rules into list []json.RawMessage: %+v", err) + } + + output := make([]RoleManagementPolicyRule, 0) + for i, val := range listTemp { + impl, err := unmarshalRoleManagementPolicyRuleImplementation(val) + if err != nil { + return fmt.Errorf("unmarshaling index %d field 'Rules' for 'RoleManagementPolicyProperties': %+v", i, err) + } + output = append(output, impl) + } + s.Rules = &output + } + return nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/model_rolemanagementpolicyrule.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/model_rolemanagementpolicyrule.go new file mode 100644 index 000000000000..d89224dc5fa9 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/model_rolemanagementpolicyrule.go @@ -0,0 +1,44 @@ +package rolemanagementpolicies + +import ( + "encoding/json" + "fmt" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type RoleManagementPolicyRule interface { +} + +// RawRoleManagementPolicyRuleImpl is returned when the Discriminated Value +// doesn't match any of the defined types +// NOTE: this should only be used when a type isn't defined for this type of Object (as a workaround) +// and is used only for Deserialization (e.g. this cannot be used as a Request Payload). +type RawRoleManagementPolicyRuleImpl struct { + Type string + Values map[string]interface{} +} + +func unmarshalRoleManagementPolicyRuleImplementation(input []byte) (RoleManagementPolicyRule, error) { + if input == nil { + return nil, nil + } + + var temp map[string]interface{} + if err := json.Unmarshal(input, &temp); err != nil { + return nil, fmt.Errorf("unmarshaling RoleManagementPolicyRule into map[string]interface: %+v", err) + } + + value, ok := temp["ruleType"].(string) + if !ok { + return nil, nil + } + + out := RawRoleManagementPolicyRuleImpl{ + Type: value, + Values: temp, + } + return out, nil + +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/model_rolemanagementpolicyruletarget.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/model_rolemanagementpolicyruletarget.go new file mode 100644 index 000000000000..b93dd22a7fe3 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/model_rolemanagementpolicyruletarget.go @@ -0,0 +1,13 @@ +package rolemanagementpolicies + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type RoleManagementPolicyRuleTarget struct { + Caller *string `json:"caller,omitempty"` + EnforcedSettings *[]string `json:"enforcedSettings,omitempty"` + InheritableSettings *[]string `json:"inheritableSettings,omitempty"` + Level *string `json:"level,omitempty"` + Operations *[]string `json:"operations,omitempty"` + TargetObjects *[]string `json:"targetObjects,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/predicates.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/predicates.go new file mode 100644 index 000000000000..7957ae7375fa --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/predicates.go @@ -0,0 +1,27 @@ +package rolemanagementpolicies + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type RoleManagementPolicyOperationPredicate struct { + Id *string + Name *string + Type *string +} + +func (p RoleManagementPolicyOperationPredicate) Matches(input RoleManagementPolicy) bool { + + if p.Id != nil && (input.Id == nil || *p.Id != *input.Id) { + return false + } + + if p.Name != nil && (input.Name == nil || *p.Name != *input.Name) { + return false + } + + if p.Type != nil && (input.Type == nil || *p.Type != *input.Type) { + return false + } + + return true +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/version.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/version.go new file mode 100644 index 000000000000..cbd840f2fced --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies/version.go @@ -0,0 +1,12 @@ +package rolemanagementpolicies + +import "fmt" + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +const defaultApiVersion = "2020-10-01" + +func userAgent() string { + return fmt.Sprintf("hashicorp/go-azure-sdk/rolemanagementpolicies/%s", defaultApiVersion) +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/README.md b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/README.md new file mode 100644 index 000000000000..07508baf38e2 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/README.md @@ -0,0 +1,91 @@ + +## `github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments` Documentation + +The `rolemanagementpolicyassignments` SDK allows for interaction with the Azure Resource Manager Service `authorization` (API Version `2020-10-01`). + +This readme covers example usages, but further information on [using this SDK can be found in the project root](https://github.com/hashicorp/go-azure-sdk/tree/main/docs). + +### Import Path + +```go +import "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" +import "github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments" +``` + + +### Client Initialization + +```go +client := rolemanagementpolicyassignments.NewRoleManagementPolicyAssignmentsClientWithBaseURI("https://management.azure.com") +client.Client.Authorizer = authorizer +``` + + +### Example Usage: `RoleManagementPolicyAssignmentsClient.Create` + +```go +ctx := context.TODO() +id := rolemanagementpolicyassignments.NewScopedRoleManagementPolicyAssignmentID("/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group", "roleManagementPolicyAssignmentValue") + +payload := rolemanagementpolicyassignments.RoleManagementPolicyAssignment{ + // ... +} + + +read, err := client.Create(ctx, id, payload) +if err != nil { + // handle the error +} +if model := read.Model; model != nil { + // do something with the model/response object +} +``` + + +### Example Usage: `RoleManagementPolicyAssignmentsClient.Delete` + +```go +ctx := context.TODO() +id := rolemanagementpolicyassignments.NewScopedRoleManagementPolicyAssignmentID("/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group", "roleManagementPolicyAssignmentValue") + +read, err := client.Delete(ctx, id) +if err != nil { + // handle the error +} +if model := read.Model; model != nil { + // do something with the model/response object +} +``` + + +### Example Usage: `RoleManagementPolicyAssignmentsClient.Get` + +```go +ctx := context.TODO() +id := rolemanagementpolicyassignments.NewScopedRoleManagementPolicyAssignmentID("/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group", "roleManagementPolicyAssignmentValue") + +read, err := client.Get(ctx, id) +if err != nil { + // handle the error +} +if model := read.Model; model != nil { + // do something with the model/response object +} +``` + + +### Example Usage: `RoleManagementPolicyAssignmentsClient.ListForScope` + +```go +ctx := context.TODO() +id := commonids.NewScopeID("/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group") + +// alternatively `client.ListForScope(ctx, id)` can be used to do batched pagination +items, err := client.ListForScopeComplete(ctx, id) +if err != nil { + // handle the error +} +for _, item := range items { + // do something +} +``` diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/client.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/client.go new file mode 100644 index 000000000000..c2d42940c831 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/client.go @@ -0,0 +1,26 @@ +package rolemanagementpolicyassignments + +import ( + "fmt" + + "github.com/hashicorp/go-azure-sdk/sdk/client/resourcemanager" + sdkEnv "github.com/hashicorp/go-azure-sdk/sdk/environments" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type RoleManagementPolicyAssignmentsClient struct { + Client *resourcemanager.Client +} + +func NewRoleManagementPolicyAssignmentsClientWithBaseURI(sdkApi sdkEnv.Api) (*RoleManagementPolicyAssignmentsClient, error) { + client, err := resourcemanager.NewResourceManagerClient(sdkApi, "rolemanagementpolicyassignments", defaultApiVersion) + if err != nil { + return nil, fmt.Errorf("instantiating RoleManagementPolicyAssignmentsClient: %+v", err) + } + + return &RoleManagementPolicyAssignmentsClient{ + Client: client, + }, nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/constants.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/constants.go new file mode 100644 index 000000000000..429be1bb0c47 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/constants.go @@ -0,0 +1,60 @@ +package rolemanagementpolicyassignments + +import ( + "encoding/json" + "fmt" + "strings" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type RoleManagementPolicyRuleType string + +const ( + RoleManagementPolicyRuleTypeRoleManagementPolicyApprovalRule RoleManagementPolicyRuleType = "RoleManagementPolicyApprovalRule" + RoleManagementPolicyRuleTypeRoleManagementPolicyAuthenticationContextRule RoleManagementPolicyRuleType = "RoleManagementPolicyAuthenticationContextRule" + RoleManagementPolicyRuleTypeRoleManagementPolicyEnablementRule RoleManagementPolicyRuleType = "RoleManagementPolicyEnablementRule" + RoleManagementPolicyRuleTypeRoleManagementPolicyExpirationRule RoleManagementPolicyRuleType = "RoleManagementPolicyExpirationRule" + RoleManagementPolicyRuleTypeRoleManagementPolicyNotificationRule RoleManagementPolicyRuleType = "RoleManagementPolicyNotificationRule" +) + +func PossibleValuesForRoleManagementPolicyRuleType() []string { + return []string{ + string(RoleManagementPolicyRuleTypeRoleManagementPolicyApprovalRule), + string(RoleManagementPolicyRuleTypeRoleManagementPolicyAuthenticationContextRule), + string(RoleManagementPolicyRuleTypeRoleManagementPolicyEnablementRule), + string(RoleManagementPolicyRuleTypeRoleManagementPolicyExpirationRule), + string(RoleManagementPolicyRuleTypeRoleManagementPolicyNotificationRule), + } +} + +func (s *RoleManagementPolicyRuleType) UnmarshalJSON(bytes []byte) error { + var decoded string + if err := json.Unmarshal(bytes, &decoded); err != nil { + return fmt.Errorf("unmarshaling: %+v", err) + } + out, err := parseRoleManagementPolicyRuleType(decoded) + if err != nil { + return fmt.Errorf("parsing %q: %+v", decoded, err) + } + *s = *out + return nil +} + +func parseRoleManagementPolicyRuleType(input string) (*RoleManagementPolicyRuleType, error) { + vals := map[string]RoleManagementPolicyRuleType{ + "rolemanagementpolicyapprovalrule": RoleManagementPolicyRuleTypeRoleManagementPolicyApprovalRule, + "rolemanagementpolicyauthenticationcontextrule": RoleManagementPolicyRuleTypeRoleManagementPolicyAuthenticationContextRule, + "rolemanagementpolicyenablementrule": RoleManagementPolicyRuleTypeRoleManagementPolicyEnablementRule, + "rolemanagementpolicyexpirationrule": RoleManagementPolicyRuleTypeRoleManagementPolicyExpirationRule, + "rolemanagementpolicynotificationrule": RoleManagementPolicyRuleTypeRoleManagementPolicyNotificationRule, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := RoleManagementPolicyRuleType(input) + return &out, nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/id_scopedrolemanagementpolicyassignment.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/id_scopedrolemanagementpolicyassignment.go new file mode 100644 index 000000000000..aab2b229ecc9 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/id_scopedrolemanagementpolicyassignment.go @@ -0,0 +1,120 @@ +package rolemanagementpolicyassignments + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/recaser" + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +func init() { + recaser.RegisterResourceId(&ScopedRoleManagementPolicyAssignmentId{}) +} + +var _ resourceids.ResourceId = &ScopedRoleManagementPolicyAssignmentId{} + +// ScopedRoleManagementPolicyAssignmentId is a struct representing the Resource ID for a Scoped Role Management Policy Assignment +type ScopedRoleManagementPolicyAssignmentId struct { + Scope string + RoleManagementPolicyAssignmentName string +} + +// NewScopedRoleManagementPolicyAssignmentID returns a new ScopedRoleManagementPolicyAssignmentId struct +func NewScopedRoleManagementPolicyAssignmentID(scope string, roleManagementPolicyAssignmentName string) ScopedRoleManagementPolicyAssignmentId { + return ScopedRoleManagementPolicyAssignmentId{ + Scope: scope, + RoleManagementPolicyAssignmentName: roleManagementPolicyAssignmentName, + } +} + +// ParseScopedRoleManagementPolicyAssignmentID parses 'input' into a ScopedRoleManagementPolicyAssignmentId +func ParseScopedRoleManagementPolicyAssignmentID(input string) (*ScopedRoleManagementPolicyAssignmentId, error) { + parser := resourceids.NewParserFromResourceIdType(&ScopedRoleManagementPolicyAssignmentId{}) + parsed, err := parser.Parse(input, false) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + id := ScopedRoleManagementPolicyAssignmentId{} + if err := id.FromParseResult(*parsed); err != nil { + return nil, err + } + + return &id, nil +} + +// ParseScopedRoleManagementPolicyAssignmentIDInsensitively parses 'input' case-insensitively into a ScopedRoleManagementPolicyAssignmentId +// note: this method should only be used for API response data and not user input +func ParseScopedRoleManagementPolicyAssignmentIDInsensitively(input string) (*ScopedRoleManagementPolicyAssignmentId, error) { + parser := resourceids.NewParserFromResourceIdType(&ScopedRoleManagementPolicyAssignmentId{}) + parsed, err := parser.Parse(input, true) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + id := ScopedRoleManagementPolicyAssignmentId{} + if err := id.FromParseResult(*parsed); err != nil { + return nil, err + } + + return &id, nil +} + +func (id *ScopedRoleManagementPolicyAssignmentId) FromParseResult(input resourceids.ParseResult) error { + var ok bool + + if id.Scope, ok = input.Parsed["scope"]; !ok { + return resourceids.NewSegmentNotSpecifiedError(id, "scope", input) + } + + if id.RoleManagementPolicyAssignmentName, ok = input.Parsed["roleManagementPolicyAssignmentName"]; !ok { + return resourceids.NewSegmentNotSpecifiedError(id, "roleManagementPolicyAssignmentName", input) + } + + return nil +} + +// ValidateScopedRoleManagementPolicyAssignmentID checks that 'input' can be parsed as a Scoped Role Management Policy Assignment ID +func ValidateScopedRoleManagementPolicyAssignmentID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := ParseScopedRoleManagementPolicyAssignmentID(v); err != nil { + errors = append(errors, err) + } + + return +} + +// ID returns the formatted Scoped Role Management Policy Assignment ID +func (id ScopedRoleManagementPolicyAssignmentId) ID() string { + fmtString := "/%s/providers/Microsoft.Authorization/roleManagementPolicyAssignments/%s" + return fmt.Sprintf(fmtString, strings.TrimPrefix(id.Scope, "/"), id.RoleManagementPolicyAssignmentName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Scoped Role Management Policy Assignment ID +func (id ScopedRoleManagementPolicyAssignmentId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.ScopeSegment("scope", "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group"), + resourceids.StaticSegment("staticProviders", "providers", "providers"), + resourceids.ResourceProviderSegment("staticMicrosoftAuthorization", "Microsoft.Authorization", "Microsoft.Authorization"), + resourceids.StaticSegment("staticRoleManagementPolicyAssignments", "roleManagementPolicyAssignments", "roleManagementPolicyAssignments"), + resourceids.UserSpecifiedSegment("roleManagementPolicyAssignmentName", "roleManagementPolicyAssignmentValue"), + } +} + +// String returns a human-readable description of this Scoped Role Management Policy Assignment ID +func (id ScopedRoleManagementPolicyAssignmentId) String() string { + components := []string{ + fmt.Sprintf("Scope: %q", id.Scope), + fmt.Sprintf("Role Management Policy Assignment Name: %q", id.RoleManagementPolicyAssignmentName), + } + return fmt.Sprintf("Scoped Role Management Policy Assignment (%s)", strings.Join(components, "\n")) +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/method_create.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/method_create.go new file mode 100644 index 000000000000..fdb037e7b97b --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/method_create.go @@ -0,0 +1,58 @@ +package rolemanagementpolicyassignments + +import ( + "context" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type CreateOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData + Model *RoleManagementPolicyAssignment +} + +// Create ... +func (c RoleManagementPolicyAssignmentsClient) Create(ctx context.Context, id ScopedRoleManagementPolicyAssignmentId, input RoleManagementPolicyAssignment) (result CreateOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusCreated, + }, + HttpMethod: http.MethodPut, + Path: id.ID(), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + if err = req.Marshal(input); err != nil { + return + } + + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + var model RoleManagementPolicyAssignment + result.Model = &model + + if err = resp.Unmarshal(result.Model); err != nil { + return + } + + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/method_delete.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/method_delete.go new file mode 100644 index 000000000000..17e7afd4e661 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/method_delete.go @@ -0,0 +1,47 @@ +package rolemanagementpolicyassignments + +import ( + "context" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type DeleteOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData +} + +// Delete ... +func (c RoleManagementPolicyAssignmentsClient) Delete(ctx context.Context, id ScopedRoleManagementPolicyAssignmentId) (result DeleteOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusNoContent, + http.StatusOK, + }, + HttpMethod: http.MethodDelete, + Path: id.ID(), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/method_get.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/method_get.go new file mode 100644 index 000000000000..bba35f1b903e --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/method_get.go @@ -0,0 +1,54 @@ +package rolemanagementpolicyassignments + +import ( + "context" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type GetOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData + Model *RoleManagementPolicyAssignment +} + +// Get ... +func (c RoleManagementPolicyAssignmentsClient) Get(ctx context.Context, id ScopedRoleManagementPolicyAssignmentId) (result GetOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusOK, + }, + HttpMethod: http.MethodGet, + Path: id.ID(), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + var model RoleManagementPolicyAssignment + result.Model = &model + + if err = resp.Unmarshal(result.Model); err != nil { + return + } + + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/method_listforscope.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/method_listforscope.go new file mode 100644 index 000000000000..d45b00fee525 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/method_listforscope.go @@ -0,0 +1,93 @@ +package rolemanagementpolicyassignments + +import ( + "context" + "fmt" + "net/http" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type ListForScopeOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData + Model *[]RoleManagementPolicyAssignment +} + +type ListForScopeCompleteResult struct { + LatestHttpResponse *http.Response + Items []RoleManagementPolicyAssignment +} + +// ListForScope ... +func (c RoleManagementPolicyAssignmentsClient) ListForScope(ctx context.Context, id commonids.ScopeId) (result ListForScopeOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusOK, + }, + HttpMethod: http.MethodGet, + Path: fmt.Sprintf("%s/providers/Microsoft.Authorization/roleManagementPolicyAssignments", id.ID()), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + var resp *client.Response + resp, err = req.ExecutePaged(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + var values struct { + Values *[]RoleManagementPolicyAssignment `json:"value"` + } + if err = resp.Unmarshal(&values); err != nil { + return + } + + result.Model = values.Values + + return +} + +// ListForScopeComplete retrieves all the results into a single object +func (c RoleManagementPolicyAssignmentsClient) ListForScopeComplete(ctx context.Context, id commonids.ScopeId) (ListForScopeCompleteResult, error) { + return c.ListForScopeCompleteMatchingPredicate(ctx, id, RoleManagementPolicyAssignmentOperationPredicate{}) +} + +// ListForScopeCompleteMatchingPredicate retrieves all the results and then applies the predicate +func (c RoleManagementPolicyAssignmentsClient) ListForScopeCompleteMatchingPredicate(ctx context.Context, id commonids.ScopeId, predicate RoleManagementPolicyAssignmentOperationPredicate) (result ListForScopeCompleteResult, err error) { + items := make([]RoleManagementPolicyAssignment, 0) + + resp, err := c.ListForScope(ctx, id) + if err != nil { + result.LatestHttpResponse = resp.HttpResponse + err = fmt.Errorf("loading results: %+v", err) + return + } + if resp.Model != nil { + for _, v := range *resp.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + + result = ListForScopeCompleteResult{ + LatestHttpResponse: resp.HttpResponse, + Items: items, + } + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_policyassignmentproperties.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_policyassignmentproperties.go new file mode 100644 index 000000000000..fe8af73d2160 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_policyassignmentproperties.go @@ -0,0 +1,10 @@ +package rolemanagementpolicyassignments + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type PolicyAssignmentProperties struct { + Policy *PolicyAssignmentPropertiesPolicy `json:"policy,omitempty"` + RoleDefinition *PolicyAssignmentPropertiesRoleDefinition `json:"roleDefinition,omitempty"` + Scope *PolicyAssignmentPropertiesScope `json:"scope,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_policyassignmentpropertiespolicy.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_policyassignmentpropertiespolicy.go new file mode 100644 index 000000000000..e6a8e323f626 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_policyassignmentpropertiespolicy.go @@ -0,0 +1,28 @@ +package rolemanagementpolicyassignments + +import ( + "time" + + "github.com/hashicorp/go-azure-helpers/lang/dates" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type PolicyAssignmentPropertiesPolicy struct { + Id *string `json:"id,omitempty"` + LastModifiedBy *Principal `json:"lastModifiedBy,omitempty"` + LastModifiedDateTime *string `json:"lastModifiedDateTime,omitempty"` +} + +func (o *PolicyAssignmentPropertiesPolicy) GetLastModifiedDateTimeAsTime() (*time.Time, error) { + if o.LastModifiedDateTime == nil { + return nil, nil + } + return dates.ParseAsFormat(o.LastModifiedDateTime, "2006-01-02T15:04:05Z07:00") +} + +func (o *PolicyAssignmentPropertiesPolicy) SetLastModifiedDateTimeAsTime(input time.Time) { + formatted := input.Format("2006-01-02T15:04:05Z07:00") + o.LastModifiedDateTime = &formatted +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_policyassignmentpropertiesroledefinition.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_policyassignmentpropertiesroledefinition.go new file mode 100644 index 000000000000..2d3a4bfc169a --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_policyassignmentpropertiesroledefinition.go @@ -0,0 +1,10 @@ +package rolemanagementpolicyassignments + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type PolicyAssignmentPropertiesRoleDefinition struct { + DisplayName *string `json:"displayName,omitempty"` + Id *string `json:"id,omitempty"` + Type *string `json:"type,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_policyassignmentpropertiesscope.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_policyassignmentpropertiesscope.go new file mode 100644 index 000000000000..750df3866265 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_policyassignmentpropertiesscope.go @@ -0,0 +1,10 @@ +package rolemanagementpolicyassignments + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type PolicyAssignmentPropertiesScope struct { + DisplayName *string `json:"displayName,omitempty"` + Id *string `json:"id,omitempty"` + Type *string `json:"type,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_principal.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_principal.go new file mode 100644 index 000000000000..3c2c5a84f6d9 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_principal.go @@ -0,0 +1,11 @@ +package rolemanagementpolicyassignments + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type Principal struct { + DisplayName *string `json:"displayName,omitempty"` + Email *string `json:"email,omitempty"` + Id *string `json:"id,omitempty"` + Type *string `json:"type,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_rolemanagementpolicyassignment.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_rolemanagementpolicyassignment.go new file mode 100644 index 000000000000..9394ae4af6b9 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_rolemanagementpolicyassignment.go @@ -0,0 +1,11 @@ +package rolemanagementpolicyassignments + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type RoleManagementPolicyAssignment struct { + Id *string `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Properties *RoleManagementPolicyAssignmentProperties `json:"properties,omitempty"` + Type *string `json:"type,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_rolemanagementpolicyassignmentproperties.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_rolemanagementpolicyassignmentproperties.go new file mode 100644 index 000000000000..a4a156831b0e --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_rolemanagementpolicyassignmentproperties.go @@ -0,0 +1,55 @@ +package rolemanagementpolicyassignments + +import ( + "encoding/json" + "fmt" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type RoleManagementPolicyAssignmentProperties struct { + EffectiveRules *[]RoleManagementPolicyRule `json:"effectiveRules,omitempty"` + PolicyAssignmentProperties *PolicyAssignmentProperties `json:"policyAssignmentProperties,omitempty"` + PolicyId *string `json:"policyId,omitempty"` + RoleDefinitionId *string `json:"roleDefinitionId,omitempty"` + Scope *string `json:"scope,omitempty"` +} + +var _ json.Unmarshaler = &RoleManagementPolicyAssignmentProperties{} + +func (s *RoleManagementPolicyAssignmentProperties) UnmarshalJSON(bytes []byte) error { + type alias RoleManagementPolicyAssignmentProperties + var decoded alias + if err := json.Unmarshal(bytes, &decoded); err != nil { + return fmt.Errorf("unmarshaling into RoleManagementPolicyAssignmentProperties: %+v", err) + } + + s.PolicyAssignmentProperties = decoded.PolicyAssignmentProperties + s.PolicyId = decoded.PolicyId + s.RoleDefinitionId = decoded.RoleDefinitionId + s.Scope = decoded.Scope + + var temp map[string]json.RawMessage + if err := json.Unmarshal(bytes, &temp); err != nil { + return fmt.Errorf("unmarshaling RoleManagementPolicyAssignmentProperties into map[string]json.RawMessage: %+v", err) + } + + if v, ok := temp["effectiveRules"]; ok { + var listTemp []json.RawMessage + if err := json.Unmarshal(v, &listTemp); err != nil { + return fmt.Errorf("unmarshaling EffectiveRules into list []json.RawMessage: %+v", err) + } + + output := make([]RoleManagementPolicyRule, 0) + for i, val := range listTemp { + impl, err := unmarshalRoleManagementPolicyRuleImplementation(val) + if err != nil { + return fmt.Errorf("unmarshaling index %d field 'EffectiveRules' for 'RoleManagementPolicyAssignmentProperties': %+v", i, err) + } + output = append(output, impl) + } + s.EffectiveRules = &output + } + return nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_rolemanagementpolicyrule.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_rolemanagementpolicyrule.go new file mode 100644 index 000000000000..ab772e8c79a3 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_rolemanagementpolicyrule.go @@ -0,0 +1,44 @@ +package rolemanagementpolicyassignments + +import ( + "encoding/json" + "fmt" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type RoleManagementPolicyRule interface { +} + +// RawRoleManagementPolicyRuleImpl is returned when the Discriminated Value +// doesn't match any of the defined types +// NOTE: this should only be used when a type isn't defined for this type of Object (as a workaround) +// and is used only for Deserialization (e.g. this cannot be used as a Request Payload). +type RawRoleManagementPolicyRuleImpl struct { + Type string + Values map[string]interface{} +} + +func unmarshalRoleManagementPolicyRuleImplementation(input []byte) (RoleManagementPolicyRule, error) { + if input == nil { + return nil, nil + } + + var temp map[string]interface{} + if err := json.Unmarshal(input, &temp); err != nil { + return nil, fmt.Errorf("unmarshaling RoleManagementPolicyRule into map[string]interface: %+v", err) + } + + value, ok := temp["ruleType"].(string) + if !ok { + return nil, nil + } + + out := RawRoleManagementPolicyRuleImpl{ + Type: value, + Values: temp, + } + return out, nil + +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_rolemanagementpolicyruletarget.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_rolemanagementpolicyruletarget.go new file mode 100644 index 000000000000..916e8d18d2e3 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/model_rolemanagementpolicyruletarget.go @@ -0,0 +1,13 @@ +package rolemanagementpolicyassignments + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type RoleManagementPolicyRuleTarget struct { + Caller *string `json:"caller,omitempty"` + EnforcedSettings *[]string `json:"enforcedSettings,omitempty"` + InheritableSettings *[]string `json:"inheritableSettings,omitempty"` + Level *string `json:"level,omitempty"` + Operations *[]string `json:"operations,omitempty"` + TargetObjects *[]string `json:"targetObjects,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/predicates.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/predicates.go new file mode 100644 index 000000000000..52bbdac168a9 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/predicates.go @@ -0,0 +1,27 @@ +package rolemanagementpolicyassignments + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type RoleManagementPolicyAssignmentOperationPredicate struct { + Id *string + Name *string + Type *string +} + +func (p RoleManagementPolicyAssignmentOperationPredicate) Matches(input RoleManagementPolicyAssignment) bool { + + if p.Id != nil && (input.Id == nil || *p.Id != *input.Id) { + return false + } + + if p.Name != nil && (input.Name == nil || *p.Name != *input.Name) { + return false + } + + if p.Type != nil && (input.Type == nil || *p.Type != *input.Type) { + return false + } + + return true +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/version.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/version.go new file mode 100644 index 000000000000..cb84f796c24b --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments/version.go @@ -0,0 +1,12 @@ +package rolemanagementpolicyassignments + +import "fmt" + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +const defaultApiVersion = "2020-10-01" + +func userAgent() string { + return fmt.Sprintf("hashicorp/go-azure-sdk/rolemanagementpolicyassignments/%s", defaultApiVersion) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 28c1bd10374e..b9a220473423 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -233,6 +233,8 @@ github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/role github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/roleeligibilityscheduleinstances github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/roleeligibilityschedulerequests github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/roleeligibilityschedules +github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicies +github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2020-10-01/rolemanagementpolicyassignments github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2022-04-01/roleassignments github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2022-04-01/roledefinitions github.com/hashicorp/go-azure-sdk/resource-manager/authorization/2022-05-01-preview/roledefinitions diff --git a/website/docs/d/role_management_policy.html.markdown b/website/docs/d/role_management_policy.html.markdown new file mode 100644 index 000000000000..0b91502764d6 --- /dev/null +++ b/website/docs/d/role_management_policy.html.markdown @@ -0,0 +1,138 @@ +--- +subcategory: "Authorization" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_role_management_policy" +description: |- + Get information about an Azure PIM Role Management Policy. +--- + +# Data Source: azurerm_role_management_policy + +Use this data source to get information on a role policy for an Azure Management Group, Subscription, Resource Group or resource. + +## Example Usage + +### Resource Group + +```terraform +data "azurerm_resource_group" "example" { + name = "example-rg" +} + +data "azurerm_role_definition" "rg_contributor" { + name = "Contributor" + scope = data.azurerm_resource_group.example.id +} + +data "azurerm_role_management_policy" "example" { + scope = data.azurerm_resource_group.test.id + role_definition_id = data.azurerm_role_definition.contributor.id +} +``` + +### Management Group + +```terraform +data "azurerm_management_group" "example" { + name = "example-group" +} + +data "azurerm_role_definition" "mg_contributor" { + name = "Contributor" + scope = azurerm_management_group.example.id +} + +data "azurerm_role_management_policy" "example" { + scope = data.azurerm_management_group.example.id + role_definition_id = data.azurerm_role_definition.mg_contributor.id +} +``` + +## Argument Reference + +* `role_definition_id` - (Required) The scoped Role Definition ID of the role for which this policy applies. +* `scope` - (Required) The scope to which this Role Management Policy applies. Can refer to a management group, a subscription or a resource group. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` (String) The ID of this policy. +* `name` (String) The name of this policy, which is typically a UUID and may change over time. +* `description` (String) The description of this policy. +* `activation_rules` - An `activation_rules` block as defined below. +* `active_assignment_rules` - An `active_assignment_rules` block as defined below. +* `eligible_assignment_rules` - An `eligible_assignment_rules` block as defined below. +* `notification_rules` - A `notification_rules` block as defined below. + +--- + +An `activation_rules` block returns the following: + +* `approval_stage` - An `approval_stage` block as defined below. +* `maximum_duration` - (String) The maximum length of time an activated role can be valid, in an ISO8601 Duration format. +* `require_approval` - (Boolean) Is approval required for activation. +* `require_justification` - (Boolean) Is a justification required during activation of the role. +* `require_multifactor_authentication` - (Boolean) Is multi-factor authentication required to activate the role. +* `require_ticket_info` - (Boolean) Is ticket information requrired during activation of the role. +* `required_conditional_access_authentication_context` - (String) The Entra ID Conditional Access context that must be present for activation. + +--- + +An `active_assignment_rules` block returns the following: + +* `expiration_required` - (Boolean) Must an assignment have an expiry date. +* `expire_after` - (String) The maximum length of time an assignment can be valid, as an ISO8601 duration. +* `require_justification` - (Boolean) Is a justification required to create new assignments. +* `require_multifactor_authentication` - (Boolean) Is multi-factor authentication required to create new assignments. +* `require_ticket_info` - (Boolean) Is ticket information required to create new assignments. + +--- + +An `approval_stage` block returns the following: + +* One or more `primary_approver` blocks as defined below. + +--- + +An `eligible_assignment_rules` block returns the following: + +* `expiration_required`- (Boolean) Must an assignment have an expiry date. +* `expire_after` - (String) The maximum length of time an assignment can be valid, as an ISO8601 duration. + +--- + +A `notification_rules` block returns the following: + +* `active_assignments` - A `notification_target` block as defined below with the details of notfications on active role assignments. +* `eligible_activations` - A `notification_target` block as defined below with the details of notifications on activation of eligible role. +* `eligible_assignments` - A `notification_target` block as defined below with the details of notifications on eligible role assignments. + +--- + +A `notification_settings` block returns the following: + +* `additional_recipients` - A list of additional email addresses that will receive these notifications. +* `default_recipients` - (Boolean) Should the default recipients receive these notifications. +* `notification_level` - (String) What level of notifications should be sent. Either `All` or `Critical`. + +--- + +A `notification_target` block returns the following: + +* `admin_notifications` - A `notification_settings` block as defined above. +* `approver_notifications` - A `notification_settings` block as defined above. +* `assignee_notifications` - A `notification_settings` block as defined above. + +--- + +A `primary_approver` block returns the following: + +* `object_id` - (String) The ID of the object which will act as an approver. +* `type` - (String) The type of object acting as an approver. Either `User` or `Group`. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/language/resources/syntax#operation-timeouts) for certain actions: + +* `read` - (Defaults to 5 minutes) Used when retrieving the Role Definition. diff --git a/website/docs/r/role_management_policy.html.markdown b/website/docs/r/role_management_policy.html.markdown new file mode 100644 index 000000000000..72f89ad1c071 --- /dev/null +++ b/website/docs/r/role_management_policy.html.markdown @@ -0,0 +1,221 @@ +--- +subcategory: "Authorization" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_role_management_policy" +description: |- + Manages Azure PIM Role Management Policies. +--- + +# Resource: azurerm_role_management_policy + +Manage a role policy for an Azure Management Group, Subscription, Resource Group or resource. + +## Example Usage + +### Resource Group + +```terraform +resource "azurerm_resource_group" "example" { + name = "example-rg" + location = "East US" +} + +data "azurerm_role_definition" "rg_contributor" { + name = "Contributor" + scope = azurerm_resource_group.example.id +} + +data "azuread_group" "approvers" { + name = "Example Approver Group" +} + +resource "azurerm_role_management_policy" "example" { + scope = azurerm_resource_group.test.id + role_definition_id = data.azurerm_role_definition.contributor.id + + active_assignment_rules { + expire_after = "P365D" + } + + eligible_assignment_rules { + expiration_required = false + } + + activation_rules { + maximum_duration = "PT1H" + require_approval = true + approval_stage { + primary_approver { + object_id = data.azuread_group.approvers.object_id + type = "Group" + } + } + } + + notification_rules { + eligible_assignments { + approver_notifications { + notification_level = "Critical" + default_recipients = false + additional_recipients = ["someone@example.com"] + } + } + eligible_activations { + assignee_notifications { + notification_level = "All" + default_recipients = true + additional_recipients = ["someone.else@example.com"] + } + } + } +} +``` + +### Management Group + +```terraform +resource "azurerm_management_group" "example" { + name = "example-group" +} + +data "azurerm_role_definition" "mg_contributor" { + name = "Contributor" + scope = azurerm_management_group.example.id +} + +resource "azurerm_role_management_policy" "example" { + scope = azurerm_management_group.example.id + role_definition_id = data.azurerm_role_definition.mg_contributor.id + + eligible_assignment_rules { + expiration_required = false + } + + active_assignment_rules { + expire_after = "P90D" + } + + activation_rules { + maximum_duration = "PT1H" + require_approval = true + } + + notification_rules { + active_assignments { + admin_notifications { + notification_level = "Critical" + default_recipients = false + additional_recipients = ["someone@example.com"] + } + } + } +} +``` + +## Argument Reference + +* `activation_rules` - (Optional) An `activation_rules` block as defined below. +* `active_assignment_rules` - (Optional) An `active_assignment_rules` block as defined below. +* `eligible_assignment_rules` - (Optional) An `eligible_assignment_rules` block as defined below. +* `notification_rules` - (Optional) A `notification_rules` block as defined below. +* `role_definition_id` - (Required) The scoped Role Definition ID of the role for which this policy will apply. Changing this forces a new resource to be created. +* `scope` - (Required) The scope to which this Role Management Policy will apply. Can refer to a management group, a subscription or a resource group. Changing this forces a new resource to be created. + +--- + +An `activation_rules` block supports the following: + +* `approval_stage` - (Optional) An `approval_stage` block as defined below. +* `maximum_duration` - (Optional) The maximum length of time an activated role can be valid, in an ISO8601 Duration format (e.g. `PT8H`). Valid range is `PT30M` to `PT23H30M`, in 30 minute increments, or `PT1D`. +* `require_approval` - (Optional) Is approval required for activation. If `true` an `approval_stage` block must be provided. +* `require_justification` - (Optional) Is a justification required during activation of the role. +* `require_multifactor_authentication` - (Optional) Is multi-factor authentication required to activate the role. Conflicts with `required_conditional_access_authentication_context`. +* `require_ticket_info` - (Optional) Is ticket information requrired during activation of the role. +* `required_conditional_access_authentication_context` - (Optional) The Entra ID Conditional Access context that must be present for activation. Conflicts with `require_multifactor_authentication`. + +--- + +An `active_assignment_rules` block supports the following: + +* `expiration_required` - (Optional) Must an assignment have an expiry date. `false` allows permanent assignment. +* `expire_after` - (Optional) The maximum length of time an assignment can be valid, as an ISO8601 duration. Permitted values: `P15D`, `P30D`, `P90D`, `P180D`, or `P365D`. +* `require_justification` - (Optional) Is a justification required to create new assignments. +* `require_multifactor_authentication` - (Optional) Is multi-factor authentication required to create new assignments. +* `require_ticket_info` - (Optional) Is ticket information required to create new assignments. + +One of `expiration_required` or `expire_after` must be provided. + +--- + +An `approval_stage` block supports the following: + +* One or more `primary_approver` blocks as defined below. + +--- + +An `eligible_assignment_rules` block supports the following: + +* `expiration_required`- Must an assignment have an expiry date. `false` allows permanent assignment. +* `expire_after` - The maximum length of time an assignment can be valid, as an ISO8601 duration. Permitted values: `P15D`, `P30D`, `P90D`, `P180D`, or `P365D`. + +One of `expiration_required` or `expire_after` must be provided. + +--- + +A `notification_rules` block supports the following: + +* `active_assignments` - (Optional) A `notification_target` block as defined below to configure notfications on active role assignments. +* `eligible_activations` - (Optional) A `notification_target` block as defined below for configuring notifications on activation of eligible role. +* `eligible_assignments` - (Optional) A `notification_target` block as defined below to configure notification on eligible role assignments. + +At least one `notification_target` block must be provided. + +--- + +A `notification_settings` block supports the following: + +* `additional_recipients` - (Optional) A list of additional email addresses that will receive these notifications. +* `default_recipients` - (Required) Should the default recipients receive these notifications. +* `notification_level` - (Required) What level of notifications should be sent. Options are `All` or `Critical`. + +--- + +A `notification_target` block supports the following: + +* `admin_notifications` - (Optional) A `notification_settings` block as defined above. +* `approver_notifications` - (Optional) A `notification_settings` block as defined above. +* `assignee_notifications` - (Optional) A `notification_settings` block as defined above. + +At least one `notification_settings` block must be provided. + +--- + +A `primary_approver` block supports the following: + +* `object_id` - (Required) The ID of the object which will act as an approver. +* `type` - (Required) The type of object acting as an approver. Possible options are `User` and `Group`. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` (String) The ID of this policy. +* `name` (String) The name of this policy, which is typically a UUID and may change over time. +* `description` (String) The description of this policy. + +## Import + +Because these policies are created automatically by Azure, they will auto-import on first use. They can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_role_management_policy.example "/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleManagementPolicies/00000000-0000-0000-0000-000000000000" +``` + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/language/resources/syntax#operation-timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the Role Definition. +* `update` - (Defaults to 30 minutes) Used when updating the Role Definition. +* `read` - (Defaults to 5 minutes) Used when retrieving the Role Definition. +* `delete` - (Defaults to 5 minutes) Used when deleting the Role Definition.