Search code examples
azureazure-web-app-serviceazure-cliazure-pipelines-yaml

How to add a public key certificate using AZ CLI


I can easily add my public key certificate to my WebApp using the portal:
MyWebApp --> Certificates --> Public key certificate --> Add certificate.

I need to do the same using AZ CLI. I already understand such a dedicated command doesn't exist, but I should be able to use az resource create.

I've been trying with numerous variations for days but can't get it to work.
This is my YAML task:

- task: AzureCLI@2
  displayName: Add Public Certificate to App Service
  inputs:
    azureSubscription: "${{ parameters.SubscriptionName }}"
    scriptType: 'pscore'
    scriptLocation: 'inlineScript'
    inlineScript: >           
      az resource create 
      --resource-group $(ResourceGroupName) 
      --name "my-wa/ServicePublicKey" 
      --resource-type "Microsoft.Web/sites/publicCertificates"  
      --is-full-object 
      --api-version "2022-09-01"
      --properties '{\"existingWebAppName\":\"my-wa\", \"location\":\"West Europe\", \"blob\":\"MIIC/zCCAeugAwIBAgIQjngbV7+4eppN1YUvFh8guDAJBgUrDgMCHQUAMBgx...FjAUBgNVBAMTDXRlc3RjZX8\",\"publicCertificateLocation\":\"CurrentUserMy\"}' 

It seems my JSON is OK, but I now get this error:

ERROR: Operation returned an invalid status 'Not Found'

Sadly it doesn't tell me what it can't find.
I can't find any other example about how to add a public key certificate to my WebApp.


Solution

  • You can make use of az rest command and call this Azure Rest API to update the certificate to your web app, Make sure the service principal or Azure Resource manager service connection you're using to add the certificate has necessary permissions on the Key vault to access the certificate.As my certificate is stored in the Key vault certificate. I am using default Azure Resource manager service connection as my azureSubscription.

    My YAML script with Azure CLI task:-

    trigger:
    - main
    
    pool:
      vmImage: ubuntu-latest
    
    steps:
    - task: AzureCLI@2
      inputs:
        azureSubscription: 'xxx subscription(10)(xxxx6-xxxxcb2a7)'
        scriptType: 'bash'
        scriptLocation: 'inlineScript'
        inlineScript: |
          az account set --subscription "Subscription Name"
          az account show
          az rest --method put --body '{
            "location": "australiaeast",
            "properties": {
              "keyVaultId": "/subscriptions/xxxx98-44d6-xxxx97cb2a7/resourceGroups/valleyrg54/providers/Microsoft.KeyVault/vaults/valleykv9",
              "keyVaultSecretName": "siliconcert",
              "serverFarmId": "/subscriptions/xxx-f598-xxxx-xx7cb2a7/resourceGroups/valleyrg54/providers/Microsoft.Web/serverfarms/ASP-valleyrg54-8a96"
            },
            "tags": {
              "environment": "production",
              "owner": "john.doe"
            }
          }' --uri https://management.azure.com/subscriptions/xxx65-xx-xxxfd-xxx97cb2a7/resourceGroups/valleyrg54/providers/Microsoft.Web/certificates/siliconcert?api-version=2022-03-01 --headers "Content-Type=application/json"
    

    Output:-

    enter image description here

    enter image description here

    If you face any permission error, Refer this SO thread answer by Brando Zhang

    One workaround is to use Azure Powershell command SO answer as suggested by Miao Tian-MSFT

    Here, I have the .cer certificate in my Azure repository:-

    trigger:
    - main
    
    pool:
      vmImage: ubuntu-latest
    
    steps:
    - task: AzurePowerShell@5
      inputs:
        azureSubscription: 'PowershellSid'
        ScriptType: 'InlineScript'
        Inline: |
          # Install the specific version of Azure PowerShell module
          Install-Module -Name Az 
                
          # Import the Azure PowerShell module
          Import-Module Az -Force
          
          #get function app
          $appName="valleywebapp09"
          $groupName="valleyrg54"
          $app =Get-AzWebApp -ResourceGroupName $groupName -Name $appName
          
          #get public certificate content
          $cerpath="$(System.DefaultWorkingDirectory)\siliconcert_714f1b774b99453784cac60599e29620.cer"
          $cerFileBytes = get-content $cerpath -Encoding Byte
          $cerblob=[System.Convert]::ToBase64String($cerFileBytes)
          
          $properties=@{
           blob =$cerblob;
           publicCertificateLocation="$(System.DefaultWorkingDirectory)"
          }
          
          New-AzResource -ResourceName "$($appName)/testcer" -ResourceType "Microsoft.Web/sites/publicCertificates" `
                   -Properties $properties -ResourceGroupName $groupName