Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I enable HTTPS in CustomDomain in Azure CDN through ARM Template

I have created Azure CDN through ARM template from Azure DevOps by CI/CD, followed the below references -

https://github.com/Azure/azure-quickstart-templates/tree/master/201-cdn-with-storage-account

https://docs.microsoft.com/en-us/azure/templates/microsoft.cdn/2019-04-15/profiles/endpoints/customdomains

Azure CDN created and mapped the Custom Domain with Endpoint. But not sure how do I enable HTTPS (My Own certificate available in KeyVault) in custom domain through ARM (from Azure DevOps) template, options are not available in MS template reference.

Want to automate the whole creation of Azure CDN.

Is there a way to enable HTTPS for CustomDomain thorough DevOps?

Here is my script (not the final) -

#Enable Https in Custom Domain - Azure CDN

$cdnProfileName ='debtestcdnprofile'
$cdnEndpointName = 'debtestcdnendpoint'
$cdnCustomDomainName = 'mysubdomain-mydomain-com' # testing 
$keyVaultName = 'debkeyvault'
$certificateName = 'debasiscert'
$apiVersion = '2019-04-15'

$secretVersion = 'XXXXXXXXXXX'
$secretName = 'debasiscert'
$keyVaultResourceGroupName = 'rsgStgCDN'

$cdnProfile = Get-AzCdnProfile -ProfileName $cdnProfileName;
$resourceGroup = Get-AzResourceGroup -Name $cdnProfile.ResourceGroupName;
$resourceGroupName = $resourceGroup.ResourceGroupName;
$context = Get-AzContext;
$subscriptionId = $context.Subscription.Id;
$azProfile = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile;

$profileClient = New-Object Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient($azProfile);
$token = $profileClient.AcquireAccessToken($context.Subscription.TenantId);
$accessToken = $token.AccessToken;

write-verbose -verbose "[INF] Access token : $($accessToken)"

$StateUri = "https://management.azure.com/subscriptions/$($subscriptionId)/resourcegroups/$($resourceGroupName)/providers/Microsoft.Cdn/profiles/$($cdnProfileName)/endpoints/$($cdnEndpointName)/customdomains/$($cdnCustomDomainName)?api-version=$($apiVersion)"

$ProvisionUri = "https://management.azure.com/subscriptions/$($subscriptionId)/resourcegroups/$($resourceGroupName)/providers/Microsoft.Cdn/profiles/$($cdnProfileName)/endpoints/$($cdnEndpointName)/customdomains/$($cdnCustomDomainName)/enableCustomHttps?api-version=$($apiVersion)"

$body = $ExecutionContext.InvokeCommand.ExpandString('{"certificateSource":"AzureKeyVault","protocolType":"ServerNameIndication","certificateSourceParameters":{"@odata.type":"#Microsoft.Azure.Cdn.Models.KeyVaultCertificateSourceParameters","subscriptionId":"$subscriptionId","resourceGroupName":"$keyVaultResourceGroupName","vaultName":"$keyVaultName","SecretName":"$secretName","SecretVersion":"$secretVersion","updateRule":"NoAction","deleteRule":"NoAction"}}')

$headers = @{ }

$headers.Add('Authorization', "Bearer $accessToken") 

$headers.Add('Content-Type', 'application/json')


$AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'

