Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 37 additions & 6 deletions internal/services/policies/policies.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ import (

"github.com/hashicorp/go-azure-helpers/lang/pointer"
"github.com/hashicorp/go-azure-sdk/microsoft-graph/policies/stable/rolemanagementpolicyassignment"
"github.com/hashicorp/terraform-provider-azuread/internal/helpers/consistency"
"github.com/hashicorp/terraform-provider-azuread/internal/sdk"
"github.com/hashicorp/terraform-provider-azuread/internal/services/policies/parse"
)

// There isn't a reliable way to get the policy ID from the policy API, as the policy ID changes with each modification
func getPolicyId(ctx context.Context, metadata sdk.ResourceMetaData, scopeId, roleDefinitionId string) (*parse.RoleManagementPolicyId, error) {

// tryGetPolicyId attempts to fetch the policy ID, returning false if not yet available
func tryGetPolicyId(ctx context.Context, metadata sdk.ResourceMetaData, scopeId, roleDefinitionId string) (*parse.RoleManagementPolicyId, bool, error) {
client := metadata.Client.Policies.RoleManagementPolicyAssignmentClient

options := rolemanagementpolicyassignment.ListRoleManagementPolicyAssignmentsOperationOptions{
Expand All @@ -23,21 +26,49 @@ func getPolicyId(ctx context.Context, metadata sdk.ResourceMetaData, scopeId, ro

resp, err := client.ListRoleManagementPolicyAssignments(ctx, options)
if err != nil {
return nil, fmt.Errorf("could not list existing policy assignments: %v", err)
return nil, false, fmt.Errorf("could not list existing policy assignments: %v", err)
}

assignments := resp.Model
if assignments == nil {
return nil, fmt.Errorf("could not list existing policy assignments: model was nil")
return nil, false, fmt.Errorf("could not list existing policy assignments: model was nil")
}

// Not yet available - return false instead of error
if len(*assignments) == 0 {
return nil, false, nil
}

if len(*assignments) != 1 {
return nil, fmt.Errorf("got the wrong number of policy assignments: expected 1, got %d", len(*assignments))
return nil, false, fmt.Errorf("got the wrong number of policy assignments: expected 1, got %d", len(*assignments))
}

assignmentId, err := parse.ParseRoleManagementPolicyAssignmentID(pointer.From((*assignments)[0].Id))
if err != nil {
return nil, fmt.Errorf("parsing policy assignment ID: %v", err)
return nil, false, fmt.Errorf("parsing policy assignment ID: %v", err)
}

policyId := parse.NewRoleManagementPolicyID(assignmentId.ScopeType, assignmentId.ScopeId, assignmentId.PolicyId)
return policyId, true, nil
}

// getPolicyId reliably fetches the policy ID, waiting for eventual consistency
func getPolicyId(ctx context.Context, metadata sdk.ResourceMetaData, scopeId, roleDefinitionId string) (*parse.RoleManagementPolicyId, error) {
var policyId *parse.RoleManagementPolicyId
err := consistency.WaitForUpdate(ctx, func(ctx context.Context) (*bool, error) {
id, exists, err := tryGetPolicyId(ctx, metadata, scopeId, roleDefinitionId)
if err != nil {
return nil, err
}
if exists {
policyId = id
}
return &exists, nil
})

if err != nil {
return nil, fmt.Errorf("waiting for policy assignment to become available: %v", err)
}

return parse.NewRoleManagementPolicyID(assignmentId.ScopeType, assignmentId.ScopeId, assignmentId.PolicyId), nil
return policyId, nil
}
Loading