Skip to content

Commit

Permalink
Document enhancement features (#741)
Browse files Browse the repository at this point in the history
Co-authored-by: Anthony Watherston <[email protected]>
  • Loading branch information
anwather and Anthony Watherston authored Sep 6, 2024
1 parent 3a60da8 commit 91b6ca2
Show file tree
Hide file tree
Showing 11 changed files with 356 additions and 18 deletions.
4 changes: 4 additions & 0 deletions Docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

Enterprise Azure Policy as Code (EPAC for short) is a number of PowerShell scripts which can be used in CI/CD based system or a semi-automated use to deploy Policies, Policy Sets, Policy Assignments, Policy Exemptions and Role Assignments. It also contains operational scripts to simplify operational tasks.

## Latest Updates

For all EPAC changes and newest updates, please visit our [GitHub Releases Page](https://github.com/Azure/enterprise-azure-policy-as-code/releases).

> [!CAUTION]
> Review the Breaking changes in v10.0.0 carefully to avoid issues with your EPAC instance. The changes are [documented here](start-changes.md#breaking-changes-in-v1000).
Expand Down
65 changes: 53 additions & 12 deletions Docs/operational-scripts-documenting-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,15 @@ Each file must contain one or both documentation topics. This example file in th
{
"fileNameStem": "contoso-policy-effects-across-environments",
"environmentCategories": [], // when using 'documentAllAssignments', this value will be overwritten
"title": "Contoso Policy effects"
"title": "Contoso Policy effects",
"markdownAdoWiki": true,
"markdownAdoWikiConfig": [
{
"adoOrganization": "MyOrganization",
"adoProject": "EPAC",
"adoWiki": "EPAC"
}
]
}
]
},
Expand Down Expand Up @@ -154,20 +162,28 @@ Each file must contain one or both documentation topics. This example file in th
"id": "/providers/Microsoft.Management/managementGroups/Contoso-Dev/providers/Microsoft.Authorization/policyAssignments/prod-org"
}
]
},
],
"documentationSpecifications": [
{
"fileNameStem": "contoso-policy-effects-across-environments",
"environmentCategories": [
"prod",
"test",
"dev"
],
"title": "Contoso Policy effects"
}
]
},
"documentationSpecifications": [
{
"fileNameStem": "contoso-policy-effects-across-environments",
"environmentCategories": [
"prod",
"test",
"dev"
],
"title": "Contoso Policy effects",
"markdownAdoWiki": true,
"markdownAdoWikiConfig": [
{
"adoOrganization": "MyOrganization",
"adoProject": "EPAC",
"adoWiki": "EPAC"
}
]
}
],
"documentPolicySets": [
{
"pacEnvironment": "tenant",
Expand Down Expand Up @@ -219,6 +235,31 @@ Markdown processors vary slightly. This shipt has settings to tune the output to
"markdownAdoWiki": true, // default is false, set to true to format headings for Azure DevOps Wiki and generate a table of contents
```

### Automating Azure DevOps Wiki Markdown

- EPAC can be used to automate the population of your Azure DevOps Wiki pages with the generated markdown files. To do this, you must call "Build-PolicyDocumentation" with the parameter "WikiClonePat". The value of the parameter should be the name of the Personal Access Token (PAT) set in your pipeline variable. Example:

```
Build-PolicyDocumentation.ps1 -WikiClonePat $(WikiClonePat)
```
- This PAT only requires "Read & write" permissions for "Code", as it will modify and push these markdown files to your Wiki. For more information please see ["Azure DevOps: Use personal access tokens"](https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=Windows)
- In order for your EPAC to reach your Wiki, you must configure the "markdownAdoWikiConfig" property within your policyDeocumention file.
- **adoOrganization**: Name of your ADO Organization
- **adoProject**: Name of your ADO Project
- **adoWiki**: Name of your Wiki (If Wiki was not manually set up, it will be created for you based on the name given here)

```jsonc
"markdownAdoWikiConfig": [
{
"adoOrganization": "MyOrganization",
"adoProject": "EPAC",
"adoWiki": "EPAC"
}
]
```

- For a full implementation using an example pipeline, please see ["EPAC GitHub: epac-dev-pipeline-with-adowiki.yml"](https://github.com/Azure/enterprise-azure-policy-as-code/blob/main/StarterKit/Pipelines/GitHubActions/GitHub-Flow-With-ADOWiki/epac-dev-pipeline-with-adowiki.yml)

### Embedded HTML in Markdown Tables

EPAC uses embedded HTML to format Markdown tables. Some Markdown processors, such as SharePoint, do not recognize embedded HTML. Setting `markdownNoEmbeddedHtml` to `true` emits commas `, ` instead of the HTML tag `<br/>`.
Expand Down
46 changes: 44 additions & 2 deletions Scripts/Helpers/Out-DocumentationForPolicyAssignments.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ function Out-DocumentationForPolicyAssignments {
$DocumentationSpecification,
[hashtable] $AssignmentsByEnvironment,
[switch] $IncludeManualPolicies,
[hashtable] $PacEnvironments
[hashtable] $PacEnvironments,
[string] $WikiClonePat
)

[string] $fileNameStem = $DocumentationSpecification.fileNameStem
Expand Down Expand Up @@ -587,5 +588,46 @@ function Out-DocumentationForPolicyAssignments {
}

#endregion csv


#region PushToWiki
if ($DocumentationSpecification.markdownAdoWikiConfig) {
if ($WikiClonePat -eq "") {
Write-Error "PAT Token not found! Please pass as parameter 'WikiClonePat'!"
Exit 1
}
Write-Information "Attempting push to Azure DevOps Wiki"
# Clone down wiki
git clone "https://$($WikiClonePat):x-oauth-basic@$($DocumentationSpecification.markdownAdoWikiConfig.adoOrganization).visualstudio.com/$($DocumentationSpecification.markdownAdoWikiConfig.adoProject)/_git/$($DocumentationSpecification.markdownAdoWikiConfig.adoWiki).wiki"
# Move into folder
Set-Location -Path "$($DocumentationSpecification.markdownAdoWikiConfig.adoWiki).wiki"
$branch = git branch
$branch = $branch.split(" ")[1]
# Copy main markdown file into wiki
Copy-Item -Path "../$OutputPath/$($DocumentationSpecification.fileNameStem).md"
# Configure dummy email and user (required)
git config user.email "[email protected]"
git config user.name "EPAC Wiki"
# Add changes to commit
git add .
# Check if a folder exist that holds the sub pages
if (-not (Test-Path -Path "$($DocumentationSpecification.fileNameStem)")) {
# Create folder if does not exist
New-Item -Path "$($DocumentationSpecification.fileNameStem)" -ItemType Directory
}
# Copy all individual services markdown files
$services = Get-ChildItem -Path "../$OutputPathServices"
# Move into folder
Set-Location -Path "$($DocumentationSpecification.fileNameStem)"
# Remove files that currently exist in file to ensure fresh updates
Get-ChildItem -Path . -File | Remove-Item
# Copy over new individual services markdown files
foreach ($file in $services) {
Copy-Item $file .
}
# Commit and push up to Wiki
git add .
git commit -m "Update wiki with the latest markdown files"
git push origin "$branch"
Set-Location "../../"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,8 @@ function Set-AzRoleAssignmentRestMethod {
$content = $response.Content
Write-Warning "Error, continue deployment: $($statusCode) -- $($content)"
}
if ($statusCode -eq 403 -and $response.content -match "does not have authorization to perform action") {
Write-Error "Error, Permissions Issue. Please review permissions for service principal at scope $($RoleAssignment.scope)"
}
}
}
9 changes: 7 additions & 2 deletions Scripts/Operations/Build-PolicyDocumentation.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@ param (
[switch] $SuppressConfirmation,

[Parameter(Mandatory = $false, HelpMessage = "Include Policies with effect Manual. Default: do not include Polcies with effect Manual.")]
[switch] $IncludeManualPolicies
[switch] $IncludeManualPolicies,

[Parameter(Mandatory = $false, HelpMessage = "Include if using a PAT token for pushing to ADO Wiki.")]
[string] $WikiClonePat
)

# Dot Source Helper Scripts
Expand Down Expand Up @@ -452,6 +455,7 @@ foreach ($file in $files) {
environmentCategories = $envCategoriesArray
title = $documentAssignments.documentationSpecifications.title
markdownAdoWiki = $documentAssignments.documentationSpecifications.markdownAdoWiki
markdownAdoWikiConfig = if ($null -ne $documentAssignments.documentationSpecifications.markdownAdoWikiConfig) { $documentAssignments.documentationSpecifications.markdownAdoWikiConfig }else { $null }
}

$documentAssignments.documentationSpecifications = $tempDocumentationSpecifications
Expand Down Expand Up @@ -500,7 +504,8 @@ foreach ($file in $files) {
-DocumentationSpecification $documentationSpecification `
-AssignmentsByEnvironment $assignmentsByEnvironment `
-IncludeManualPolicies:$IncludeManualPolicies `
-PacEnvironments $pacEnvironments
-PacEnvironments $pacEnvironments `
-WikiClonePat $WikiClonePat
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,15 @@
"prod",
"nonprod"
],
"title": "Contoso Policy effects"
"title": "Contoso Policy effects",
"markdownAdoWiki": true,
"markdownAdoWikiConfig": [
{
"adoOrganization": "MyOrganization",
"adoProject": "EPAC",
"adoWiki": "EPAC"
}
]
}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,15 @@
"prod",
"nonprod"
],
"title": "Contoso Policy effects"
"title": "Contoso Policy effects",
"markdownAdoWiki": true,
"markdownAdoWikiConfig": [
{
"adoOrganization": "MyOrganization",
"adoProject": "EPAC",
"adoWiki": "EPAC"
}
]
}
]
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
variables:
# This pipeline is used to deploy Policies, Initiative definitions and Assignments into Azure.
PAC_OUTPUT_FOLDER: ./Output
PAC_DEFINITIONS_FOLDER: ./Definitions

# Use the plain text name of each service connection as a reference
planServiceConnection: "sc-epac-plan"
devServiceConnection: "sc-epac-dev"

# set the environment selector
pacEnvironmentSelector: epac-dev

# what to build trigger
trigger:
branches:
include:
- feature/*
paths:
include:
- Definitions
- Pipelines

pr: none

pool:
vmImage: "ubuntu-latest"

stages:
- stage: Plan
displayName: "Plan ${{ variables.pacEnvironmentSelector }}"
jobs:
- job: Plan
steps:
- template: templates/plan.yml
parameters:
serviceConnection: $(planServiceConnection)
pacEnvironmentSelector: ${{ variables.pacEnvironmentSelector }}

- stage: Deploy
displayName: "Deploy ${{ variables.pacEnvironmentSelector }}"
dependsOn: Plan
condition: and(not(failed()), not(canceled()), or(eq(dependencies.Plan.outputs['Plan.Plan.deployPolicyChanges'], 'yes'), eq(dependencies.Plan.outputs['Plan.Plan.deployRoleChanges'], 'yes')))
variables:
PAC_INPUT_FOLDER: "$(Pipeline.Workspace)/plans-${{ variables.pacEnvironmentSelector }}"
localDeployPolicyChanges: $[stageDependencies.Plan.Plan.outputs['Plan.deployPolicyChanges']]
localDeployRoleChanges: $[stageDependencies.Plan.Plan.outputs['Plan.deployRoleChanges']]
jobs:
- deployment: DeployPolicy
displayName: "Deploy Policy Changes"
environment: PAC-DEV
condition: and(not(failed()), not(canceled()), eq(variables.localDeployPolicyChanges, 'yes'))
strategy:
runOnce:
deploy:
steps:
- template: templates/deploy-policy.yml
parameters:
serviceConnection: $(devServiceConnection)
pacEnvironmentSelector: ${{ variables.pacEnvironmentSelector }}
- deployment: DeployRoles
displayName: "Deploy Role Changes"
dependsOn: DeployPolicy
environment: PAC-DEV
condition: and(not(failed()), not(canceled()), eq(variables.localDeployRoleChanges, 'yes'))
strategy:
runOnce:
deploy:
steps:
- template: templates/deploy-roles.yml
parameters:
serviceConnection: $(devServiceConnection)
pacEnvironmentSelector: ${{ variables.pacEnvironmentSelector }}

- stage: tenantPlan
displayName: "Plan tenant"
dependsOn:
- Deploy
condition: and(not(failed()), not(canceled()))
jobs:
- job: Plan
steps:
- template: templates/plan.yml
parameters:
serviceConnection: $(planServiceConnection)
pacEnvironmentSelector: tenant

- stage: Documentation
displayName: "Document ${{ variables.pacEnvironmentSelector }}"
condition: always()
jobs:
- job: Documentation
displayName: "Create Documentation"
steps:
- template: templates/documentation.yaml
parameters:
serviceConnection: $(serviceConnectionPlan)
pacEnvironmentSelector: ${{ variables.pacEnvironmentSelector }}
Loading

0 comments on commit 91b6ca2

Please sign in to comment.