Skip to content

Commit 080815f

Browse files
qamagoEwan Noble
authored andcommitted
CDN Integration Components (#88)
* Initial commit * CDN components * . "$PSScriptRoot\..\Modules\BlobCopy.psm1" @DeploymentParameters * Additional CORS function and settings * cases * removing . source as the function is called directly * "StorageAccountName" * updates to componemts * BlobCopy @DeploymentParameters * fix path Set-location -path "$PSScriptRoot\..\Tools\AzCopy\" * Set-location -path "$PSScriptRoot\..\..\Tools\AzCopy\" * PurgeContent and additional changes * additional comments * Additional configuration * ConvertTo-AzureDevOpsVariables * remove function * Move AzureDevOpsVariables and change extension * Update to file name * Adding unit testing * Update example * Update to AT015.. file name * Moving modules to CDN-Helpers module * Updates and cleanup * Update to example and parameters * duplicate parameter purgecontent * syntax * updates to hashtable - cors rules * enableCors * docs update * remove AzureDevOpsVariables * cleanup * No state change: [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] * remove trailing whitespace * Updates to the code review * review updates * $AzCopyPath = "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\AzCopy\" * updates * Parameter updates * updates to set-cdnComponents params * further updates * if ($EnableCORS.IsPresent) { Enable-CORS @DeploymentParameters * Add function for testing registry for content types * added .Parameter OriginType description * Code updates * Enable-CORS
1 parent df7b51f commit 080815f

File tree

3 files changed

+374
-2
lines changed

3 files changed

+374
-2
lines changed
Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
function Start-BlobCopy {
2+
<#
3+
.SYNOPSIS
4+
Copy content to blob storage and update ContentType(MIME) settings
5+
6+
.DESCRIPTION
7+
Copy content to blob storage and update ContentType(MIME) settings using AzCopy
8+
AzCopy syntax: https://docs.microsoft.com/en-us/azure/storage/common/storage-use-azcopy
9+
10+
.PARAMETER Source
11+
The source location of the files to be copied
12+
13+
.PARAMETER Destination
14+
The blob destinaton of where to copy the files
15+
16+
.PARAMETER AccessKey
17+
The Access Key to access the blob storage container
18+
19+
.PARAMETER OriginType
20+
The Origin Type i.e. "Storage", "Cloud Service", "Web App" or "Custom Origin"
21+
22+
.EXAMPLE
23+
24+
$DeploymentParameters = @ {
25+
Source = "c:\FilesToBeCopied\"
26+
Destination = "https://name.blob.core.windows.net/cdn"
27+
Accesskey = "MySecureAccessKeyString"
28+
OriginType = "Storage"
29+
30+
}
31+
BlobCopy @DeploymentParameters
32+
33+
.NOTES
34+
35+
Suppressed Script Analyzer rules:
36+
- PSUseShouldProcessForStateChangingFunctions - The function does not alter the state of an object
37+
38+
#>
39+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
40+
Param(
41+
[Parameter(Mandatory = $true)]
42+
[String]$Source,
43+
[Parameter(Mandatory = $true)]
44+
[String]$Destination,
45+
[Parameter(Mandatory = $true)]
46+
[String]$AccessKey,
47+
[Parameter(Mandatory = $true)]
48+
[ValidateSet("Storage", "Cloud Service", "Web App", "Custom Origin")]
49+
[String]$OriginType
50+
)
51+
try {
52+
if ($OriginType -eq "Storage") {
53+
# --- Set location for AzCopy.exe
54+
$AzCopyPath = "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\AzCopy\"
55+
if (Test-Path $AzCopyPath ) {
56+
Write-Log -LogLevel Information -Message "Setting location to Azure Storage AzCopy utility"
57+
Set-Location -Path $AzCopyPath
58+
}
59+
else {
60+
Write-Log -LogLevel Information -Message "Could not locate Azure Storage AzCopy utility under $AzCopyPath"
61+
break
62+
}
63+
Write-Log -LogLevel Information -Message "Invoking Azure Storage AzCopy utility to upload content and change MIME settings"
64+
# ---> Invoke AzCopy.exe for
65+
.\AzCopy.exe /Source:$Source /Dest:$Destination /DestKey:$AccessKey /NC:10 /Z /V /S /Y /SetContentType
66+
}
67+
else {
68+
Write-Log -LogLevel Information -Message "Blob copy not required as OriginType set to either 'Cloud Service', 'Web App' or 'Custom Origin'"
69+
}
70+
}
71+
catch {
72+
throw "Failed to copy content to blob and set MIME settings: $_"
73+
}
74+
}
75+
76+
function Enable-CORS {
77+
<#
78+
.SYNOPSIS
79+
Set CORS settings on blob storage
80+
81+
.DESCRIPTION
82+
Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional HTTP headers to tell a browser
83+
to let a web application running at one origin (domain) have permission to access selected resources from a server at a different origin.
84+
Courtesy: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
85+
More Information: https://docs.microsoft.com/en-us/powershell/module/azure.storage/set-azurestoragecorsrule?view=azurermps-6.12.0
86+
87+
.PARAMETER StorageAccountName
88+
The StorageAccountName to apply the CORS settings
89+
90+
.PARAMETER AccessKey
91+
The Access Key to access the blob storage container
92+
93+
.EXAMPLE
94+
95+
$DeploymentParameters = @ {
96+
StorageAccountName = "mystorageaccountname"
97+
AccessKey = "MySecureAccessKeyString"
98+
}
99+
Enable-CORS @DeploymentParameters
100+
101+
#>
102+
Param(
103+
[Parameter(Mandatory = $false , ParameterSetName = 'Storage')]
104+
[string]$StorageAccountName,
105+
[Parameter(Mandatory = $false , ParameterSetName = 'Storage')]
106+
[string]$AccessKey
107+
)
108+
# ---- Default CORS Settings
109+
$CORSRules = (@{
110+
AllowedHeaders = @("*");
111+
AllowedOrigins = @("*");
112+
MaxAgeInSeconds = 3600;
113+
AllowedMethods = @("Get")
114+
})
115+
try {
116+
# ---- Set CORS Rules
117+
if ($PSCmdlet.ParameterSetName -eq "Storage") {
118+
Write-Log -LogLevel Information -Message "Setting Storage Context and applying CORS settings"
119+
$StorageContext = New-AzureStorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $AccessKey
120+
Set-AzureStorageCORSRule -ServiceType Blob -CorsRules $CORSRules -Context $StorageContext
121+
}
122+
else {
123+
Write-Log -LogLevel Information -Message "CORS settings not applied, only required for Development and Testing environments when using Storage Account"
124+
}
125+
}
126+
catch {
127+
throw "Failed to get Storage Context and set CORS settings: $_"
128+
}
129+
}
130+
131+
132+
function Start-ContentPurge {
133+
<#
134+
.SYNOPSIS
135+
Purges the content from an Azure Content Delivery Network (CDN)
136+
137+
.DESCRIPTION
138+
Purges the content from an Azure Content Delivery Network (CDN)
139+
140+
.PARAMETER CDNProfileResourceGroup
141+
The Resource Group of the CDN
142+
143+
.PARAMETER CDNProfileName
144+
The CDN Profile Name
145+
146+
.PARAMETER CDNEndPointName
147+
The CDN EndPoint Name
148+
149+
.PARAMETER PurgeContent
150+
The assest you wish to purge from the edge nodes
151+
Single URL Purge: Purge individual asset by specifying the full URL, e.g., "/pictures/image1.png" or "/pictures/image1"
152+
Wildcard purge: Purge all folders, sub-folders, and files under an endpoint with "/*" e.g. "/* " or "/pictures/*"
153+
Root domain purge: Purge the root of the endpoint with "/" in the path
154+
155+
.EXAMPLE
156+
157+
$DeploymentParameters = @ {
158+
CDNProfileResourceGroup = "cdn"
159+
CDNProfileName = "myprofile01"
160+
CDNEndPointName = "myendpoint01"
161+
PurgeContent = "/*"
162+
}
163+
PurgeContent @DeploymentParameters
164+
165+
.NOTES
166+
167+
Suppressed Script Analyzer rules:
168+
- PSUseShouldProcessForStateChangingFunctions - The function does not alter the state of an object
169+
170+
#>
171+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
172+
Param(
173+
[Parameter(Mandatory = $true)]
174+
[String]$CDNProfileResourceGroup,
175+
[Parameter(Mandatory = $true)]
176+
[String]$CDNProfileName,
177+
[Parameter(Mandatory = $true)]
178+
[String]$CDNEndPointName,
179+
[Parameter(Mandatory = $false)]
180+
[String]$PurgeContent = ""
181+
)
182+
try {
183+
if ( $PurgeContent -eq "" ) { Write-Log -LogLevel Information -Message "Purge Content not required"
184+
}
185+
else {
186+
# --- Set CDN EndPoint
187+
Write-Log -LogLevel Information -Message "Setting CDN EndPoint"
188+
$CDNEndpoint = Get-AzureRmCdnEndpoint -ResourceGroupName $CDNProfileResourceGroup -ProfileName $CDNProfileName -EndpointName $CDNEndpointName
189+
190+
# ---> Purging CDN EndPoint
191+
Write-Log -LogLevel Information -Message "Purging CDN EndPoint"
192+
$CDNEndpoint | Unpublish-AzureRmCdnEndpointContent -PurgeContent $PurgeContent
193+
}
194+
}
195+
catch {
196+
throw "Failed to fetch CDN Endpoint and Purge Content: $_"
197+
}
198+
}
199+
200+
201+
function Test-AzCopyContentType {
202+
<#
203+
.SYNOPSIS
204+
Tests all file extensions in a source directory for content types in the registry which AzCopy will use.
205+
206+
.DESCRIPTION
207+
Tests all file extensions in a source directory for content types in the registry which AzCopy will use.
208+
209+
.PARAMETER Source
210+
Source path to test recursively
211+
212+
.EXAMPLE
213+
Test-AzCopyContentType -Source $SourcePath
214+
215+
#>
216+
param(
217+
[string]$Source
218+
)
219+
220+
if (Test-Path -Path $Source) {
221+
222+
$RegistryContentTypes = (Get-ChildItem -Path Registry::HKEY_CLASSES_ROOT | Where-Object { $_.Property -like "Content Type"}).Name.Replace("HKEY_CLASSES_ROOT\", [string]::Empty)
223+
224+
225+
$SourceContentTypes = Get-ChildItem -Path $Source -Recurse | Select-Object -ExpandProperty Extension -Unique
226+
227+
$MissingTypes = $SourceContentTypes | Where-Object { ($RegistryContentTypes -notcontains $_) -and ($_ -ne [string]::Empty)}
228+
229+
if ($MissingTypes) {
230+
Write-Error "Registry is missing Content Types for:`n$([string]::Join("`n", $MissingTypes))"
231+
}
232+
}
233+
else {
234+
throw "Invalid path supplied"
235+
}
236+
}

Infrastructure/Modules/Helpers.psm1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ function New-Password {
2727
2828
#>
2929
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "")]
30-
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
30+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
3131
Param(
3232
[Parameter(Mandatory=$false)]
3333
[Int]$Length = 15,
@@ -119,4 +119,4 @@ function Write-Log {
119119
}
120120
}
121121
}
122-
}
122+
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
<#
2+
3+
.SYNOPSIS
4+
Set additonal CDN (Content Delivery Network) Components
5+
6+
.DESCRIPTION
7+
Set additional CDN (Content Delivery Network) Components
8+
9+
.PARAMETER Source
10+
The source location of the files to be copied
11+
12+
.PARAMETER Destination
13+
The blob destinaton of where to copy the files
14+
15+
.PARAMETER AccessKey
16+
The Access Key to access the blob storage container
17+
18+
.PARAMETER OriginType
19+
The Origin Type i.e. "Storage", "Cloud Service", "Web App" or "Custom Origin"
20+
21+
.PARAMETER StorageAccountName
22+
The StorageAccountName to apply the CORS settings
23+
24+
.PARAMETER CDNProfileResourceGroup
25+
The Resource Group of the CDN
26+
27+
.PARAMETER CDNProfileName
28+
The CDN Profile Name
29+
30+
.PARAMETER CDNEndPointName
31+
The CDN EndPoint Name
32+
33+
.PARAMETER PurgeContent
34+
The content to purge
35+
36+
.PARAMETER EnableCORS
37+
The EnableCORS switch parameter, if specified at run time then Enable-CORS function will run
38+
39+
.EXAMPLE
40+
$DeploymentParameters = @ {
41+
Source = "c:\FilesToBeCopied\"
42+
Destination = "https://name.blob.core.windows.net/cdn"
43+
AccessKey = "MySecureAccessKeyString"
44+
StorageAccountName = "mystorageaccountname"
45+
CDNProfileResourceGroupName = "cdn"
46+
CDNProfileName = "myprofile01"
47+
CDNEndPointName = "myendpoint01"
48+
PurgeContent = "/*"
49+
}
50+
.\Set-CDNComponents.ps1 @DeploymentParameters -EnableCORS
51+
52+
#>
53+
# ---- Copy CDN content to blob storage and set MIME settings
54+
Param(
55+
[Parameter(Mandatory = $true)]
56+
[String]$Source,
57+
[Parameter(Mandatory = $true)]
58+
[String]$Destination,
59+
[Parameter(Mandatory = $false)]
60+
[String]$AccessKey,
61+
[Parameter(Mandatory = $false)]
62+
[String]$StorageAccountName,
63+
[Parameter(Mandatory = $true)]
64+
[String]$CDNProfileResourceGroup,
65+
[Parameter(Mandatory = $true)]
66+
[String]$CDNProfileName,
67+
[Parameter(Mandatory = $true)]
68+
[String]$CDNEndPointName,
69+
[Parameter(Mandatory = $false)]
70+
[String]$PurgeContent = "",
71+
[Parameter(Mandatory = $true)]
72+
[ValidateSet("Storage", "Cloud Service", "Web App", "Custom Origin")]
73+
[String]$OriginType,
74+
[Parameter(Mandatory = $false)]
75+
[switch]$EnableCORS
76+
77+
)
78+
# --- Import Azure Helpers
79+
Import-Module (Resolve-Path -Path $PSScriptRoot\..\Modules\CDNHelpers.psm1).Path
80+
Import-Module (Resolve-Path -Path $PSScriptRoot\..\Modules\Helpers.psm1).Path
81+
82+
83+
# ---- Set BlobCopy Deployment Parameters
84+
$DeploymentParameters = @{
85+
Source = $Source
86+
Destination = $Destination
87+
AccessKey = $AccessKey
88+
OriginType = $OriginType
89+
}
90+
try {
91+
# ---- Run BlobCopy Function
92+
if ($OriginType -eq "Storage") {
93+
Test-AzCopyContentType $Source
94+
Start-BlobCopy @DeploymentParameters
95+
}
96+
else {
97+
Write-Log -LogLevel Information -Message "Blob copy not required as OriginType set to either 'Cloud Service', 'Web App' or 'Custom Origin'"
98+
}
99+
}
100+
catch {
101+
throw "Registry is missing Content Types and failed to copy content to blob and set MIME settings: $_"
102+
}
103+
104+
# ---- Set CORS Deployment Parameters
105+
$DeploymentParameters = @{
106+
StorageAccountName = $StorageAccountName
107+
AccessKey = $AccessKey
108+
}
109+
try {
110+
# ---- Run CORS Function
111+
if ($EnableCORS.IsPresent) {
112+
Enable-CORS @DeploymentParameters
113+
}
114+
else {
115+
Write-Log -LogLevel Information -Message "CORS settings not applied, only required for Development and Testing environments when using Storage Account"
116+
}
117+
}
118+
catch {
119+
throw "Failed to get Storage Context and set CORS settings: $_"
120+
}
121+
# ---- Set PurgeContent Deployment Parameters
122+
$DeploymentParameters = @{
123+
CDNProfileResourceGroup = $CDNProfileResourceGroup
124+
CDNProfileName = $CDNProfileName
125+
CDNEndPointName = $CDNEndPointName
126+
PurgeContent = $PurgeContent
127+
}
128+
129+
try {
130+
# ---- Run PurgeContent Function
131+
Start-ContentPurge @DeploymentParameters
132+
}
133+
catch {
134+
throw "Failed to fetch CDN Endpoint and Purge Content: $_"
135+
}
136+

0 commit comments

Comments
 (0)