зеркало из https://github.com/Azure/ALZ-Bicep.git
add policy pull workflow and scripts (#20)
This commit is contained in:
Родитель
5fd7129eb7
Коммит
041442ab3d
134
.github/scripts/EnterpriseScaleLibraryTools/EnterpriseScaleLibraryTools.psd1
поставляемый
Normal file
134
.github/scripts/EnterpriseScaleLibraryTools/EnterpriseScaleLibraryTools.psd1
поставляемый
Normal file
|
@ -0,0 +1,134 @@
|
|||
#!/usr/bin/pwsh
|
||||
|
||||
#
|
||||
# Module manifest for module 'EnterpriseScaleLibraryTools'
|
||||
#
|
||||
# Generated by: krowlandson
|
||||
#
|
||||
# Generated on: 26/02/2021
|
||||
#
|
||||
|
||||
@{
|
||||
|
||||
# Script module or binary module file associated with this manifest.
|
||||
# RootModule = ''
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '0.0.1'
|
||||
|
||||
# Supported PSEditions
|
||||
CompatiblePSEditions = 'Core', 'Desktop'
|
||||
|
||||
# ID used to uniquely identify this module
|
||||
GUID = 'f4d9375d-cb0c-4ade-b0dc-134a97444704'
|
||||
|
||||
# Author of this module
|
||||
Author = 'krowlandson'
|
||||
|
||||
# Company or vendor of this module
|
||||
CompanyName = 'krowlandson'
|
||||
|
||||
# Copyright statement for this module
|
||||
Copyright = 'Copyright (c) 2020 Kevin Rowlandson. All rights reserved.'
|
||||
|
||||
# Description of the functionality provided by this module
|
||||
Description = 'This module provides a set of custom classes and functions used for managing the template library in the Terraform Module for Cloud Adoption Framework Enterprise-scale.'
|
||||
|
||||
# Minimum version of the PowerShell engine required by this module
|
||||
PowerShellVersion = '7.0'
|
||||
|
||||
# Name of the PowerShell host required by this module
|
||||
# PowerShellHostName = ''
|
||||
|
||||
# Minimum version of the PowerShell host required by this module
|
||||
# PowerShellHostVersion = ''
|
||||
|
||||
# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
|
||||
# DotNetFrameworkVersion = ''
|
||||
|
||||
# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
|
||||
# ClrVersion = ''
|
||||
|
||||
# Processor architecture (None, X86, Amd64) required by this module
|
||||
# ProcessorArchitecture = ''
|
||||
|
||||
# Modules that must be imported into the global environment prior to importing this module
|
||||
# RequiredModules = @()
|
||||
|
||||
# Assemblies that must be loaded prior to importing this module
|
||||
# RequiredAssemblies = @()
|
||||
|
||||
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
|
||||
# ScriptsToProcess = @()
|
||||
|
||||
# Type files (.ps1xml) to be loaded when importing this module
|
||||
# TypesToProcess = @()
|
||||
|
||||
# Format files (.ps1xml) to be loaded when importing this module
|
||||
# FormatsToProcess = @()
|
||||
|
||||
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
|
||||
# NestedModules = @()
|
||||
|
||||
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
|
||||
FunctionsToExport = @()
|
||||
|
||||
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
|
||||
CmdletsToExport = @()
|
||||
|
||||
# Variables to export from this module
|
||||
VariablesToExport = '*'
|
||||
|
||||
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
|
||||
AliasesToExport = @()
|
||||
|
||||
# DSC resources to export from this module
|
||||
# DscResourcesToExport = @()
|
||||
|
||||
# List of all modules packaged with this module
|
||||
# ModuleList = @()
|
||||
|
||||
# List of all files packaged with this module
|
||||
# FileList = @()
|
||||
|
||||
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
|
||||
PrivateData = @{
|
||||
|
||||
PSData = @{
|
||||
|
||||
# Tags applied to this module. These help with module discovery in online galleries.
|
||||
# Tags = @()
|
||||
|
||||
# A URL to the license for this module.
|
||||
# LicenseUri = ''
|
||||
|
||||
# A URL to the main website for this project.
|
||||
# ProjectUri = ''
|
||||
|
||||
# A URL to an icon representing this module.
|
||||
# IconUri = ''
|
||||
|
||||
# ReleaseNotes of this module
|
||||
# ReleaseNotes = ''
|
||||
|
||||
# Prerelease string of this module
|
||||
# Prerelease = ''
|
||||
|
||||
# Flag to indicate whether the module requires explicit user acceptance for install/update/save
|
||||
# RequireLicenseAcceptance = $false
|
||||
|
||||
# External dependent modules of this module
|
||||
# ExternalModuleDependencies = @()
|
||||
|
||||
} # End of PSData hashtable
|
||||
|
||||
} # End of PrivateData hashtable
|
||||
|
||||
# HelpInfo URI of this module
|
||||
# HelpInfoURI = ''
|
||||
|
||||
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
|
||||
# DefaultCommandPrefix = ''
|
||||
|
||||
}
|
||||
|
858
.github/scripts/EnterpriseScaleLibraryTools/EnterpriseScaleLibraryTools.psm1
поставляемый
Normal file
858
.github/scripts/EnterpriseScaleLibraryTools/EnterpriseScaleLibraryTools.psm1
поставляемый
Normal file
|
@ -0,0 +1,858 @@
|
|||
#!/usr/bin/pwsh
|
||||
|
||||
#########################################
|
||||
# Module dependencies and configuration #
|
||||
#########################################
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
# Set-StrictMode -Version 3.0
|
||||
[System.Version]$azAccountsVersion = "2.2.3"
|
||||
|
||||
$module = Get-Module Az.Accounts
|
||||
if ($null -ne $module -and $module.Version -lt $azAccountsVersion) {
|
||||
Write-Error "This module requires Az.Accounts version $azAccountsVersion. An earlier version of Az.Accounts is imported in the current PowerShell session. Please open a new session before importing this module. This error could indicate that multiple incompatible versions of the Azure PowerShell cmdlets are installed on your system. Please see https://aka.ms/azps-version-error for troubleshooting information." -ErrorAction Stop
|
||||
}
|
||||
elseif ($null -eq $module) {
|
||||
Import-Module Az.Accounts -MinimumVersion $azAccountsVersion -Scope Global
|
||||
}
|
||||
|
||||
############################################
|
||||
# Custom enum data sets used within module #
|
||||
############################################
|
||||
|
||||
enum PolicyDefinitionPropertiesMode {
|
||||
All
|
||||
Indexed
|
||||
}
|
||||
|
||||
enum PolicyAssignmentPropertiesEnforcementMode {
|
||||
Default
|
||||
DoNotEnforce
|
||||
}
|
||||
|
||||
enum PolicyAssignmentIdentityType {
|
||||
None
|
||||
SystemAssigned
|
||||
}
|
||||
|
||||
enum PolicySetDefinitionPropertiesPolicyType {
|
||||
NotSpecified
|
||||
BuiltIn
|
||||
Custom
|
||||
Static
|
||||
}
|
||||
|
||||
enum GetFileNameCaseModifier {
|
||||
ToString
|
||||
ToLower
|
||||
ToUpper
|
||||
}
|
||||
|
||||
################################
|
||||
# Variables used within module #
|
||||
################################
|
||||
|
||||
[Int]$jsonDepth = 100
|
||||
|
||||
[Regex]$regex_schema_deploymentParameters = "http[s]?:\/\/schema\.management\.azure\.com\/schemas\/([0-9-]{10})\/deploymentParameters\.json#"
|
||||
[Regex]$regex_schema_managementGroupDeploymentTemplate = "http[s]?:\/\/schema\.management\.azure\.com\/schemas\/([0-9-]{10})\/managementGroupDeploymentTemplate\.json#"
|
||||
[Regex]$regex_doubleLeftSquareBrace = "(?<=`")(\[\[)"
|
||||
|
||||
#############################
|
||||
# ProviderApiVersions Class #
|
||||
#############################
|
||||
|
||||
# [ProviderApiVersions] class is used to create cache of latest API versions for all Azure Providers.
|
||||
# This can be used to retrieve the latest or stable API version in string format.
|
||||
# Can also output the API version as a param string for use within a Rest API request.
|
||||
# To minimise the number of Rest API requests needed, this class creates a cache and populates.
|
||||
# it with all results from the request. The cache is then used to return the requested result.
|
||||
# Need to store and lookup the key in lowercase to avoid case sensitivity issues while providing
|
||||
# better performance as allows using ContainsKey method to search for key in cache.
|
||||
# Should be safe to ignore case as Providers are not case sensitive.
|
||||
class ProviderApiVersions {
|
||||
|
||||
# Public class properties
|
||||
[String]$Provider
|
||||
[String]$ResourceType
|
||||
[String]$Type
|
||||
[Array]$ApiVersions
|
||||
|
||||
# Static properties
|
||||
hidden static [String]$ProvidersApiVersion = "2020-06-01"
|
||||
|
||||
# Default empty constructor
|
||||
ProviderApiVersions() {
|
||||
}
|
||||
|
||||
# Default constructor using PSCustomObject to populate object
|
||||
ProviderApiVersions([PSCustomObject]$PSCustomObject) {
|
||||
$this.Provider = $PSCustomObject.Provider
|
||||
$this.ResourceType = $PSCustomObject.ResourceType
|
||||
$this.Type = $PSCustomObject.Type
|
||||
$this.ApiVersions = $PSCustomObject.ApiVersions
|
||||
}
|
||||
|
||||
# Static method to get Api Version using Type
|
||||
static [Array] GetByType([String]$Type) {
|
||||
if ([ProviderApiVersions]::Cache.Count -lt 1) {
|
||||
[ProviderApiVersions]::UpdateCache()
|
||||
}
|
||||
$private:ProviderApiVersionsFromCache = [ProviderApiVersions]::SearchCache($Type)
|
||||
return $private:ProviderApiVersionsFromCache.ApiVersions
|
||||
}
|
||||
|
||||
# Static method to get latest Api Version using Type
|
||||
static [String] GetLatestByType([String]$Type) {
|
||||
$private:GetLatestByType = [ProviderApiVersions]::GetByType($Type) |
|
||||
Sort-Object -Descending |
|
||||
Select-Object -First 1
|
||||
return $private:GetLatestByType
|
||||
}
|
||||
|
||||
# Static method to get latest stable Api Version using Type
|
||||
# If no stable release, will return latest
|
||||
static [String] GetLatestStableByType([String]$Type) {
|
||||
$private:GetByType = [ProviderApiVersions]::GetByType($Type)
|
||||
$private:GetLatestStableByType = $private:GetByType |
|
||||
Where-Object { $_ -Match "^[0-9-]{10}$" } |
|
||||
Sort-Object -Descending |
|
||||
Select-Object -First 1
|
||||
if ($private:GetLatestStableByType) {
|
||||
return $private:GetLatestStableByType.ToString()
|
||||
}
|
||||
else {
|
||||
return [ProviderApiVersions]::GetLatestByType($Type).ToString()
|
||||
}
|
||||
}
|
||||
|
||||
static [String[]] ListTypes() {
|
||||
if ([ProviderApiVersions]::Cache.Count -lt 1) {
|
||||
[ProviderApiVersions]::UpdateCache()
|
||||
}
|
||||
$private:ShowCacheTypes = [ProviderApiVersions]::ShowCache().Type | Sort-Object
|
||||
return $private:ShowCacheTypes
|
||||
}
|
||||
|
||||
# Static property to store cache of ProviderApiVersions using a threadsafe
|
||||
# dictionary variable to allow caching across parallel jobs
|
||||
# https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/foreach-object#example-14--using-thread-safe-variable-references
|
||||
static [System.Collections.Concurrent.ConcurrentDictionary[String, ProviderApiVersions]]$Cache
|
||||
|
||||
# Static method to show all entries in Cache
|
||||
static [ProviderApiVersions[]] ShowCache() {
|
||||
return ([ProviderApiVersions]::Cache).Values
|
||||
}
|
||||
|
||||
# Static method to show all entries in Cache matching the specified type using the specified release type
|
||||
static [ProviderApiVersions[]] SearchCache([String]$Type) {
|
||||
return [ProviderApiVersions]::Cache[$Type.ToString().ToLower()]
|
||||
}
|
||||
|
||||
# Static method to return [Boolean] for Resource Type in Cache query using the specified release type
|
||||
static [Boolean] InCache([String]$Type) {
|
||||
if ([ProviderApiVersions]::Cache) {
|
||||
$private:CacheKeyLowercase = $Type.ToString().ToLower()
|
||||
$private:InCache = ([ProviderApiVersions]::Cache).ContainsKey($private:CacheKeyLowercase)
|
||||
if ($private:InCache) {
|
||||
Write-Verbose "[ProviderApiVersions] Resource Type found in Cache [$Type]"
|
||||
}
|
||||
else {
|
||||
Write-Verbose "[ProviderApiVersions] Resource Type not found in Cache [$Type]"
|
||||
}
|
||||
return $private:InCache
|
||||
}
|
||||
else {
|
||||
# The following prevents needing to initialize the cache
|
||||
# manually if not exist on first attempt to use
|
||||
[ProviderApiVersions]::InitializeCache()
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
# Static method to update Cache using current Subscription from context
|
||||
static [Void] UpdateCache() {
|
||||
$private:SubscriptionId = (Get-AzContext).Subscription.Id
|
||||
[ProviderApiVersions]::UpdateCache($private:SubscriptionId)
|
||||
}
|
||||
|
||||
# Static method to update Cache using specified SubscriptionId
|
||||
static [Void] UpdateCache([String]$SubscriptionId) {
|
||||
$private:Method = "GET"
|
||||
$private:Path = "/subscriptions/$subscriptionId/providers?api-version=$([ProviderApiVersions]::ProvidersApiVersion)"
|
||||
$private:PSHttpResponse = Invoke-AzRestMethod -Method $private:Method -Path $private:Path
|
||||
$private:PSHttpResponseContent = $private:PSHttpResponse.Content
|
||||
$private:Providers = ($private:PSHttpResponseContent | ConvertFrom-Json).value
|
||||
if ($private:Providers) {
|
||||
[ProviderApiVersions]::InitializeCache()
|
||||
}
|
||||
foreach ($private:Provider in $private:Providers) {
|
||||
Write-Verbose "[ProviderApiVersions] Processing Provider Namespace [$($private:Provider.namespace)]"
|
||||
foreach ($private:Type in $private:Provider.resourceTypes) {
|
||||
# Check for latest ApiVersions and add to cache
|
||||
[ProviderApiVersions]::AddToCache(
|
||||
$private:Provider.namespace.ToString(),
|
||||
$private:Type.resourceType.ToString(),
|
||||
$private:Type.ApiVersions
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Static method to add provider instance to Cache
|
||||
hidden static [Void] AddToCache([String]$Provider, [String]$ResourceType, [Array]$ApiVersions) {
|
||||
Write-Debug "[ProviderApiVersions] Adding [$($Provider)/$($ResourceType)] to Cache"
|
||||
$private:AzStateProviderObject = [PsCustomObject]@{
|
||||
Provider = "$Provider"
|
||||
ResourceType = "$ResourceType"
|
||||
Type = "$Provider/$ResourceType"
|
||||
ApiVersions = $ApiVersions
|
||||
}
|
||||
$private:CacheKey = "$Provider/$ResourceType"
|
||||
$private:CacheKeyLowercase = $private:CacheKey.ToString().ToLower()
|
||||
$private:CacheValue = [ProviderApiVersions]::new($private:AzStateProviderObject)
|
||||
$private:TryAdd = ([ProviderApiVersions]::Cache).TryAdd($private:CacheKeyLowercase, $private:CacheValue)
|
||||
if ($private:TryAdd) {
|
||||
Write-Verbose "[ProviderApiVersions] Added Resource Type to Cache [$private:CacheKey]"
|
||||
}
|
||||
}
|
||||
|
||||
# Static method to initialize Cache
|
||||
# Will also reset cache if exists
|
||||
static [Void] InitializeCache() {
|
||||
Write-Verbose "[ProviderApiVersions] Initializing Cache (Empty)"
|
||||
[ProviderApiVersions]::Cache = [System.Collections.Concurrent.ConcurrentDictionary[String, ProviderApiVersions]]::new()
|
||||
}
|
||||
|
||||
# Static method to clear all entries from Cache
|
||||
static [Void] ClearCache() {
|
||||
[ProviderApiVersions]::InitializeCache()
|
||||
}
|
||||
|
||||
# Static method to save all entries from Cache to filesystem
|
||||
static [Void] SaveCacheToDirectory() {
|
||||
[ProviderApiVersions]::SaveCacheToDirectory("./")
|
||||
}
|
||||
|
||||
# Static method to save all entries from Cache to filesystem
|
||||
static [Void] SaveCacheToDirectory([String]$Directory) {
|
||||
if ([ProviderApiVersions]::Cache.Count -lt 1) {
|
||||
[ProviderApiVersions]::UpdateCache()
|
||||
}
|
||||
$private:saveCachePath = "$Directory/ProviderApiVersions"
|
||||
[ProviderApiVersions]::Cache |
|
||||
ConvertTo-Json -Depth 10 -Compress |
|
||||
Out-File -FilePath "$($private:saveCachePath).json" `
|
||||
-Force
|
||||
try {
|
||||
Compress-Archive -Path "$($private:saveCachePath).json" `
|
||||
-DestinationPath "$($private:saveCachePath).zip" `
|
||||
-Force
|
||||
}
|
||||
finally {
|
||||
Remove-Item -Path "$($private:saveCachePath).json" `
|
||||
-Force
|
||||
}
|
||||
}
|
||||
|
||||
# Static method to load all entries from filesystem to Cache
|
||||
static [Void] LoadCacheFromDirectory() {
|
||||
[ProviderApiVersions]::LoadCacheFromDirectory("./")
|
||||
}
|
||||
|
||||
# Static method to load all entries from filesystem to Cache
|
||||
static [Void] LoadCacheFromDirectory([String]$Directory) {
|
||||
[ProviderApiVersions]::ClearCache()
|
||||
$private:loadCachePath = "$Directory/ProviderApiVersions"
|
||||
Expand-Archive -Path "$($private:loadCachePath).zip" `
|
||||
-DestinationPath "$Directory" `
|
||||
-Force
|
||||
try {
|
||||
$private:loadCacheObject = Get-Content `
|
||||
-Path "$($private:loadCachePath).json" `
|
||||
-Force |
|
||||
ConvertFrom-Json
|
||||
foreach ($key in $private:loadCacheObject.psobject.Properties.Name) {
|
||||
$private:value = $private:loadCacheObject."$key"
|
||||
([ProviderApiVersions]::Cache).TryAdd($key, $private:value)
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Error $_.Exception.Message
|
||||
}
|
||||
finally {
|
||||
Remove-Item -Path "$($private:loadCachePath).json" `
|
||||
-Force
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ESLTBase : System.Collections.Specialized.OrderedDictionary {
|
||||
|
||||
ESLTBase(): base() {}
|
||||
|
||||
[String] ToString() {
|
||||
if ($this.GetType() -notin "String", "Boolean", "Int") {
|
||||
return $this | ConvertTo-Json -Depth 1 -WarningAction SilentlyContinue | ConvertFrom-Json
|
||||
}
|
||||
else {
|
||||
return $this
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PolicyAssignmentProperties : ESLTBase {
|
||||
[String]$displayName = ""
|
||||
[Object]$policyDefinitionId = ""
|
||||
[String]$scope = ""
|
||||
[String[]]$notScopes = @()
|
||||
[Object]$parameters = @{}
|
||||
[String]$description = ""
|
||||
[Object]$metadata = @{}
|
||||
[String]$enforcementMode = "Default"
|
||||
|
||||
PolicyAssignmentProperties(): base() {}
|
||||
|
||||
PolicyAssignmentProperties([Object]$that): base() {
|
||||
$this.displayName = $that.displayName
|
||||
$this.policyDefinitionId = $that.policyDefinitionId
|
||||
$this.scope = $that.scope
|
||||
$this.notScopes = $that.notScopes ?? $this.notScopes
|
||||
$this.parameters = $that.parameters ?? $this.parameters
|
||||
$this.description = $that.description ?? $that.displayName
|
||||
$this.metadata = $that.metadata ?? $this.metadata
|
||||
$this.enforcementMode = ([PolicyAssignmentPropertiesEnforcementMode]($that.enforcementMode ?? $this.enforcementMode)).ToString()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PolicyAssignmentIdentity : ESLTBase {
|
||||
[String]$type = "None"
|
||||
|
||||
PolicyAssignmentIdentity(): base() {}
|
||||
|
||||
PolicyAssignmentIdentity([Object]$that): base() {
|
||||
$this.type = ([PolicyAssignmentIdentityType]($that.type ?? $this.type)).ToString()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PolicyDefinitionProperties : ESLTBase {
|
||||
[String]$policyType = "NotSpecified"
|
||||
[String]$mode = ""
|
||||
[String]$displayName = ""
|
||||
[String]$description = ""
|
||||
[Object]$metadata = @{}
|
||||
[Object]$parameters = @{}
|
||||
[Object]$policyRule = @{}
|
||||
|
||||
PolicyDefinitionProperties(): base() {}
|
||||
|
||||
PolicyDefinitionProperties([Object]$that): base() {
|
||||
$this.policyType = ([PolicySetDefinitionPropertiesPolicyType]($that.policyType ?? $this.policyType)).ToString()
|
||||
$this.mode = ([PolicyDefinitionPropertiesMode]($that.mode)).ToString()
|
||||
$this.displayName = $that.displayName
|
||||
$this.description = $that.description ?? $that.displayName
|
||||
$this.metadata = $that.metadata ?? $this.metadata
|
||||
$this.parameters = $that.parameters ?? $this.parameters
|
||||
$this.policyRule = $that.policyRule
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PolicySetDefinitionPropertiesPolicyDefinitions : ESLTBase {
|
||||
[String]$policyDefinitionReferenceId = ""
|
||||
[String]$policyDefinitionId = ""
|
||||
[Object]$parameters = @{}
|
||||
[Array]$groupNames = @()
|
||||
|
||||
PolicySetDefinitionPropertiesPolicyDefinitions(): base() {}
|
||||
|
||||
PolicySetDefinitionPropertiesPolicyDefinitions([Object]$that): base() {
|
||||
$this.policyDefinitionReferenceId = $that.policyDefinitionReferenceId
|
||||
$this.policyDefinitionId = $that.policyDefinitionId
|
||||
$this.parameters = $that.parameters ?? $this.parameters
|
||||
$this.groupNames = $that.groupNames ?? $this.groupNames
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PolicySetDefinitionPropertiesPolicyDefinitionGroup : ESLTBase {
|
||||
[String]$name = ""
|
||||
[String]$displayName = ""
|
||||
[String]$category = ""
|
||||
[String]$description = ""
|
||||
[String]$additionalMetadataId = ""
|
||||
|
||||
PolicySetDefinitionPropertiesPolicyDefinitionGroup(): base() {}
|
||||
|
||||
PolicySetDefinitionPropertiesPolicyDefinitionGroup([Object]$that): base() {
|
||||
$this.name = $that.name
|
||||
$this.displayName = $that.displayName
|
||||
$this.category = $that.category
|
||||
$this.description = $that.description
|
||||
$this.additionalMetadataId = $that.additionalMetadataId
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PolicySetDefinitionProperties : ESLTBase {
|
||||
[String]$policyType = "NotSpecified"
|
||||
[String]$displayName = ""
|
||||
[String]$description = ""
|
||||
[Object]$metadata = @{}
|
||||
[Object]$parameters = @{}
|
||||
[Array]$policyDefinitions = @()
|
||||
[Array]$policyDefinitionGroups = $null
|
||||
|
||||
PolicySetDefinitionProperties(): base() {}
|
||||
|
||||
PolicySetDefinitionProperties([Object]$that): base() {
|
||||
$this.policyType = ([PolicySetDefinitionPropertiesPolicyType]($that.policyType ?? $this.policyType)).ToString()
|
||||
$this.displayName = $that.displayName ?? ""
|
||||
$this.description = $that.description ?? $that.displayName
|
||||
$this.metadata = $that.metadata ?? $this.metadata
|
||||
$this.parameters = $that.parameters ?? $this.parameters
|
||||
$this.policyDefinitions = foreach ($policyDefinition in $that.policyDefinitions) {
|
||||
[PolicySetDefinitionPropertiesPolicyDefinitions]::new($policyDefinition)
|
||||
}
|
||||
$this.policyDefinitionGroups = foreach ($policyDefinitionGroup in $that.policyDefinitionGroups) {
|
||||
[PolicySetDefinitionPropertiesPolicyDefinitionGroup]::new($that.policyDefinitionGroups)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class RoleAssignmentProperties : ESLTBase {
|
||||
RoleAssignmentProperties(): base() {}
|
||||
}
|
||||
|
||||
class RoleDefinitionPropertiesPermissions {
|
||||
[String[]]$actions = @()
|
||||
[String[]]$notActions = @()
|
||||
[String[]]$dataActions = @()
|
||||
[String[]]$notDataActions = @()
|
||||
|
||||
RoleDefinitionPropertiesPermissions(): base() {}
|
||||
|
||||
RoleDefinitionPropertiesPermissions([Object]$that): base() {
|
||||
$this.actions = $that.actions ?? $this.actions
|
||||
$this.notActions = $that.notActions ?? $that.notActions
|
||||
$this.dataActions = $that.dataActions ?? $this.dataActions
|
||||
$this.notDataActions = $that.notDataActions ?? $this.notDataActions
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class RoleDefinitionProperties : ESLTBase {
|
||||
[String]$roleName = ""
|
||||
[String]$description = ""
|
||||
[String]$type = "customRole"
|
||||
[Array]$permissions = @()
|
||||
[Array]$assignableScopes = @()
|
||||
|
||||
RoleDefinitionProperties(): base() {}
|
||||
|
||||
RoleDefinitionProperties([Object]$that): base() {
|
||||
$this.roleName = $that.roleName
|
||||
$this.description = $that.description ?? $that.roleName
|
||||
$this.type = $that.type ?? $this.type
|
||||
$this.permissions = @(
|
||||
[PolicyAssignmentIdentity]::new($that.permissions[0])
|
||||
)
|
||||
$this.assignableScopes = $that.assignableScopes ?? $this.assignableScopes
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ArmTemplateResource : ESLTBase {
|
||||
|
||||
# Public class properties
|
||||
# Need to declare base object properties with default values to set order
|
||||
[String]$name = ""
|
||||
[String]$type = ""
|
||||
[String]$apiVersion = ""
|
||||
[Object]$scope = $null # Needs to be declared as object to avoid null returning empty string in JSON output
|
||||
[Object]$properties = @{}
|
||||
|
||||
# Hidden static class properties
|
||||
hidden static [GetFileNameCaseModifier]$GetFileNameCaseModifier = "ToLower" # Default to make lowercase
|
||||
hidden static [Regex]$regexReplaceFileNameCharacters = "\W" # Default to replace all non word characters
|
||||
hidden static [String]$GetFileNameSubstituteCharacter = "_"
|
||||
hidden static [Regex]$regexExtractProviderId = "\/providers\/(?!.*\/providers\/)[\/\w-.]+"
|
||||
|
||||
ArmTemplateResource(): base() {}
|
||||
|
||||
ArmTemplateResource([PSCustomObject]$that): base() {
|
||||
$this.name = $that.name
|
||||
$this.type = $that.ResourceType ?? $that.type
|
||||
$this.apiVersion = $that.apiVersion
|
||||
$this.scope = if ($that.scope.Length -gt 0) { $that.scope } else { $null }
|
||||
$this.properties = $that.properties
|
||||
}
|
||||
|
||||
# Initialize [ArmTemplateResource] object
|
||||
[Void] SetApiVersion([String]$ResourceType) {
|
||||
$this.apiVersion = [ProviderApiVersions]::GetLatestStableByType($ResourceType)
|
||||
}
|
||||
|
||||
# Update resource values as per requirements for Terraform Module
|
||||
# for Cloud Adoption Framework Enterprise Scale
|
||||
[Object] ToTemplateFile() {
|
||||
if ($this.type -eq "Microsoft.Authorization/policyAssignments") {
|
||||
$this.properties.scope = "`${current_scope_resource_id}"
|
||||
$this.properties.policyDefinitionId = "`${root_scope_resource_id}/"
|
||||
$this.location = "`${default_location}"
|
||||
}
|
||||
if ($this.type -eq "Microsoft.Authorization/policyDefinitions") {
|
||||
$this.properties.policyType = "Custom"
|
||||
}
|
||||
if ($this.type -eq "Microsoft.Authorization/policySetDefinitions") {
|
||||
$this.properties.policyType = "Custom"
|
||||
foreach ($policyDefinition in $this.properties.policyDefinitions) {
|
||||
$regexMatches = [ArmTemplateResource]::regexExtractProviderId.Matches($policyDefinition.policyDefinitionId)
|
||||
if ($regexMatches.Index -gt 0) {
|
||||
$policyDefinition.policyDefinitionId = "`${root_scope_resource_id}$($regexMatches.Value)"
|
||||
}
|
||||
else {
|
||||
$policyDefinition.policyDefinitionId = $regexMatches.Value
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this
|
||||
}
|
||||
|
||||
[String] GetFileName() {
|
||||
$fileName = $this.GetFileName("")
|
||||
return $fileName
|
||||
}
|
||||
|
||||
[String] GetFileName([String]$Prefix) {
|
||||
$fileNameBase = $this.name.$([ArmTemplateResource]::GetFileNameCaseModifier)()
|
||||
$fileNameBase = [ArmTemplateResource]::regexReplaceFileNameCharacters.Replace($fileNameBase, [ArmTemplateResource]::GetFileNameSubstituteCharacter)
|
||||
$fileName = $Prefix + $fileNameBase
|
||||
return $fileName
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PolicyAssignment : ArmTemplateResource {
|
||||
|
||||
# Need to re-declare base object properties with default values to maintain order
|
||||
[String]$name = ""
|
||||
[String]$type = ""
|
||||
[String]$apiVersion = ""
|
||||
[String]$scope = ""
|
||||
[Object]$properties = @{}
|
||||
[String]$location = ""
|
||||
[Object]$identity = @{}
|
||||
|
||||
PolicyAssignment(): base() {}
|
||||
|
||||
PolicyAssignment([PSCustomObject]$that): base($that) {
|
||||
$this.type = "Microsoft.Authorization/policyAssignments"
|
||||
$this.SetApiVersion($this.type)
|
||||
$this.location = $that.location
|
||||
$this.identity = [PolicyAssignmentIdentity]::new($that.identity)
|
||||
$this.properties = [PolicyAssignmentProperties]::new($this.properties)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PolicyDefinition : ArmTemplateResource {
|
||||
|
||||
PolicyDefinition(): base() {}
|
||||
|
||||
PolicyDefinition([PSCustomObject]$that): base($that) {
|
||||
$this.type = "Microsoft.Authorization/policyDefinitions"
|
||||
$this.SetApiVersion($this.type)
|
||||
$this.properties = [PolicyDefinitionProperties]::new($this.properties)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PolicySetDefinition : ArmTemplateResource {
|
||||
|
||||
PolicySetDefinition(): base() {}
|
||||
|
||||
PolicySetDefinition([PSCustomObject]$that): base($that) {
|
||||
$this.type = "Microsoft.Authorization/policySetDefinitions"
|
||||
$this.SetApiVersion($this.type)
|
||||
$this.properties = [PolicySetDefinitionProperties]::new($this.properties)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class RoleAssignment : ArmTemplateResource {
|
||||
|
||||
RoleAssignment(): base() {}
|
||||
|
||||
RoleAssignment([PSCustomObject]$that): base($that) {
|
||||
$this.type = "Microsoft.Authorization/roleAssignments"
|
||||
$this.SetApiVersion($this.type)
|
||||
$this.properties = [RoleAssignmentProperties]::new($this.properties)
|
||||
}
|
||||
}
|
||||
|
||||
class RoleDefinition : ArmTemplateResource {
|
||||
|
||||
RoleDefinition(): base() {}
|
||||
|
||||
RoleDefinition([PSCustomObject]$that): base($that) {
|
||||
$this.type = "Microsoft.Authorization/roleDefinitions"
|
||||
$this.SetApiVersion($this.type)
|
||||
$this.properties = [RoleDefinitionProperties]::new($this.properties)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function ProcessObjectByResourceType {
|
||||
[CmdletBinding()]
|
||||
[OutputType([Object])]
|
||||
param (
|
||||
[Object]$ResourceObject,
|
||||
[String]$ResourceType
|
||||
)
|
||||
try {
|
||||
switch ($ResourceType.ToLower()) {
|
||||
"microsoft.authorization/policyassignments" {
|
||||
$outputObject = [PolicyAssignment]::new($ResourceObject)
|
||||
}
|
||||
"microsoft.authorization/policydefinitions" {
|
||||
$outputObject = [PolicyDefinition]::new($ResourceObject)
|
||||
}
|
||||
"microsoft.authorization/policysetdefinitions" {
|
||||
$outputObject = [PolicySetDefinition]::new($ResourceObject)
|
||||
}
|
||||
"microsoft.authorization/roleassignments" {
|
||||
$outputObject = [RoleAssignment]::new($ResourceObject)
|
||||
}
|
||||
"microsoft.authorization/roledefinitions" {
|
||||
$outputObject = [RoleDefinition]::new($ResourceObject)
|
||||
}
|
||||
Default {
|
||||
Write-Warning "Unsupported resource type: $($ResourceType)"
|
||||
$outputObject = $ResourceObject
|
||||
}
|
||||
}
|
||||
}
|
||||
catch [System.Management.Automation.RuntimeException] {
|
||||
Write-Error $_.Exception.Message
|
||||
}
|
||||
|
||||
return $outputObject
|
||||
|
||||
}
|
||||
|
||||
function RemoveEscaping {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[Object]$InputObject
|
||||
)
|
||||
|
||||
# A number of sources store the required definition in variables
|
||||
# which use escaping for ARM functions so they are correctly
|
||||
# processed within copy_loops. These may need to be removed when
|
||||
# converting to a native ARM template.
|
||||
$output = $InputObject |
|
||||
ConvertTo-Json -Depth $jsonDepth |
|
||||
ForEach-Object { $_ -replace $regex_doubleLeftSquareBrace, "[" } |
|
||||
ConvertFrom-Json
|
||||
|
||||
return $output
|
||||
}
|
||||
|
||||
function GetObjectByResourceTypeFromJson {
|
||||
[CmdletBinding()]
|
||||
[OutputType([Object])]
|
||||
param (
|
||||
[String]$Id,
|
||||
[String[]]$InputJSON
|
||||
)
|
||||
|
||||
# Try catch is used to gracefully handle type conversion errors when the input contains invalid JSON
|
||||
try {
|
||||
$objectFromJson = $InputJSON | ConvertFrom-Json -ErrorAction Stop
|
||||
}
|
||||
catch {
|
||||
throw $_.Exception.Message
|
||||
}
|
||||
|
||||
# The following block handles processing files in the format generated by the AzOps output
|
||||
# e.g. azopsreference/ folder in Azure/Enterprise-Scale repository
|
||||
if ($regex_schema_deploymentParameters.IsMatch($objectFromJson."`$schema")) {
|
||||
if ($objectFromJson.parameters.input.value.ResourceType) {
|
||||
ProcessObjectByResourceType `
|
||||
-ResourceObject ($objectFromJson.parameters.input.value) `
|
||||
-ResourceType ($objectFromJson.parameters.input.value.ResourceType)
|
||||
}
|
||||
}
|
||||
# The following block handles processing files in the format used by the ES reference deployments
|
||||
# e.g. docs/reference/<scenario>/armTemplates/auxiliary/ folder in Azure/Enterprise-Scale repository
|
||||
elseif ($regex_schema_managementGroupDeploymentTemplate.IsMatch($objectFromJson."`$schema")) {
|
||||
foreach ($policyDefinition in $objectFromJson.variables.policies.policyDefinitions) {
|
||||
ProcessObjectByResourceType `
|
||||
-ResourceObject (RemoveEscaping -InputObject $policyDefinition) `
|
||||
-ResourceType ("Microsoft.Authorization/policyDefinitions")
|
||||
}
|
||||
foreach ($policySetDefinition in $objectFromJson.variables.initiatives.policySetDefinitions) {
|
||||
ProcessObjectByResourceType `
|
||||
-ResourceObject (RemoveEscaping -InputObject $policySetDefinition) `
|
||||
-ResourceType ("Microsoft.Authorization/policySetDefinitions")
|
||||
}
|
||||
foreach (
|
||||
$policySetDefinition in $objectFromJson.resources |
|
||||
Where-Object { $_.type -eq "Microsoft.Authorization/policyDefinitions" } |
|
||||
Where-Object { $_.name -ne "[variables('policies').policyDefinitions[copyIndex()].name]" }
|
||||
) {
|
||||
ProcessObjectByResourceType `
|
||||
-ResourceObject (RemoveEscaping -InputObject $policySetDefinition) `
|
||||
-ResourceType ("Microsoft.Authorization/policyDefinitions")
|
||||
}
|
||||
foreach (
|
||||
$policySetDefinition in $objectFromJson.resources |
|
||||
Where-Object { $_.type -eq "Microsoft.Authorization/policySetDefinitions" } |
|
||||
Where-Object { $_.name -ne "[variables('initiatives').policySetDefinitions[copyIndex()].name]" }
|
||||
) {
|
||||
ProcessObjectByResourceType `
|
||||
-ResourceObject (RemoveEscaping -InputObject $policySetDefinition) `
|
||||
-ResourceType ("Microsoft.Authorization/policySetDefinitions")
|
||||
}
|
||||
}
|
||||
# The following block handles processing generic files where the source content is unknown
|
||||
# High probability of incorrect format if this happens.
|
||||
else {
|
||||
Write-Warning "Unable to find converter for input object: $Id"
|
||||
# return $objectFromJson
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function ProcessFile {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[String]$FilePath
|
||||
)
|
||||
|
||||
$content = Get-Content -Path $FilePath
|
||||
|
||||
$output = GetObjectByResourceTypeFromJson `
|
||||
-Id $FilePath `
|
||||
-InputJSON $content
|
||||
|
||||
return $output
|
||||
}
|
||||
|
||||
function Invoke-UseCacheFromModule {
|
||||
param (
|
||||
[String]$Directory = "./"
|
||||
)
|
||||
[ProviderApiVersions]::LoadCacheFromDirectory($Directory)
|
||||
}
|
||||
|
||||
function Invoke-UpdateCacheInModule {
|
||||
param (
|
||||
[String]$Directory = "./"
|
||||
)
|
||||
[ProviderApiVersions]::SaveCacheToDirectory($Directory)
|
||||
}
|
||||
|
||||
function ConvertTo-LibraryArtifact {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[String[]]$InputPath,
|
||||
[String]$InputFilter = "*.json",
|
||||
[String]$OutputPath = "./",
|
||||
[String]$FileNamePrefix = "",
|
||||
[String]$FileNameSuffix = ".json",
|
||||
[Switch]$AsTemplate,
|
||||
[Switch]$Recurse
|
||||
)
|
||||
$inputFiles = foreach ($path in $InputPath) {
|
||||
Get-ChildItem -Path $path -Recurse:$Recurse -Filter $InputFilter
|
||||
}
|
||||
|
||||
[Object[]]$outputItems = foreach ($inputFile in $inputFiles) {
|
||||
$content = ProcessFile `
|
||||
-FilePath $inputFile.FullName
|
||||
foreach ($item in $content | Where-Object { $_ }) {
|
||||
[PSCustomObject]@{
|
||||
InputFilePath = $inputFile.FullName
|
||||
OutputFilePath = ($OutputPath + "/" + $item.GetFileName($FileNamePrefix) + $FileNameSuffix) -replace "//", "/"
|
||||
OutputTemplate = $AsTemplate ? $item.ToTemplateFile() : $item
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $outputItems
|
||||
|
||||
}
|
||||
|
||||
function Export-LibraryArtifact {
|
||||
[CmdletBinding(SupportsShouldProcess)]
|
||||
param (
|
||||
[String[]]$InputPath,
|
||||
[String]$InputFilter = "*.json",
|
||||
[String[]]$TypeFilter = @(),
|
||||
[String]$OutputPath = "./",
|
||||
[String]$FileNamePrefix = "",
|
||||
[String]$FileNameSuffix = ".json",
|
||||
[Switch]$AsTemplate,
|
||||
[Switch]$Recurse
|
||||
)
|
||||
|
||||
$libraryArtifacts = ConvertTo-LibraryArtifact `
|
||||
-InputPath $InputPath `
|
||||
-InputFilter $InputFilter `
|
||||
-OutputPath $OutputPath `
|
||||
-FileNamePrefix $FileNamePrefix `
|
||||
-FileNameSuffix $FileNameSuffix `
|
||||
-AsTemplate:$AsTemplate `
|
||||
-Recurse:$Recurse
|
||||
|
||||
if ($TypeFilter.Length -eq 0) {
|
||||
Write-Verbose "Using default TypeFilter. Will process all valid resource types."
|
||||
$TypeFilter = [ProviderApiVersions]::ListTypes()
|
||||
}
|
||||
else {
|
||||
Write-Verbose "Using custom TypeFilter. Will process the following resource types:`n $($TypeFilter.foreach({" - " + $_ +"`n"}))"
|
||||
}
|
||||
|
||||
foreach ($libraryArtifact in $libraryArtifacts) {
|
||||
$libraryArtifactMessage = ("Processing file... `n" + `
|
||||
" - Input : $($libraryArtifact.InputFilePath) `n" + `
|
||||
" - Output : $($libraryArtifact.OutputFilePath)")
|
||||
|
||||
if ($libraryArtifact.OutputTemplate.type -in $TypeFilter) {
|
||||
if ($PSCmdlet.ShouldProcess($libraryArtifact.OutputFilePath)) {
|
||||
$libraryArtifactFile = $libraryArtifact.OutputTemplate |
|
||||
ConvertTo-Json -Depth $jsonDepth |
|
||||
New-Item -Path $libraryArtifact.OutputFilePath -ItemType File -Force
|
||||
$libraryArtifactMessage += "`n [COMPLETE]"
|
||||
Write-Verbose $libraryArtifactMessage
|
||||
Write-Information "Output File : $($libraryArtifactFile.FullName) [COMPLETE]" -InformationAction Continue
|
||||
}
|
||||
}
|
||||
else {
|
||||
$libraryArtifactMessage += "`n [SKIPPING] Resource Type not in TypeFilter."
|
||||
Write-Verbose $libraryArtifactMessage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Create alias(es) for Functions
|
||||
# New-Alias -Name "example" -Value "Invoke-ExampleFunction"
|
||||
|
||||
$aliasesToExport = @()
|
||||
$functionsToExport = @(
|
||||
"ConvertTo-LibraryArtifact"
|
||||
"Export-LibraryArtifact"
|
||||
"Invoke-UseCacheFromModule"
|
||||
"Invoke-UpdateCacheInModule"
|
||||
)
|
||||
|
||||
# Export module members
|
||||
Export-ModuleMember -Function $functionsToExport -Alias $aliasesToExport
|
Двоичные данные
.github/scripts/EnterpriseScaleLibraryTools/ProviderApiVersions.zip
поставляемый
Normal file
Двоичные данные
.github/scripts/EnterpriseScaleLibraryTools/ProviderApiVersions.zip
поставляемый
Normal file
Двоичный файл не отображается.
|
@ -0,0 +1,124 @@
|
|||
#!/usr/bin/pwsh
|
||||
|
||||
#
|
||||
# PowerShell Script
|
||||
# - Update template library in terraform-azurerm-caf-enterprise-scale repository
|
||||
#
|
||||
# Valid object schema for Export-LibraryArtifact function loop:
|
||||
#
|
||||
# @{
|
||||
# inputPath = [String]
|
||||
# inputFilter = [String]
|
||||
# typeFilter = [String[]]
|
||||
# outputPath = [String]
|
||||
# fileNamePrefix = [String]
|
||||
# fileNameSuffix = [String]
|
||||
# asTemplate = [Boolean]
|
||||
# recurse = [Boolean]
|
||||
# whatIf = [Boolean]
|
||||
# }
|
||||
#
|
||||
|
||||
[CmdletBinding(SupportsShouldProcess)]
|
||||
param (
|
||||
[Parameter()][String]$TargetModulePath = "$PWD/ALZ-Bicep",
|
||||
[Parameter()][String]$SourceModulePath = "$PWD/enterprise-scale",
|
||||
[Parameter()][Switch]$Reset,
|
||||
[Parameter()][Switch]$UseCacheFromModule
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# This script relies on a custom set of classes and functions
|
||||
# defined within the EnterpriseScaleLibraryTools PowerShell
|
||||
# module.
|
||||
$esltModuleDirectory = $TargetModulePath + "/.github/scripts/EnterpriseScaleLibraryTools"
|
||||
$esltModulePath = "$esltModuleDirectory/EnterpriseScaleLibraryTools.psm1"
|
||||
Import-Module $esltModulePath -ErrorAction Stop
|
||||
|
||||
# To avoid needing to authenticate with Azure, the following
|
||||
# code will preload the ProviderApiVersions cache from a
|
||||
# stored state in the module if the UseCacheFromModule flag
|
||||
# is set and the ProviderApiVersions.zip file is present.
|
||||
if ($UseCacheFromModule -and (Test-Path "$esltModuleDirectory/ProviderApiVersions.zip")) {
|
||||
Write-Information "Pre-loading ProviderApiVersions from saved cache." -InformationAction Continue
|
||||
Invoke-UseCacheFromModule($esltModuleDirectory)
|
||||
}
|
||||
|
||||
# The defaultConfig object provides a set of default values
|
||||
# to reduce verbosity within the esltConfig object.
|
||||
$defaultConfig = @{
|
||||
inputFilter = "*.json"
|
||||
typeFilter = @()
|
||||
outputPath = $TargetModulePath + "infra-as-code/bicep/modules/policy/lib"
|
||||
fileNamePrefix = ""
|
||||
fileNameSuffix = ".json"
|
||||
asTemplate = $true
|
||||
recurse = $false
|
||||
}
|
||||
|
||||
# File locations from Enterprise-scale repository for
|
||||
# resources, organised by type
|
||||
$policyDefinitionFilePaths = (Get-ChildItem -Path "$SourceModulePath/eslzArm/managementGroupTemplates/policyDefinitions").FullName
|
||||
$policySetDefinitionFilePaths = (Get-ChildItem -Path "$SourceModulePath/eslzArm/managementGroupTemplates/policyDefinitions").FullName
|
||||
|
||||
# The esltConfig array controls the foreach loop used to run
|
||||
# Export-LibraryArtifact. Each object provides a set of values
|
||||
# used to configure each run of Export-LibraryArtifact within
|
||||
# the loop. If a value needed by Export-LibraryArtifact is
|
||||
# missing, it will use the default value specified in the
|
||||
# defaultConfig object.
|
||||
$esltConfig = @()
|
||||
# Add Policy Definition source files to $esltConfig
|
||||
$esltConfig += $policyDefinitionFilePaths | ForEach-Object {
|
||||
[PsCustomObject]@{
|
||||
inputPath = $_
|
||||
typeFilter = "Microsoft.Authorization/policyDefinitions"
|
||||
fileNamePrefix = "policy_definitions/policy_definition_es_"
|
||||
}
|
||||
}
|
||||
# Add Policy Set Definition source files to $esltConfig
|
||||
$esltConfig += $policySetDefinitionFilePaths | ForEach-Object {
|
||||
[PsCustomObject]@{
|
||||
inputPath = $_
|
||||
typeFilter = "Microsoft.Authorization/policySetDefinitions"
|
||||
fileNamePrefix = "policy_set_definitions/policy_set_definition_es_"
|
||||
fileNameSuffix = ".tmpl.json"
|
||||
}
|
||||
}
|
||||
|
||||
# If the -Reset parameter is set, delete all existing
|
||||
# artefacts (by resource type) from the library
|
||||
if ($Reset) {
|
||||
Write-Information "Deleting existing Policy Definitions from library." -InformationAction Continue
|
||||
Remove-Item -Path "$TargetModulePath/infra-as-code/bicep/modules/policy/lib/policy_definitions/" -Recurse -Force
|
||||
Write-Information "Deleting existing Policy Set Definitions from library." -InformationAction Continue
|
||||
Remove-Item -Path "$TargetModulePath/infra-as-code/bicep/modules/policy/lib/policy_set_definitions/" -Recurse -Force
|
||||
}
|
||||
|
||||
# Process the files added to $esltConfig, to add content
|
||||
# to the library
|
||||
foreach ($config in $esltConfig) {
|
||||
Export-LibraryArtifact `
|
||||
-InputPath ($config.inputPath ?? $defaultConfig.inputPath) `
|
||||
-InputFilter ($config.inputFilter ?? $defaultConfig.inputFilter) `
|
||||
-TypeFilter ($config.typeFilter ?? $defaultConfig.typeFilter) `
|
||||
-OutputPath ($config.outputPath ?? $defaultConfig.outputPath) `
|
||||
-FileNamePrefix ($config.fileNamePrefix ?? $defaultConfig.fileNamePrefix) `
|
||||
-FileNameSuffix ($config.fileNameSuffix ?? $defaultConfig.fileNameSuffix) `
|
||||
-AsTemplate:($config.asTemplate ?? $defaultConfig.asTemplate) `
|
||||
-Recurse:($config.recurse ?? $defaultConfig.recurse) `
|
||||
-WhatIf:$WhatIfPreference
|
||||
}
|
||||
|
||||
# Get a list of current Policy Definition names
|
||||
$policyDefinitionFiles = Get-ChildItem -Path "$TargetModulePath/infra-as-code/bicep/modules/policy/lib/policy_definitions/"
|
||||
$policyDefinitionNames = $policyDefinitionFiles | ForEach-Object {
|
||||
(Get-Content -Path $_ | ConvertFrom-Json).Name
|
||||
}
|
||||
|
||||
# Get a list of current Policy Set Definition names
|
||||
$policySetDefinitionFiles = Get-ChildItem -Path "$TargetModulePath/infra-as-code/bicep/modules/policy/lib/policy_set_definitions/"
|
||||
$policySetDefinitionNames = $policySetDefinitionFiles | ForEach-Object {
|
||||
(Get-Content -Path $_ | ConvertFrom-Json).Name
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/pwsh
|
||||
|
||||
#
|
||||
# PowerShell Script
|
||||
# - Update the ProviderApiVersions.zip file stored in the module
|
||||
#
|
||||
# Requires an authentication session PowerShell session to Azure
|
||||
# and should be run from the same location as the script unless
|
||||
# the -Directory parameter is specified.
|
||||
#
|
||||
|
||||
[CmdletBinding(SupportsShouldProcess)]
|
||||
param (
|
||||
[Parameter()][String]$Directory = "$PWD/EnterpriseScaleLibraryTools"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# This script relies on a custom set of classes and functions
|
||||
# defined within the EnterpriseScaleLibraryTools PowerShell
|
||||
# module.
|
||||
$esltModulePath = "$Directory/EnterpriseScaleLibraryTools.psm1"
|
||||
Import-Module $esltModulePath -ErrorAction Stop
|
||||
|
||||
Write-Information "Updating ProviderApiVersions in module." -InformationAction Continue
|
||||
if ($PSCmdlet.ShouldProcess($Directory)) {
|
||||
Invoke-UpdateCacheInModule($Directory)
|
||||
}
|
||||
|
||||
Write-Information "... Complete" -InformationAction Continue
|
|
@ -0,0 +1,110 @@
|
|||
---
|
||||
name: Update Policy Library
|
||||
|
||||
# on:
|
||||
# schedule:
|
||||
# - cron: '0 12 1 * *'
|
||||
|
||||
on: workflow_dispatch
|
||||
|
||||
env:
|
||||
remote_repository: "Azure/Enterprise-Scale"
|
||||
branch_name: "patch-policy-library"
|
||||
az_accounts_minimum_version: "2.2.3"
|
||||
pr_title: "Update Policy Library (automated)"
|
||||
pr_body: "This is an automated 'pull_request' containing updates to the library templates stored in 'modules/archetypes/lib'.\nPlease review the 'files changed' tab to review changes."
|
||||
|
||||
jobs:
|
||||
update-templates:
|
||||
name: Update Policy Library
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- name: Local repository checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: ${{ github.repository }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Remote repository checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: ${{ env.remote_repository }}
|
||||
path: ${{ env.remote_repository }}
|
||||
ref: main
|
||||
|
||||
- name: Configure local git
|
||||
run: |
|
||||
git config user.name github-actions
|
||||
git config user.email action@github.com
|
||||
working-directory: ${{ github.repository }}
|
||||
|
||||
- name: Create and checkout branch
|
||||
run: |
|
||||
BRANCH_URL="repos/${{ github.repository }}/branches"
|
||||
JQ_FILTER=".[] | select(.name == \"${{ env.branch_name }}\").name"
|
||||
CHECK_BRANCH_ORIGIN=$(gh api $BRANCH_URL | jq -r "$JQ_FILTER")
|
||||
if [ -z "$CHECK_BRANCH_ORIGIN" ]
|
||||
then
|
||||
echo "Checkout local branch (create new, no origin)..."
|
||||
git checkout -b ${{ env.branch_name }}
|
||||
else
|
||||
echo "Checkout local branch (create new, track from origin)..."
|
||||
git checkout -b ${{ env.branch_name }} --track origin/${{ env.branch_name }}
|
||||
fi
|
||||
working-directory: ${{ github.repository }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.github_token }}
|
||||
|
||||
- name: Update Policy Library
|
||||
run: |
|
||||
Write-Information "==> Installing Az.Accounts PowerShell Module..." -InformationAction Continue
|
||||
Install-Module -Name "Az.Accounts" -MinimumVersion "${{ env.az_accounts_minimum_version }}" -Force
|
||||
Write-Information "==> Running script..." -InformationAction Continue
|
||||
${{ github.repository }}/.github/scripts/Invoke-LibraryUpdate.ps1 `
|
||||
-TargetModulePath ${{ github.workspace }}/${{ github.repository }} `
|
||||
-SourceModulePath ${{ github.workspace }}/${{ env.remote_repository }} `
|
||||
-UseCacheFromModule `
|
||||
-Reset
|
||||
shell: pwsh
|
||||
|
||||
- name: Check for changes
|
||||
id: git_status
|
||||
run: |
|
||||
CHECK_GIT_STATUS=($(git status -s))
|
||||
git status -s
|
||||
echo "::set-output name=changes::${#CHECK_GIT_STATUS[@]}"
|
||||
working-directory: ${{ github.repository }}
|
||||
|
||||
- name: Add files, commit and push
|
||||
if: steps.git_status.outputs.changes > 0
|
||||
run: |
|
||||
echo "Pushing changes to origin..."
|
||||
git add infra-as-code/bicep/modules/policy/lib
|
||||
git commit -m '${{ env.pr_title }}'
|
||||
git push origin ${{ env.branch_name }}
|
||||
working-directory: ${{ github.repository }}
|
||||
|
||||
- name: Create pull request
|
||||
if: steps.git_status.outputs.changes > 0
|
||||
run: |
|
||||
HEAD_LABEL="${{ github.repository_owner }}:${{ env.branch_name }}"
|
||||
BASE_LABEL="${{ github.repository_owner }}:$(echo '${{ github.ref }}' | sed 's:refs/heads/::')"
|
||||
PULL_REQUEST_URL="repos/${{ github.repository }}/pulls"
|
||||
JQ_FILTER=".[] | select(.head.label == \"$HEAD_LABEL\") | select(.base.label == \"$BASE_LABEL\") | .url"
|
||||
CHECK_PULL_REQUEST_URL=$(gh api $PULL_REQUEST_URL | jq -r "$JQ_FILTER")
|
||||
if [ -z "$CHECK_PULL_REQUEST_URL" ]
|
||||
then
|
||||
CHECK_PULL_REQUEST_URL=$(gh pr create \
|
||||
--title "${{ env.pr_title }}" \
|
||||
--body "${{ env.pr_body }}" \
|
||||
--base "${{ github.ref }}" \
|
||||
--head "${{ env.branch_name }}" \
|
||||
--draft)
|
||||
echo "Created new PR: $CHECK_PULL_REQUEST_URL"
|
||||
else
|
||||
echo "Existing PR found: $CHECK_PULL_REQUEST_URL"
|
||||
fi
|
||||
working-directory: ${{ github.repository }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.github_token }}
|
Загрузка…
Ссылка в новой задаче