Skip to content

Commit

Permalink
Added support for Azure GC
Browse files Browse the repository at this point in the history
  • Loading branch information
raandree committed Jun 16, 2023
1 parent f4c9311 commit 6922b64
Show file tree
Hide file tree
Showing 102 changed files with 9,395 additions and 71 deletions.
249 changes: 249 additions & 0 deletions .build/GuestConfigurationTasks.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
param
(
[Parameter()]
[System.String]
$ProjectName = (property ProjectName ''),

[Parameter()]
[System.String]
$SourcePath = (property SourcePath ''),

[Parameter()]
[System.String]
$GCPackagesPath = (property GCPackagesPath 'GCPackages'),

[Parameter()]
[System.String]
$GCPackagesOutputPath = (property GCPackagesOutputPath 'GCPackages'),

[Parameter()]
[System.String]
$GCPoliciesPath = (property GCPoliciesPath 'GCPolicies'),

[Parameter()]
[System.String]
$OutputDirectory = (property OutputDirectory (Join-Path $BuildRoot 'output')),

[Parameter()]
[System.String]
$BuiltModuleSubdirectory = (property BuiltModuleSubdirectory ''),

[Parameter()]
[System.String]
$BuildModuleOutput = (property BuildModuleOutput (Join-Path $OutputDirectory $BuiltModuleSubdirectory)),

[Parameter()]
[System.String]
$ModuleVersion = (property ModuleVersion ''),

[Parameter()]
[System.Collections.Hashtable]
$BuildInfo = (property BuildInfo @{ })
)

# SYNOPSIS: Building the Azure Policy Guest Configuration Packages
task build_guestconfiguration_packages_from_MOF -if ($PSVersionTable.PSEdition -eq 'Core') {
# Get the vales for task variables, see https://github.com/gaelcolas/Sampler#task-variables.
. Set-SamplerTaskVariable -AsNewBuild

if (-not (Split-Path -IsAbsolute $GCPackagesPath))
{
$GCPackagesPath = Join-Path -Path $SourcePath -ChildPath $GCPackagesPath
}

if (-not (Split-Path -IsAbsolute $GCPoliciesPath))
{
$GCPoliciesPath = Join-Path -Path $SourcePath -ChildPath $GCPoliciesPath
}

"`tBuild Module Output = $BuildModuleOutput"
"`tGC Packages Path = $GCPackagesPath"
"`tGC Policies Path = $GCPoliciesPath"
"`t------------------------------------------------`r`n"

$mofPath = Join-Path -Path $OutputDirectory -ChildPath $MofOutputFolder
$mofFiles = Get-ChildItem -Path $mofPath -Filter '*.mof' -Recurse |
Where-Object Name -NotLike ReferenceConfiguration*

$moduleVersion = '2.0.0'

foreach ($mofFile in $mofFiles)
{
$GCPackageName = $mofFile.BaseName
Write-Build DarkGray "Package Name '$GCPackageName' with Configuration '$MOFFile', OutputDirectory $OutputDirectory, GCPackagesOutputPath '$GCPackagesOutputPath'."
$GCPackageOutput = Get-SamplerAbsolutePath -Path $GCPackagesOutputPath -RelativeTo $OutputDirectory

$NewGCPackageParams = @{
Configuration = $mofFile.FullName
Name = $mofFile.BaseName
Path = $GCPackageOutput
Force = $true
Version = $ModuleVersion
Type = 'AuditAndSet'
}

foreach ($paramName in (Get-Command -Name 'New-GuestConfigurationPackage' -ErrorAction Stop).Parameters.Keys.Where({ $_ -in $newPackageExtraParams.Keys }))
{
Write-Verbose -Message "`t Testing for parameter '$paramName'."
Write-Build DarkGray "`t`t Using configured parameter '$paramName' with value '$($newPackageExtraParams[$paramName])'."
# Override the Parameters from the $GCPackageName.psd1
$NewGCPackageParams[$paramName] = $newPackageExtraParams[$paramName]
}

$ZippedGCPackage = (& {
New-GuestConfigurationPackage @NewGCPackageParams
} 2>&1).Where{
if ($_ -isnot [System.Management.Automation.ErrorRecord])
{
# Filter out the Error records from New-GuestConfigurationPackage
$true
}
elseif ($_.Exception.Message -notmatch '^A second CIM class definition')
{
# Write non-terminating errors that are not "A second CIM class definition for .... was found..."
$false
Write-Error $_ -ErrorAction Continue
}
else
{
$false
}
}

Write-Build DarkGray "`t Zips created, you may want to delete the unzipped folders under '$GCPackagesOutputPath'..."

if ($ModuleVersion)
{
$GCPackageWithVersionZipName = ('{0}_{1}.zip' -f $GCPackageName, $ModuleVersion)
$GCPackageOutputPath = Get-SamplerAbsolutePath -Path $GCPackagesOutputPath -RelativeTo $OutputDirectory
$versionedGCPackageName = Join-Path -Path $GCPackageOutputPath -ChildPath $GCPackageWithVersionZipName
Write-Build DarkGray "`t Renaming Zip as '$versionedGCPackageName'."
$ZippedGCPackagePath = Move-Item -Path $ZippedGCPackage.Path -Destination $versionedGCPackageName -Force -PassThru
$ZippedGCPackage = @{
Name = $ZippedGCPackage.Name
Path = $ZippedGCPackagePath.FullName
}
}

Write-Build Green "`tZipped Guest Config Package: $($ZippedGCPackage.Path)"
}
}

