AS2 certificates and Azure Integration Accounts

Posted: January 20, 2023  |  Categories: Azure

This is a story about how to refresh AS2 certificates in Azure Integration accounts. Additionally, I will highlight a gotcha when renewing partner certificates.

Setting up AS2 certificates in an Integration Account

To begin with we set up our certificate following Microsoft documentation. As was previously stated, we script the upload of all our AS2 certificates using powershell scripts in devops.

Firstly, an example script to upload a private certificate for our host is below. Note that I could not work out how to update a private certificate in an integration account. Delete that certificate before you begin.

Get-ChildItem "$(System.DefaultWorkingDirectory)/$(edi.templatesPath)/edi-supplier-certificates/" -Filter *.pfx | 
Foreach-Object {
    $certificateName=[io.path]::GetFileNameWithoutExtension($_)
    $certificateFileName=$_
    Write-Host "Deploying certificate:$certificateName from file:$certificateFileName"

	$Password = ConvertTo-SecureString -String "$(edi.certificatePassword)" -AsPlainText -Force
	Add-AzureKeyVaultKey -VaultName "edi-$(edi.env)-kv" -Name "$certificateName" -KeyFilePath "$(System.DefaultWorkingDirectory)/$(edi.templatesPath)/edi-supplier-certificates/$certificateFileName" -KeyFilePassword $Password
}

Secondly an example script that uploads our partner and host public certificates is below.

#AddNewCert2IA.ps1

Get-ChildItem "$(System.DefaultWorkingDirectory)/$(edi.templatesPath)/edi-supplier-biztalk-certs-ia/$(edi.env)/" -Filter *.cer | 
Foreach-Object {
    $IACertName=[io.path]::GetFileNameWithoutExtension($_)
    $IACertFileName=$_
    Write-Host "Re-Deploying cert:$IACertName from file:$IACertFileName"

    try 
	{
	    #throws an error if the certificate does not exist
        Set-AzureRmIntegrationAccountCertificate -ResourceGroupName "edi-$(edi.env)-rg" -Name "edi-$(edi.env)-ia" -CertificateName $IACertName  -PublicCertificateFilePath "$(System.DefaultWorkingDirectory)/$(edi.templatesPath)/edi-supplier-biztalk-certs-ia/$(edi.env)/$IACertFileName" -ErrorAction Stop -Force
	}
	catch 
	{
         Write-Host "Deploying cert:$IACertName from file:$IACertFileName"
        New-AzureRmIntegrationAccountCertificate -ResourceGroupName "edi-$(edi.env)-rg" -Name "edi-$(edi.env)-ia" -CertificateName $IACertName  -PublicCertificateFilePath "$(System.DefaultWorkingDirectory)/$(edi.templatesPath)/edi-supplier-biztalk-certs-ia/$(edi.env)/$IACertFileName"
	}
}

However, the way the integration account configures a private certificate is very different from public certificates. Public certificates associate with partners. When you configure these from the drop down you do not specify a resource group, key vault or key name.

Conversely private certificates are normally associate with the host. When you configure a private certificate you must specify a resource group, key vault and a key name. One of the prerequisites is to add the private certificate to the key container of a key vault.

As an aside, I found it very difficult to prove what private certificate is in the key vault. If you download the public key it is a PEM. I could not find a good way of converting the PEM so I could read the certificate.

Configuring these public and private certificates in an AS2 agreement to decrypt or sign completes the AS2 puzzle.

The Problem

We update public certificates by simply adding the new certificate to our build and deploying with devops. This requires that you keep the name of the certificate the same. As soon as deployment is complete the new partner public certificate is in use without error.

Conversely, if you update a private certificate. Then send a AS2 request to the send side of an AS2 agreement you observe a MDN NACK. The NACK says that decrypting the request fails. Furthermore, if you send a AS2 request encrypted with the old public certificate you receive a MDN ACK. This suggests to me that even after deleting and replacing the private certificate in the key vault the integration account still references the old private certificate.

With this in mind I open the AS2 agreement. Browse to the receive side. Look at the encryption certificate. Finally, I select OK and agreement says it is updating even though I have not changed anything.

Now if I send another AS2 request signed with new certificate then I do not get the encryption error.

Conclusion

In my hands, private certificates do not refresh in the Azure Integration account on update whereas public certificates do. In order to refresh a private certificate, I think you need to also refresh the AS2 agreements as well. This can take a long time if you have a lot of AS2 agreements.

Luckily, we script the deployment agreements in our devops. Thus, deploying with these steps enabled does this quickly.

turbo360

Back to Top