Skip to content

Commit

Permalink
fix: bug where set parameter names did not match referenced def (#127)
Browse files Browse the repository at this point in the history
* wip: casing bug

* feat: minor updates before merge

* test: implement known goo dtest data for example
  • Loading branch information
matt-FFFFFF authored Jul 4, 2024
1 parent 1c0d4be commit cafaed8
Show file tree
Hide file tree
Showing 295 changed files with 37,810 additions and 23 deletions.
3 changes: 1 addition & 2 deletions alzlib.go
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ func (az *AlzLib) getBuiltInPolicySets(ctx context.Context, names []string) erro

// Get the policy definitions for newly added policy set definitions.
defnames := make([]string, 0)
for _, name := range names {
for _, name := range processedNames {
name := name
refs, err := az.policySetDefinitions[name].PolicyDefinitionReferences()
if err != nil {
Expand All @@ -534,7 +534,6 @@ func (az *AlzLib) getBuiltInPolicySets(ctx context.Context, names []string) erro
if err := az.getBuiltInPolicies(ctx, defnames); err != nil {
return fmt.Errorf("Alzlib.getBuiltInPolicySets: error getting new built-in policy definitions referenced by policy sets: %w", err)
}

return nil
}

Expand Down
11 changes: 11 additions & 0 deletions assets/policyDefinition.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,17 @@ func (pd *PolicyDefinition) AssignPermissionsParameterNames() ([]string, error)
return names, nil
}

func (pd *PolicyDefinition) Parameter(name string) *armpolicy.ParameterDefinitionsValue {
if pd == nil || pd.Properties == nil || pd.Properties.Parameters == nil {
return nil
}
ret, ok := pd.Properties.Parameters[name]
if !ok {
return nil
}
return ret
}

// normalizeRoleDefinitionId takes a Azure builtin role definition id and returns a normalized id.
// This is one without the management group portion.
func normalizeRoleDefinitionId(id string) (string, error) {
Expand Down
21 changes: 20 additions & 1 deletion deployment/hierarchy.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/Azure/alzlib"
"github.com/Azure/alzlib/to"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
mapset "github.com/deckarep/golang-set/v2"
"github.com/google/uuid"
)
Expand Down Expand Up @@ -200,7 +201,7 @@ func (h *Hierarchy) addManagementGroup(ctx context.Context, req managementGroupA
}
mg.policyDefinitions[name] = newDef
}
// Copmbine all policy set definitions form all supplied archetypes into a single set
// Combine all policy set definitions form all supplied archetypes into a single set
allPolicySetDefinitions := mapset.NewThreadUnsafeSet[string]()
for _, archetype := range req.archetypes {
allPolicySetDefinitions = allPolicySetDefinitions.Union(archetype.PolicySetDefinitions)
Expand All @@ -218,6 +219,24 @@ func (h *Hierarchy) addManagementGroup(ctx context.Context, req managementGroupA
if err != nil {
return nil, fmt.Errorf("Hierarchy.AddManagementGroup(): policy assignment `%s` in management group `%s` does not exist in the library", name, req.id)
}
// Check if the referenced policy is a set and if its parameters match the parameters in the policy definitions
refPdId, _ := newpolassign.ReferencedPolicyDefinitionResourceId()
if refPdId.ResourceType.Type == "policySetDefinitions" {
psd, _ := h.alzlib.PolicySetDefinition(refPdId.Name)
rfs, _ := psd.PolicyDefinitionReferences()
for _, rf := range rfs {
resId, _ := arm.ParseResourceID(*rf.PolicyDefinitionID)
pd, err := h.alzlib.PolicyDefinition(resId.Name)
if err != nil {
return nil, fmt.Errorf("Hierarchy.AddManagementGroup(): policy definition `%s` in policy set definition `%s` in management group `%s` does not exist in the library", resId.Name, refPdId.Name, req.id)
}
for param := range rf.Parameters {
if pd.Parameter(param) == nil {
return nil, fmt.Errorf("Hierarchy.AddManagementGroup(): parameter `%s` in policy set definition `%s` does not match a parameter in referenced definition `%s` in management group `%s`", param, *psd.Name, *pd.Name, req.id)
}
}
}
}
mg.policyAssignments[name] = newpolassign
}

Expand Down
38 changes: 21 additions & 17 deletions deployment/managementgroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,10 @@ func (mg *HierarchyManagementGroup) generatePolicyAssignmentAdditionalRoleAssign
// get the role definition ids from the policy definition and add to the additional role assignment data
rdids, err := pd.NormalizedRoleDefinitionResourceIds()
if err != nil {
return fmt.Errorf("ManagementGroup.GeneratePolicyAssignmentAdditionalRoleAssignments: error getting role definition ids for policy definition `%s`: %w", *pd.Name, err)
return fmt.Errorf("ManagementGroup.GeneratePolicyAssignmentAdditionalRoleAssignments: assignment `%s`, error getting role definition ids for policy definition `%s`: %w", paName, *pd.Name, err)
}
if len(rdids) == 0 {
return fmt.Errorf("ManagementGroup.GeneratePolicyAssignmentAdditionalRoleAssignments: policy definition `%s` has no role definition ids", *pd.Name)
return fmt.Errorf("ManagementGroup.GeneratePolicyAssignmentAdditionalRoleAssignments: assignment `%s`, policy definition `%s` has no role definition ids", paName, *pd.Name)
}
for _, rdid := range rdids {
mg.policyRoleAssignments.Add(PolicyRoleAssignment{
Expand Down Expand Up @@ -227,27 +227,27 @@ func (mg *HierarchyManagementGroup) generatePolicyAssignmentAdditionalRoleAssign
case "policySetDefinitions":
psd, err := mg.hierarchy.alzlib.PolicySetDefinition(policyDefinitionRef.Name)
if err != nil {
return fmt.Errorf("ManagementGroup.GeneratePolicyAssignmentAdditionalRoleAssignments: policy set definition `%s`, referenced by `%s` not found in AlzLib", policyDefinitionRef.Name, paName)
return fmt.Errorf("ManagementGroup.GeneratePolicyAssignmentAdditionalRoleAssignments: assignment `%s`, policy set `%s`, referenced by `%s` not found in AlzLib", paName, *psd.Name, paName)
}
pdRefs, err := psd.PolicyDefinitionReferences()
if err != nil {
return fmt.Errorf("ManagementGroup.GeneratePolicyAssignmentAdditionalRoleAssignments: error getting referenced policy definition names for policy set definition %s: %w", *psd.Name, err)
return fmt.Errorf("ManagementGroup.GeneratePolicyAssignmentAdditionalRoleAssignments: assignment `%s`, error getting referenced policy definition names for policy set definition %s: %w", paName, *psd.Name, err)
}
// for each policy definition in the policy set definition
for _, pdRef := range pdRefs {
pdName, err := assets.NameFromResourceId(*pdRef.PolicyDefinitionID)
if err != nil {
return fmt.Errorf("ManagementGroup.GeneratePolicyAssignmentAdditionalRoleAssignments: error getting policy definition name from id `%s`: %w", *pdRef.PolicyDefinitionID, err)
return fmt.Errorf("ManagementGroup.GeneratePolicyAssignmentAdditionalRoleAssignments: assignment `%s`, error getting policy definition name from policy set definition `%s`, with id `%s`: %w", paName, *psd.Name, *pdRef.PolicyDefinitionID, err)
}
pd, err := mg.hierarchy.alzlib.PolicyDefinition(pdName)
if err != nil {
return fmt.Errorf("ManagementGroup.GeneratePolicyAssignmentAdditionalRoleAssignments: policy definition `%s`, referenced by `%s` not found in AlzLib", pdName, *psd.Name)
return fmt.Errorf("ManagementGroup.GeneratePolicyAssignmentAdditionalRoleAssignments: assignment `%s`, policy definition `%s`, referenced by `%s` not found in AlzLib", paName, pdName, *psd.Name)
}

// get the role definition ids from the policy definition and add to the additional role assignment data
rdids, err := pd.NormalizedRoleDefinitionResourceIds()
if err != nil {
return fmt.Errorf("ManagementGroup.GeneratePolicyAssignmentAdditionalRoleAssignments: error getting role definition ids for policy definition %s: %w", pdName, err)
return fmt.Errorf("ManagementGroup.GeneratePolicyAssignmentAdditionalRoleAssignments: assignment `%s`, error getting role definition ids referenced in policy set `%s` for policy definition %s: %w", paName, *psd.Name, pdName, err)
}
for _, rdid := range rdids {
mg.policyRoleAssignments.Add(PolicyRoleAssignment{
Expand All @@ -267,12 +267,16 @@ func (mg *HierarchyManagementGroup) generatePolicyAssignmentAdditionalRoleAssign
}
// get the parameter value from the policy reference within the set definition
if _, ok := pd.Properties.Parameters[paramName]; !ok {
return fmt.Errorf("ManagementGroup.GeneratePolicyAssignmentAdditionalRoleAssignments: parameter `%s` not found in policy definition `%s`", paramName, *pd.Name)
return fmt.Errorf("ManagementGroup.GeneratePolicyAssignmentAdditionalRoleAssignments: assignment `%s` for policy set `%s`, parameter `%s` not found in refernced policy definition `%s`", paName, *psd.Name, paramName, *pd.Name)
}
pdrefParamVal := pdRef.Parameters[paramName].Value
pdrefParam, ok := pdRef.Parameters[paramName]
if !ok {
return fmt.Errorf("ManagementGroup.GeneratePolicyAssignmentAdditionalRoleAssignments: assignment `%s` for policy set `%s`, parameter `%s` not found in policy definition reference `%s`", paName, *psd.Name, paramName, *pdRef.PolicyDefinitionID)
}
pdrefParamVal := pdrefParam.Value
pdrefParamValStr, ok := pdrefParamVal.(string)
if !ok {
return fmt.Errorf("ManagementGroup.GeneratePolicyAssignmentAdditionalRoleAssignments: parameter `%s` value in policy definition `%s` is not a string", paramName, *pd.Name)
return fmt.Errorf("ManagementGroup.GeneratePolicyAssignmentAdditionalRoleAssignments: assignment `%s` for policy set `%s`, parameter `%s` value in policy definition `%s` is not a string", paName, *psd.Name, paramName, *pd.Name)
}
// extract the assignment exposed policy set parameter name from the ARM function used in the policy definition reference
paParamName, err := extractParameterNameFromArmFunction(pdrefParamValStr)
Expand Down Expand Up @@ -399,19 +403,19 @@ func updatePolicyDefinitions(mg *HierarchyManagementGroup) {
// If it is found, the definition reference id is re-written with the correct management group name.
// If it is not found, we assume that it's built-in.
func updatePolicySetDefinitions(mg *HierarchyManagementGroup, pd2mg map[string]string) error {
for k, psd := range mg.policySetDefinitions {
psd.ID = to.Ptr(fmt.Sprintf(PolicySetDefinitionIdFmt, mg.id, k))
for psdName, psd := range mg.policySetDefinitions {
psd.ID = to.Ptr(fmt.Sprintf(PolicySetDefinitionIdFmt, mg.id, psdName))
refs, err := psd.PolicyDefinitionReferences()
if err != nil {
return fmt.Errorf("updatePolicySetDefinitions: error getting policy definition references for policy set definition %s: %w", k, err)
return fmt.Errorf("updatePolicySetDefinitions: error getting policy definition references for policy set definition %s: %w", psdName, err)
}
for _, pd := range refs {
pdname, err := assets.NameFromResourceId(*pd.PolicyDefinitionID)
for _, pdr := range refs {
pdname, err := assets.NameFromResourceId(*pdr.PolicyDefinitionID)
if err != nil {
return fmt.Errorf("updatePolicySetDefinitions: error getting policy definition name from resource id %s: %w", *pd.PolicyDefinitionID, err)
return fmt.Errorf("updatePolicySetDefinitions: error getting policy definition name from resource id %s: %w", *pdr.PolicyDefinitionID, err)
}
if mgname, ok := pd2mg[pdname]; ok {
pd.PolicyDefinitionID = to.Ptr(fmt.Sprintf(PolicyDefinitionIdFmt, mgname, pdname))
pdr.PolicyDefinitionID = to.Ptr(fmt.Sprintf(PolicyDefinitionIdFmt, mgname, pdname))
}
}
}
Expand Down
13 changes: 10 additions & 3 deletions integrationtest/examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
)

const (
alzLibraryTag = "2024.03.03"
alzLibraryTag = "2024.07.01"
alzLibraryMember = "platform/alz"
)

Expand All @@ -35,12 +35,13 @@ func Example_deploymentNewHierarchy() {
return
}
az.AddPolicyClient(cf)
dirfs, err := alzlib.FetchAzureLandingZonesLibraryMember(ctx, alzLibraryMember, alzLibraryTag, "alz")
//dirFs, err := alzlib.FetchAzureLandingZonesLibraryMember(ctx, alzLibraryMember, alzLibraryTag, "alz")
dirFs, err := alzlib.FetchLibraryByGetterString(ctx, "testdata/alzlib-2024-07-01", "alz")
if err != nil {
fmt.Println(err)
return
}
err = az.Init(ctx, dirfs)
err = az.Init(ctx, dirFs)
if err != nil {
fmt.Println(err)
return
Expand All @@ -49,6 +50,12 @@ func Example_deploymentNewHierarchy() {
err = h.FromArchitecture(ctx, "alz", "00000000-0000-0000-0000-000000000000", "testlocation")
if err != nil {
fmt.Println(err)
return
}
_, err = h.PolicyRoleAssignments(ctx)
if err != nil {
fmt.Println(err)
return
}
mgs := h.ManagementGroupNames()
slices.Sort(mgs)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "connectivity",
"policy_assignments": [
"Enable-DDoS-VNET"
],
"policy_definitions": [],
"policy_set_definitions": [],
"role_definitions": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "corp",
"policy_assignments": [
"Audit-PeDnsZones",
"Deny-HybridNetworking",
"Deny-Public-Endpoints",
"Deny-Public-IP-On-NIC",
"Deploy-Private-DNS-Zones"
],
"policy_definitions": [],
"policy_set_definitions": [],
"role_definitions": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "decommissioned",
"policy_assignments": [
"Enforce-ALZ-Decomm"
],
"policy_definitions": [],
"policy_set_definitions": [],
"role_definitions": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "identity",
"policy_assignments": [
"Deny-MgmtPorts-Internet",
"Deny-Public-IP",
"Deny-Subnet-Without-Nsg",
"Deploy-VM-Backup"
],
"policy_definitions": [],
"policy_set_definitions": [],
"role_definitions": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "landing_zones",
"policy_assignments": [
"Audit-AppGW-WAF",
"Deny-IP-forwarding",
"Deny-MgmtPorts-Internet",
"Deny-Priv-Esc-AKS",
"Deny-Privileged-AKS",
"Deny-Storage-http",
"Deny-Subnet-Without-Nsg",
"Deploy-AKS-Policy",
"Deploy-AzSqlDb-Auditing",
"Deploy-MDFC-DefSQL-AMA",
"Deploy-SQL-TDE",
"Deploy-SQL-Threat",
"Deploy-VM-Backup",
"Deploy-VM-ChangeTrack",
"Deploy-VM-Monitoring",
"Deploy-vmArc-ChangeTrack",
"Deploy-vmHybr-Monitoring",
"Deploy-VMSS-ChangeTrack",
"Deploy-VMSS-Monitoring",
"Enable-AUM-CheckUpdates",
"Enable-DDoS-VNET",
"Enforce-AKS-HTTPS",
"Enforce-ASR",
"Enforce-GR-KeyVault",
"Enforce-TLS-SSL-H224"
],
"policy_definitions": [],
"policy_set_definitions": [],
"role_definitions": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "management",
"policy_assignments": [
"Deploy-Log-Analytics"
],
"policy_definitions": [],
"policy_set_definitions": [],
"role_definitions": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "online",
"policy_assignments": [],
"policy_definitions": [],
"policy_set_definitions": [],
"role_definitions": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "platform",
"policy_assignments": [
"DenyAction-DeleteUAMIAMA",
"Deploy-MDFC-DefSQL-AMA",
"Deploy-VM-ChangeTrack",
"Deploy-VM-Monitoring",
"Deploy-vmArc-ChangeTrack",
"Deploy-vmHybr-Monitoring",
"Deploy-VMSS-ChangeTrack",
"Deploy-VMSS-Monitoring",
"Enable-AUM-CheckUpdates",
"Enforce-ASR",
"Enforce-GR-KeyVault"
],
"policy_definitions": [],
"policy_set_definitions": [],
"role_definitions": []
}
Loading

0 comments on commit cafaed8

Please sign in to comment.