task publish_guestconfiguration_packages -if (
$PSVersionTable.PSEdition -eq 'Core' -and $env:azureClientSecret
) {
$subscriptionId = $datum.Global.Azure.SubscriptionId
$tenantId = $datum.Global.Azure.TenantId
$resourceGroupName = $datum.Global.Azure.ResourceGroupName
$storageAccountName = $datum.Global.Azure.StorageAccountName

Update-AzConfig -DisplayBreakingChangeWarning $false

$credential = New-Object System.Management.Automation.PSCredential -ArgumentList $env:azureClientId, (ConvertTo-SecureString -String $env:azureClientSecret -AsPlainText -Force)
Connect-AzAccount -Credential $Credential -Tenant $tenantId -ServicePrincipal -SubscriptionId $subscriptionId | Out-Null

$resourceGroup = Get-AzResourceGroup -Name $resourceGroupName
$guestConfigurationContainerName = 'guestconfiguration'

if (-not (Get-AzStorageAccount -ResourceGroupName $resourceGroupName -Name $storageAccountName -ErrorAction SilentlyContinue))
{
$param = @{
ResourceGroupName = $resourceGroupName
Name = $storageAccountName
Location = $resourceGroup.Location
SkuName = 'Standard_LRS'
Kind = 'StorageV2'
}

New-AzStorageAccount @param | Out-Null
}

$storageAccountKeys = Get-AzStorageAccountKey -ResourceGroupName $resourceGroupName -Name $storageAccountName
$storageContext = New-AzStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $storageAccountKeys[0].Value
if (-not (Get-AzStorageContainer -Context $storageContext -Name guestconfiguration -ErrorAction SilentlyContinue))
{
New-AzStorageContainer -Context $storageContext -Name guestconfiguration -Permission Blob | Out-Null
}

$moduleVersion = '2.0.0'

$managedIdentity = Get-AzUserAssignedIdentity -ResourceGroupName $resourceGroupName -Name GCLab1_Remediation

$gpPackages = Get-ChildItem -Path $OutputDirectory\$GCPackagesOutputPath -Filter '*.zip' -Recurse
foreach ($gpPackage in $gpPackages)
{
$policyName = $gpPackage.BaseName.Split('_')[0]

$param = @{
Container = $guestConfigurationContainerName
File = $gpPackage.FullName
Blob = $gpPackage.Name
Context = $storageContext
Force = $true
}
Set-AzStorageBlobContent @param

$param = @{
Context = $storageContext
FullUri = $true
Container = $guestConfigurationContainerName
Blob = $gpPackage.Name
Permission = 'rwd'
}
$contentUri = New-AzStorageBlobSASToken @param

$params = @{
PolicyId = New-Guid
ContentUri = $contentUri
DisplayName = $policyName
Description = 'none'
Path = "$OutputDirectory\$GCPoliciesPath"
Platform = 'Windows'
PolicyVersion = $moduleVersion
Mode = 'ApplyAndAutoCorrect'
Verbose = $true
}

$policy = New-GuestConfigurationPolicy @params

try
{
$policyDefinition = New-AzPolicyDefinition -Name $policyName -Policy $Policy.Path -ErrorAction Stop
}
catch
{
if ($_.Exception.HttpStatus -eq 'Forbidden')
{
Write-Error -Message "You do not have permission to create a Guest Configuration Policy. Please ensure you have the correct permissions, for example be a 'Resource Policy Contributor' on the Azure Subscription." -Exception $_.Exception
}
else
{
Write-Error -ErrorRecord $_
}
continue
}

$vm = Get-AzVM -Name $policyName -ResourceGroupName $resourceGroupName

$param = @{
Name = $policyName
DisplayName = $policyDefinition.Properties.DisplayName
Scope = $vm.Id
PolicyDefinition = $policyDefinition
Location = $datum.Global.Azure.LocationName
IdentityType = 'UserAssigned'
IdentityId = $managedIdentity.Id
}
$assignment = New-AzPolicyAssignment @param -WarningAction SilentlyContinue

$param = @{
Name = "$($policyName)Remediation"
PolicyAssignmentId = $assignment.PolicyAssignmentId
Scope = $vm.Id
ResourceDiscoveryMode = 'ReEvaluateCompliance'
}
Start-AzPolicyRemediation @param

}

}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ output/RequiredModules/*

!output/RequiredModules/Sampler.DscPipeline
!output/RequiredModules/ProtectedData
!output/RequiredModules/FileSystemDsc
!output/RequiredModules/DscConfig.Demo
2 changes: 2 additions & 0 deletions .work/Debug.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
$env:azureClientSecret = 'ygR8Q~Uyy0QkiefumgWPd6NoNbyGwHCh4r6bFdf0'
$env:azureClientId = 'a0732820-7169-4ac5-bf37-755386f5e224'
5 changes: 5 additions & 0 deletions .work/cleanup.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Get-AzVM -ResourceGroupName GCLab1 | ForEach-Object {
Get-AzPolicyAssignment -Scope $_.Id | Remove-AzPolicyAssignment
}

Get-AzPolicyDefinition | Where-Object Name -like dsc* | Remove-AzPolicyDefinition -Force
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Added stages to cloud pipeline and added steps to publish modules to Azure Automation DSC.
- Added support for Azure Guest Configuration.

### Changed

- Migration to 'Sampler' and 'Sampler.DscPipeline'.
- Migration to Pester 5+.
- Changed from 'CommonTasks' to 'DscConfig.Demo' for faster build time.
- Added support for PowerShell 7.
- Added support for Azure Guest Configuration.

### Fixed

Expand Down
34 changes: 34 additions & 0 deletions Lab/10 Azure Guest Configuration Lab.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
New-LabDefinition -Name GCLab1 -DefaultVirtualizationEngine Azure

Add-LabAzureSubscription -SubscriptionName 'S1 Contoso2' -DefaultLocationName 'UK South'

#Add-LabVirtualNetworkDefinition -Name $labName -AddressSpace 192.168.111.0/24

Add-LabDomainDefinition -Name contoso.com -AdminUser Install -AdminPassword Somepass1
Set-LabInstallationCredential -Username Install -Password Somepass1

$PSDefaultParameterValues = @{
'Add-LabMachineDefinition:OperatingSystem' = 'Windows Server 2022 Datacenter (Desktop Experience)'
'Add-LabMachineDefinition:AzureRoleSize' = 'Standard_D2ds_v4'
'Add-LabMachineDefinition:DomainName' = 'contoso.com'
}

$postInstallActivity = @()
$postInstallActivity += Get-LabPostInstallationActivity -ScriptFileName 'New-ADLabAccounts 2.0.ps1' -DependencyFolder $labSources\PostInstallationActivities\PrepareFirstChildDomain
$postInstallActivity += Get-LabPostInstallationActivity -ScriptFileName PrepareRootDomain.ps1 -DependencyFolder $labSources\PostInstallationActivities\PrepareRootDomain
Add-LabMachineDefinition -Name DSCDC01 -Roles RootDC -PostInstallationActivity $postInstallActivity

Add-LabMachineDefinition -Name DSCFile01 -Roles FileServer
Add-LabMachineDefinition -Name DSCWeb01 -Roles WebServer

Add-LabMachineDefinition -Name DSCFile02 -Roles FileServer
Add-LabMachineDefinition -Name DSCWeb02 -Roles WebServer

Add-LabMachineDefinition -Name DSCFile03 -Roles FileServer
Add-LabMachineDefinition -Name DSCWeb03 -Roles WebServer

Install-Lab

Checkpoint-LabVM -All -SnapshotName AfterInstall

Show-LabDeploymentSummary -Detailed
42 changes: 42 additions & 0 deletions Lab/20 Azure Guest Configuration Lab Customizations.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#Requires -Modules AutomatedLab, Az.Resources, Az.ManagedServiceIdentity

if (-not $lab)
{
$lab = Import-Lab -Name GCLab1 -NoValidation -PassThru
}

Get-LabVM | ForEach-Object {

Write-Host "Assigning system assigned identity to virtual machine '$($_.Name)'"
$vm = Get-AzVM -Name $_.Name -ResourceGroupName $lab.AzureSettings.DefaultResourceGroup.ResourceGroupName
Update-AzVM -VM $vm -IdentityType SystemAssigned -ResourceGroupName $vm.ResourceGroupName | Out-Null

Write-Host "Installing Guest Configuration extension on virtual machine '$($_.Name)'"
$param = @{
Publisher = 'Microsoft.GuestConfiguration'
ExtensionType = 'ConfigurationforWindows'
Name = 'AzurePolicyforWindows'
TypeHandlerVersion = '1.0'
ResourceGroupName = $vm.ResourceGroupName
Location = $vm.Location
VMName = $vm.Name
EnableAutomaticUpgrade = $true
}
Set-AzVMExtension @param | Out-Null
}

Write-Host "Creating user assigned identity for remediation '$($lab.Name)_Remediation'"
New-AzUserAssignedIdentity -ResourceGroupName $lab.AzureSettings.DefaultResourceGroup -Name "$($lab.Name)_Remediation" -Location $lab.AzureSettings.DefaultLocation
Start-Sleep -Seconds 10
$managedIdentity = Get-AzADServicePrincipal -DisplayName "$($lab.Name)_Remediation"

Write-Host "Assigning role 'Contributor' to user assigned identity '$($managedIdentity.DisplayName)'"
New-AzRoleAssignment -ObjectId $managedIdentity.Id -RoleDefinitionName Contributor -Scope $lab.AzureSettings.DefaultResourceGroup.ResourceId
Write-Host "Assigning role 'Guest Configuration Resource Contributor' to user assigned identity '$($managedIdentity.DisplayName)'"
New-AzRoleAssignment -ObjectId $managedIdentity.Id -RoleDefinitionName 'Guest Configuration Resource Contributor' -Scope $lab.AzureSettings.DefaultResourceGroup.ResourceId

#DevOps Organization and Service Connection must be created prior to running these lines
$azureDevOpsOrganizationName = 'randree'
$azureDevOpsProjectName = 'DscWorkshop'
$serviceConnectionServicePrincipal = Get-AzADServicePrincipal | Where-Object DisplayName -like "$azureDevOpsOrganizationName-$azureDevOpsProjectName*"
New-AzRoleAssignment -ObjectId $serviceConnectionServicePrincipal.Id -RoleDefinitionName 'Resource Policy Contributor'
10 changes: 9 additions & 1 deletion RequiredModules.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@
'DscResource.Test' = '0.16.1'
'DscResource.DocGenerator' = '0.11.2'
PSDesiredStateConfiguration = '2.0.6'
GuestConfiguration = '4.4.0'

'Az.Accounts' = '2.12.3'
'Az.Storage' = '5.7.0'
'Az.ManagedServiceIdentity' = '1.1.1'
'Az.Resources' = '6.7.0'
'Az.PolicyInsights' = '1.6.1'
'Az.Compute' = '6.0.0'

# Composites
'DscConfig.Demo' = '0.8.3'
Expand All @@ -44,7 +52,7 @@
NetworkingDsc = '9.0.0'
JeaDsc = '4.0.0-preview0005'
WebAdministrationDsc = '4.1.0'
FileSystemDsc = '1.1.1'
#FileSystemDsc = '1.1.1'
SecurityPolicyDsc = '2.10.0.0'
xDscDiagnostics = '2.8.0'

Expand Down
Loading

0 comments on commit 6922b64

Please sign in to comment.