Policy Assignment File Folder Structure Guidelines
Assignment scopes and excluded scopes.
- CSV Assignment Parameters
- Policy Exemptions
Policy Assignments
This chapter describes how Policy Assignments are handled by EPAC. Policy Assignments are the actual assignments of Policies and Policy Sets to scopes in Azure.
Assignment JSON structure
Assignment JSON is hierarchical for efficient definitions, avoiding duplication (copy/paste) of JSON. Each branch of the tree is cumulative. Each tree node must include a nodeName - an arbitrary string exclusively used by EPAC to display an error location. EPAC concatenates a leading / and the nodeName entries encountered in the tree to create a "breadcrumbs" trail; therefore, we recommend that you use / to help separate the concatenated nodeName . The following partial and invalid assignment tree would create this error message.
JSON Schema
The GitHub repo contains a JSON schema which can be used in tools such as VS Code to provide code completion.
To utilize the schema add a $schema tag to the JSON file.
In any EPAC deployment you will have a number of assignment files. When a deployment plan is built EPAC does a recursive search for all the files in the policyAssignments folder. This means that you are free to use any folder structure you think is appropriate to help organise the files. For example if you have a multi-tenant or multi-environment setup you might choose to create folders representing each tenant or environment and then store the assignment files for each environment in that folder.
- Every tree branch must accumulate a definitionEntry (or definitionEntryList ), Assignment naming ( name and displayName ) and scope element.
- The elements parameters , overrides , resourceSelectors , notScope , enforcementMode , metadata , userAssignedIdentity , managedIdentityLocations , additionalRoleAssignments and nonComplianceMessages are optional.
- For Policy Sets with large numbers of included Policies you should use a spreadsheet (CSV file) to manage effects (parameterized or effect overrides ), parameters and optional nonComplianceMessages . We recommend the CSV approach for Policy Sets with more than 10 included Policies.
- EPAC continues to support deprecated elements initiativeId , initiativeName and ignoreBranch , Consider using their replacements policySetId , policySetName and enforcementMode instead.
- Role Assignments for user-assigned Managed Identities (UAMI) are not managed by EPAC, and will not generate a roles-plan.json file.
- additionalRoleAssignments are used when a resource required is not in the current scope. For example, a Policy Assignment that requires a Event Hub to be managed in a subscription not contained in the current management group.
The tree is not required to be balanced. The number of levels is not restricted; however, anything beyond 3 levels is unnecessary in real scenarios and would be difficult to read and manage as the depth increases.
Assignment Element and Metadata
Each Assignment is required to have a name which is used in its resource Id. EPAC also requires a displayName . The description is optional. For the allowed location assignment you specify the component with:
Multiple assignment naming components in a tree branch are string concatenated for each of the three fields.
Azure has a limit of 24 characters for the concatenated name string. EPAC displays an error if this limit is exceeded. Azure also has a limit of 128 characters for displayName and 512 characters for description (For additional information see Assignment Structure: Display name and description ).
Defining metadata
metadata is sometimes used to assign categories for changes. Do NOT specify EPAC-reserved elements roles and pacOwnerId . For the final metadata EPAC creates the union of instances in the entire tree branch.
Not recommended : Adding assignedBy to the metadata overrides the deployedBy value from the global-settings.jsonc file normally used for assignedBy . It defaults to "epac/$pacOwnerId/$pacSelector" .
Metadata for Role Assignments
Role assignments do not contain a metadata field. Instead, the description field is used to populate the deployedBy value. The description field is populated with the Policy Assignment Id, reason and deployedBy value. This is useful for tracking the source of the Role Assignment.
Reasons is one of:
- Role Assignment required by Policy - Policy definition(s) specify the required Role Definition Ids.
- additional Role Assignment - from filed "additionalRoleAssignments" in the Policy Assignment file.
- additional cross tenant Role Assignment - from filed "additionalRoleAssignments" with crossTenant set to $true in the Policy Assignment file.
Assigning Policy Sets or Policies
Assigning a single policy or policy set.
Each assignment assigns either a Policy or Policy Set. In EPAC this is done with a definitionEntry or a definitionEntryList . Exactly one occurrence must exist in any collated tree branch. For each entry, you need to specify one of the following:
- policyName - custom Policy. Specifying just the name allows EPAC to inject the correct definition scope.
- policySetName - custom Policy Set. Specifying just the name allows EPAC to inject the correct definition scope
- policyId - resource id for builtin Policy.
- policySetId - resource id for builtin Policy Set.
displayName is an optional field to document the entry if the Policy name is a GUID. Builtin Policies and Policy Sets use a GUID.
Assigning multiple Policies or Policy Sets
Using definitionEntryList allows you to save on copy/paste tree branches. Without it, the number of branches would need to be duplicated as many times as the list has entries.
Each entry in the list creates an Assignment at each leaf of the tree. Since assignments must have unique names at a specific scope, the Assignment naming component must be amended for each list entry. In this sub-component you can decide if you want to concatenate the string by appending or prepending them by specifying append boolean value.
In the above example one of the children (leaf node) has the following Assignment name.
This example generates two assignments at the "prod" leaf per scope:
- /providers/Microsoft.Management/managementGroups/ Contoso-Prod /providers/Microsoft.Authorization/policyAssignments/ pr-asb
- displayName = "Prod Azure Security Benchmark"
- description = "Prod Environment controls enforcement with Azure Security Benchmark Initiative."
- /providers/Microsoft.Management/managementGroups/ Contoso-Prod /providers/Microsoft.Authorization/policyAssignments/ pr-nist-800-53-r5
- displayName = "Prod NIST SP 800-53 Rev. 5"
- description = "Prod Environment controls enforcement with NIST SP 800-53 Rev. 5 Initiative."
scope is required exactly once in each tree branch. Excluded scopes ( notScope ) are cumulative from global-settings.json and the entire tree branch; however, once a scope is defined notScopes may not be defined at any child node.
Both scope and notScopes are specific to an EPAC Environment using the pacSelector name , e.g., epac-dev and tenant .
notScopes works the same. In addition "*" means all EPAC Environments.
Managed Identities and role assignments
Policies with a DeployIfNotExists or Modify effect need a Managed Identity (MI) and role assignments to execute remediation tasks. EPAC calculates the necessary role assignments based on the roleDefinitionIds in the policy definition. By default EPAC uses a system-assigned Managed Identity. The team maintaining EPAC recommend using system-assigned identities; however, your organization may have role assignment reasons to use user-assigned Managed Identities.
Defining managedIdentityLocations
Policy assignments requiring a Managed Identity (system-assigned or user-assigned) require a location managedIdentityLocations . You must specify the location based on EPAC Environment or use "*" to use the same location for all of the EPAC Environments. You can specify them in global-settings.jsonc or at any node in the tree. The last (closest to the leaf node) is the one chosen if multiple managedIdentityLocations entries are encountered in a tree branch.
Defining optional additionalRoleAssignments
In some scenarios you will need additionalRoleAssignments ; e.g., for diagnostics settings to Event Hubs, the target resource might be in a different Management Group and therefore the Managed Identity requires additional role assignments. You must specify the additionalRoleAssignments based on EPAC Environment or use "*" to use the same additionalRoleAssignments for all of the EPAC Environments. If the pacEnvironment under deployment is specified in the additionalRoleAssignments, the "*" assignments will be ignored.
If the additional assignment is to made to a managing tenant in the scenario where the pacEnvironment under deployment is a managed (Azure Lighthouse) tenant, you must specify ""crossTenant": true" for that assignment. Ensure all necessary ABAC permissions are in place for the executing SPN.
User-assigned Managed Identities
Azure Policy can use a user-defined Managed Identity and EPAC allows you to use this functionality. You must specify the user-defined Managed Identity based on EPAC Environment or use "*" to use the same identity for all of the EPAC Environments (only possible in single tenant scenarios). Within each EPAC Environment entry, you can specify just the URI string indicating to use the same identity even if we are using a definitionEntryList , or in the case of a definitionEntryList can assign a different identity based on the definitionEntryList by specifying a matching policyName , policyId , policySetName or policySetId .
Defining parameters , overrides and nonComplianceMessages
Utilizing a csv file to define parameters , overrides and noncompliancemessages.
Assigning single or multiple security and compliance focused Policy Sets (Initiatives), such as Microsoft Cloud Security Benchmark, NIST 800-53 R5, PCI, NIST 800-171, etc, with just JSON parameters becomes very complex. Add to this the complexity of overriding the effect if it is not surfaced as a parameter in the Policy Set . Finally, adding the optional nonComplianceMessages further increases the complexity.
To address the problem of reading and maintaining hundreds or thousands of JSON lines, EPAC can use the content of a CSV file to create parameters , overrides and optionally nonComplianceMessages for a single Policy assignment definitionEntry or multiple Policy definitions ( definitionEntryList ).
This approach is best for large Policy Sets such as Azure Security Benchmark, NIST 800-53, etc. Smaller Policy Sets should still be handled with JSON parameters , overrides and nonComplianceMessages .
Implement these steps as documented in Managing Policy Assignment Parameters with a CSV file .
- Generate the CSV file from your already deployed Assignment(s) or Policy Set(s).
- Modify the effect and parameter columns for each type of environment type you will use.
- Modify the Policy Assignment file to reference the CSV file and the column prefix.
- Update the CSV file with the new effect and parameter values.
Defining parameters with JSON
parameters have a simplified JSON structure. You do not need the additional value indirection that Azure requests (EPAC will inject that indirection).
To enable definitionEntryList , parameters not present in the Policy or Policy Set definition are quietly ignored.
Advanced Elements
Defining overrides with json.
overrides are in the same format as documented by Azure . They are cumulative in each tree branch. The selectors element is only used for Assignments of Policy Sets. They are not valid for Assignments of a single Policy.
If using definitionEntryList , you must add the policyName , policyId , policySetName or policySetId as used in the definitionEntryList item.
Defining nonComplianceMessages with JSON
Assign a non-compliance message to the assignment, or individual non-compliance messages if the assignment is for an Policy Set. This value is an array of objects - each containing a message, and in the case of an initiative a policyDefinitionReferenceId. See this link for details.
If you use single definitionEntry , place them normally. If you use a definitionEntryList place them in the respective list entry.
Defining resourceSelectors
resourceSelectors may appear anywhere in the tree and are cumulative in any branch. They follow the standard Azure Format .
Defining enforcementMode
enforcementMode is similar to the deprecated ignoreBranch ; it deploys the assignment and sets the assignment to Default or DoNotEnforce . DoNotEnforce allows a what-if analysis. enforcementMode may appear anywhere in the tree. Definitions at a child override the previous setting.
Example assignment files
Simple policy assignment (allowed locations).
In the simple case an assignment is a single node with no difference in assignment , parameters , and definitionEntry across multiple scopes. In many scenarios "Allowed Locations" is such a simple Assignment. Such Assignments do not have child nodes, just the root node. Example
- nodeName is required for error messages; its value is immaterial. EPAC concatenates them in the current tree branch.
- definitionEntry specifies that the custom Policy Set general-allowed-locations-policy-set from our starter kit. displayName has no meaning - it is for readability and in this instance is superfluous.
- assignment fields name , displayName and description are used when creating the assignment.
- This assignment has no metadata . You don't need an empty collection. EPAC will add pacOwnerId and roles metadata . Do not add them manually.
- enforcementMode is set to default - it is superfluous.
- parameters are obvious. Note: you don't add the value layer Azure inserts - EPAC takes care of that.
- During Policy resource development (called epac-dev ) the Assignment is deployed to an EPAC development Management Group Epac-Mg-1 .
- During Policy prod deployments ( tenant -wide), it is deployed to the tenant Management Group Epac-Mg-1 .
- No notScope entries are specified.
Security-Focused Policy Assignment with JSON parameters
- In the following example we named our root node ( nodeName ) /security/ . Since it is only used in case of error messages produced by EPAC during planning its actual value doesn't matter as long as its unique.
- We use a definitionEntryList to create two assignments at every leaf (six assignments total).
- For assignment string concatenation we append the strings in the definitionEntryList to the strings in the child nodes. You can see this best when you look at the description string in the child nodes. It will form a sentence when concatenated by append ing the definitionEntryList assignment field description .
- The parameters specified in the children are specific to the IaC environment types and their scope . Note: a real assignment would define many more parameters. The set here is abbreviated since the actual set could easily exceed a hundred entries for each of the IaC environments. We'll see in the next example how to simplify large Policy Set parameters with a CSV file.
Inverted Policy Assignment (Tag Inheritance and Required Tags)
As mentioned above sometimes it is advantageous (to reduce the number of repetitions) to turn a definition on its head:
- Common parameters , scope , definitionEntryList (with two Policies) at the root ( nodeName is /Tags/ ).
- Start of the assignment strings ( append is defaulted to false ). Again look at description which will be a concatenated sentence.
- The children define the tagName parameter and the second part of the strings for assignment . The set of parameters is the union of the root node and the child node.
- This creates six Assignments (number of Policies assigned times number of children).
Non-Compliance Messages in a Policy Definition Assignment
Non-compliance messages in a policy set definition assignment, non-compliance messages in a policy set definition assignment with a definitionentrylist.
IMAGES
VIDEO