[System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols

$state = (Invoke-RestMethod -Method GET  -Uri $StateUri -Headers $headers).properties.customHttpsProvisioningState

Throwing same issue in CI/CD as well as while executing through PowerShell

Issue -

Invoke-RestMethod : {
  "error": {
  "code": "NotFound",
   "message": "The resource cannot be found."
  }

At line:51 char:11
+ $state = (Invoke-RestMethod -Method GET  -Uri $StateUri -Headers $hea ...
+           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], We 
   bException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

Executing the "Get-AzCdnCustomDomain" command in PowerShell also throwing bad request -

PS C:\WINDOWS\system32> Get-AzCdnCustomDomain -ResourceGroupName 'XXXXX' -ProfileName 'XXXXX' -EndpointName 'XXXXX' -CustomDomainNa
me 'subdomain.domain.com'
Get-AzCdnCustomDomain : Operation returned an invalid status code 'BadRequest'
At line:1 char:1
+ Get-AzCdnCustomDomain -ResourceGroupName 'XXXXX' -Prof ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : CloseError: (:) [Get-AzCdnCustomDomain], ErrorResponseException
    + FullyQualifiedErrorId : Microsoft.Azure.Commands.Cdn.CustomDomain.GetAzureRmCdnCustomDomain
like image 737
Debasis Ghosh Avatar asked Dec 03 '19 15:12

Debasis Ghosh


2 Answers

Enable HTTPS in CustomDomain in Azure CDN through ARM Template

If you want to achieve this by using ARM template, unfortunately, it haven't supported to add HTTPS for endpoint in the ARM template until now. So, even using Azure Devops, it also could not be make true by using ARM template.

But in the pipeline of VSTS, you can using a short Powershell script by calling below API to enable the HTTPS:

POST https://management.azure.com/subscriptions/{subscription id}/resourcegroups/{resourceGroup name}/providers/Microsoft.Cdn/profiles/{Cdnprofile name)/endpoints/{cdnEndpointName}/customdomains/customDomain/enableCustomHttps?api-version=2018-04-02" 

As you mentioned, you store the certificate in Key Vault, you need specify the key vault as certificateSource in this request body:

{
  "certificateSource": "AzureKeyVault",
  "protocolType": "ServerNameIndication",
  "certificateSourceParameters": {
    "@odata.type": "#Microsoft.Azure.Cdn.Models.KeyVaultCertificateSourceParameters",
    "subscriptionId": "$subId",
    "resourceGroupName": "$resourceGroupKv",
    "vaultName": "$kvName",
    "SecretName": "$secretName",
    "SecretVersion": "$version",
    "updateRule": "NoAction",
    "deleteRule": "NoAction"
  }
}

For details, please check this doc to configure your request body based on your actual need.

Also, there has someone describe the detailed steps and scripts for how to using Powershell to call this API. You can refer to that blog.


Want to automate the whole creation of Azure CDN.

Now, you should have got how to enable HTTPS. So the issue is how to create the the completed Azure CDN automatically in VSTS.

Step1: Add a agent job.

Step2: Add a first task Azure resource group deployment

Apply the ARM template by using Azure resource group deployment task in Build/Release pipeline. This task is available both in build and release pipeline.

Step3: Add a second task Powershell and input the above enable HTTPS powershell script into inline type.

After configure them, run this pipeline, then it can achieve automate the whole creation of Azure CDN.

You can apply these steps in CI or CD, anyone is available in VSTS.

like image 200
Mengdi Liang Avatar answered Sep 18 '22 16:09

Mengdi Liang


Enabling HTTPS of the custom domain achieved through PowerShell script and invoking the Rest API. At least now; I am unable to do through "az cdn custom-domain enable-https", did not get proper sample for --custom-domain-https-parameters.

Due to bad mistake always I'm receiving HTTP status 400 from Rest API. Reason is I am passing domain name (host name) instead of friendly name mapping to the endpoint. (e.g. - my domain name or host name is : mysubdomain.domainname.com and friendly name is MyDevDomain; then Rest API is expecting MyDevDomain)

We can follow @Merlin Liang - MSFT steps to automate the process.

Steps I followed -

ref - https://docs.microsoft.com/en-us/azure/cdn/cdn-custom-ssl?tabs=option-2-enable-https-with-your-own-certificate#ssl-certificates

  1. Register Azure CDN in Azure Active Directory.
  2. Grant Azure CDN access to key vault.
  3. PowerShell script -

https://www.nlymbery.com.au/posts/azure-cdn-automate-provisioning-custom-certificate/

https://gist.github.com/HQJaTu/c5695626ba51c6194845fa60913e911b

$cdnProfile = Get-AzCdnProfile -ProfileName $cdnProfileName;
$resourceGroup = Get-AzResourceGroup -Name $cdnProfile.ResourceGroupName;
$resourceGroupName = $resourceGroup.ResourceGroupName;

# Get Access Token to invoke in Rest API
$context = Get-AzContext;
$subscriptionId = $context.Subscription.Id;
$azProfile = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile;
if (-not $azProfile.Accounts.Count) {
    Write-Error "Error occured!"
    Exit 1
}

$profileClient = New-Object Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient($azProfile);
$token = $profileClient.AcquireAccessToken($context.Subscription.TenantId) ;
$accessToken = $token.AccessToken;
if (-not $accessToken) {
    Write-Error "Error occured!";
    Exit 1
}

# Update certificate values
# ref - https://docs.microsoft.com/en-us/rest/api/cdn/customdomains/enablecustomhttps

$ProvisionUri = "https://management.azure.com/subscriptions/$($subscriptionId)/resourcegroups/$($resourceGroupName)/providers/Microsoft.Cdn/profiles/$($cdnProfileName)/endpoints/$($cdnEndpointName)/customdomains/$($cdnCustomDomainName)/enableCustomHttps?api-version=$($apiVersion)"

$body = $ExecutionContext.InvokeCommand.ExpandString('{"certificateSource":"AzureKeyVault","protocolType":"ServerNameIndication","certificateSourceParameters":{"@odata.type":"#Microsoft.Azure.Cdn.Models.KeyVaultCertificateSourceParameters","subscriptionId":"$subscriptionId","resourceGroupName":"$keyVaultResourceGroupName","vaultName":"$keyVaultName","SecretName":"$secretName","SecretVersion":"$secretVersion","updateRule":"NoAction","deleteRule":"NoAction"}}')

$headers = @{ }  
$headers.Add('Authorization', "Bearer $accessToken")  
$headers.Add('Content-Type', 'application/json')

write-verbose -verbose "[INF] Provision Uri: $($ProvisionUri)"
write-verbose -verbose "[INF] Headers: $($headers)"  
write-verbose -verbose "[INF] Body: $($body)"

Write-Verbose -Verbose "Applying custom certificate to $($cdnProfileName):$($cdnEndpointName)"

Invoke-RestMethod -Method Post -Uri $ProvisionUri -Headers $headers -Body $body
write-verbose -verbose "[INF] Script executed successfully!"

before invoking check the provisioning state as per the blog.

like image 24
Debasis Ghosh Avatar answered Sep 22 '22 16:09

Debasis Ghosh