Skip to content

Instantly share code, notes, and snippets.

@manishtiwari25
Last active August 9, 2023 17:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save manishtiwari25/bad34a5544c8c709db31457d9cc94ebb to your computer and use it in GitHub Desktop.
Save manishtiwari25/bad34a5544c8c709db31457d9cc94ebb to your computer and use it in GitHub Desktop.
Scripts to automate azure b2c custom policy deployment and validation, for more info (https://blogs.bitesinbyte.com/blogPost/a474c427-52d8-4f7d-9f65-02822fced323)
parameters:
- name: PoliciesFolderPath
type: string
default: false
- name: KeysToReplace
type: string
default: false
- name: VmImage
default: 'ubuntu-latest'
jobs:
- job: ValidateAndDeploy
pool:
vmImage: ${{ parameters.VmImage }}
steps:
- checkout: self
- task: PowerShell@2
displayName: Replace Tokens
inputs:
filePath: "pipelines/scripts/ReplaceToken.ps1"
arguments: -folderPath ${{ parameters.PoliciesFolderPath }} -keysToReplace ${{ parameters.KeysToReplace }}
pwsh: true
- task: PowerShell@2
displayName: Validate policies
inputs:
filePath: 'pipelines/scripts/ValidateXml.ps1'
arguments: ${{ parameters.PoliciesFolderPath }}
pwsh: true
- task: PowerShell@2
displayName: Deploy policies
inputs:
filePath: "pipelines/scripts/Deploy.ps1"
arguments: $(ClientId) $(ClientSecret) $(TenantId) ${{ parameters.PoliciesFolderPath }}
pwsh: true
trigger: none
variables:
- group: GraphApiCreds
stages:
- stage: Release_QA
displayName: Release QA
variables:
- group: QAPolicy
jobs:
- template: templates/azure-b2c-jobs.yml
parameters:
PoliciesFolderPath: "Policies"
KeysToReplace: "TENANTNAME,DEPLOYMENTMODE"
- stage: Release_Production
displayName: Release Production
variables:
- group: ProductionPolicy
jobs:
- template: templates/azure-b2c-jobs.yml
parameters:
PoliciesFolderPath: "Policies"
KeysToReplace: "TENANTNAME,DEPLOYMENTMODE"
param(
[Parameter(Mandatory = $true)]
[string]$clientID,
[Parameter(Mandatory = $true)]
[string]$clientSecret,
[Parameter(Mandatory = $true)]
[string]$tenantId,
[Parameter(Mandatory = $true)]
[string]$folderPath
)
try {
$xmlFiles = Get-ChildItem -Path $folderPath -Force | Where-Object -FilterScript {
$_.Extension -eq ".xml"
}
if ($xmlFiles.Count -eq 0) {
Write-Warning "No XML files found in the specified path $($folderPath)"
exit
}
$body = @{grant_type = "client_credentials"; scope = "https://graph.microsoft.com/.default"; client_id = $ClientID; client_secret = $ClientSecret }
$response = Invoke-RestMethod -Uri https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token -Method Post -Body $body
$token = $response.access_token
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Content-Type", 'application/xml')
$headers.Add("Authorization", 'Bearer ' + $token)
Foreach ($xmlfile in $xmlFiles) {
$filePath = $folderPath +'/'+ $xmlfile.Name
# Check if file exists
$FileExists = Test-Path -Path $filePath -PathType Leaf
if ($FileExists) {
$policycontent = Get-Content $filePath -Encoding UTF8
# Get the policy name from the XML document
$match = Select-String -InputObject $policycontent -Pattern '(?<=\bPolicyId=")[^"]*'
If ($match.matches.groups.count -ge 1) {
$PolicyId = $match.matches.groups[0].value
Write-Host "Uploading the" $PolicyId "policy..."
$graphuri = 'https://graph.microsoft.com/beta/trustframework/policies/' + $PolicyId + '/$value'
$content = [System.Text.Encoding]::UTF8.GetBytes($policycontent)
$response = Invoke-RestMethod -Uri $graphuri -Method Put -Body $content -Headers $headers -ContentType "application/xml; charset=utf-8"
Write-Host "Policy" $PolicyId "uploaded successfully."
}
}
else {
$warning = "File " + $filePath + " couldn't be not found."
Write-Warning -Message $warning
}
}
}
catch {
Write-Host "StatusCode:" $_.Exception.Response.StatusCode.value__
$_
$streamReader = [System.IO.StreamReader]::new($_.Exception.Response.GetResponseStream())
$streamReader.BaseStream.Position = 0
$streamReader.DiscardBufferedData()
$errResp = $streamReader.ReadToEnd()
$streamReader.Close()
$ErrResp
exit 1
}
exit 0
param(
[Parameter(Mandatory = $true)]
[string]$folderPath,
[Parameter(Mandatory = $true)]
[string[]]$keysToReplace
)
if ($keysToReplace.Count -eq 0) {
Write-Warning "no key found to replace"
exit 1
}
$xmlFiles = Get-ChildItem -Path $folderPath -Force | Where-Object -FilterScript {
$_.Extension -eq ".xml"
Write-Host $_
}
if ($xmlFiles.Count -eq 0) {
Write-Warning "No XML files found in the specified path"
exit 1
}
Foreach ($file in $xmlFiles) {
$filePath = $folderPath +'/'+ $file.Name
# Check if file exists
$FileExists = Test-Path -Path $filePath -PathType Leaf
if ($FileExists) {
$policycontent = Get-Content $filePath -Encoding UTF8
foreach ($key in $keysToReplace) {
$policycontent = $policycontent.Replace($key, $(Get-Content env:$key))
}
Set-Content $filepath -Value $policycontent -Force
}
else {
$warning = "File " + $filePath + " couldn't be not found."
Write-Warning -Message $warning
}
}
param (
[Parameter(Mandatory = $true)]
[string]$xmlFolderPath
)
$xmlFiles = Get-ChildItem -Path $xmlFolderPath -Force | Where-Object -FilterScript {
$_.Extension -eq ".xml"
}
if ($xmlFiles.Count -eq 0) {
Write-Warning "No XML files found in the specified path"
exit
}
$handler = [System.Xml.Schema.ValidationEventHandler] {
$copy = $_
switch ($args.Severity) {
Error {
Write-Error "ERROR: line $($copy.Exception.LineNumber)"
Write-Error "position $($copy.Exception.LinePosition)"
Write-Error $copy.Message
throw
}
Warning {
Write-Warning "Warning:: " + $copy.Message
break
}
}
}
try {
Push-Location (Split-Path $xmlFolderPath)
$isValid = $true
$failedFiles = @()
$xsd = "https://raw.githubusercontent.com/Azure-Samples/active-directory-b2c-custom-policy-starterpack/master/TrustFrameworkPolicy_0.3.0.0.xsd"
Invoke-WebRequest -Uri $xsd -OutFile "TrustFrameworkPolicy_0.3.0.0.xsd"
foreach ($xmlfile in $xmlFiles) {
Write-Host "Validating $($xmlFolderPath + $xmlfile.Name)" -ForegroundColor Cyan
$settings = new-object System.Xml.XmlReaderSettings
$null = $settings.Schemas.Add("http://schemas.microsoft.com/online/cpim/schemas/2013/06", "$(Get-Location)/TrustFrameworkPolicy_0.3.0.0.xsd")
$null = $settings.ValidationType = [System.Xml.ValidationType]::Schema
$settings.add_ValidationEventHandler($handler)
$reader = [System.Xml.XmlReader]::Create($xmlfile, $settings)
$document = new-object System.Xml.XmlDocument
try {
$null = $document.Load($reader)
}
catch {
$isValid = $false
$failedFiles += $xmlfile.Name
}
$null = $reader.Close()
}
if ($isValid -eq $false) {
Write-Error "Validation failed for $($failedFiles)"
exit 1
}
}
catch {
throw
}
finally {
Remove-Item -Path "TrustFrameworkPolicy_0.3.0.0.xsd"
Pop-Location
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment