0
votes

I'm trying to using the Azure Python SDK to drive some server configuration management, but I'm having difficulty working out how I'm supposed to use the API to upload and configure SSL certificates.

I can successfully interrogate my Azure account to discovering the App Services that are available with the WebSiteManagementClient, and I can interrogate and manipulate DNS configurations using the DnsManagementClient.

I am also able to manually add an SSL certificate to an Azure App Service using the instructions on the Azure website.

However, it isn't at all clear to me what API endpoints I should be using to install a custom SSL certificate.

If I've got a WebSiteManagementClient named client, then I can see that:

  • client.certificates.get_certificate() allows me to get a specific certificate by name - but client.certificates doesn't appear to have an API to list all available certificates.
  • client.certificates.create_or_update_certificate() allows me to presumably idempotently create/update a certificate - but it requires a CertificateEnvelope argument, and I can't see where that object should be created.
  • Assuming I manually upload a certificate, I can't work out what API endpoint I would use to install that certificate on a site. There are calls to get_site_host_name_bindings and delete_site_host_name_binding, but no obvious API to create the binding; there are dozens of calls to configure_... and create_or_update_..., but neither the naming of the API endpoints nor the API documentation is in any way illuminating as to which calls should be used.

Can anyone point me in the right direction? What Python API calls do I need to make to upload a certificate obtained from a third party, and install that certificate on an AppService under a specific domain?

Addendum

Here's some sample code, based on suggestions from @peter-pan-msft:

creds = ServicePrincipalCredentials(
    client_id=UUID('<client>'),
    secret='<secret>',
    tenant=UUID('<tenant>'),
    resource='https://vault.azure.net'
)
kv = KeyVaultClient(
    credentials=creds
)
KEY_VAULT_URI = 'https://<vault>.vault.azure.net/'

with open('example.pfx', 'rb') as f:
    data = f.read()

# Try to get the certificates
for cert in kv.get_certificates(KEY_VAULT_URI):
    print(cert)

# or...
kv.import_certificate(KEY_VAULT_URI, 'cert name', data, 'password')

This code raises:

KeyVaultErrorException: Operation returned an invalid status code 'Forbidden'

The values for the credentials have worked for other operations, including getting and creating keys in the key store. If I modify the credentials to be known bad values, I get:

KeyVaultErrorException: Operation returned an invalid status code 'Unauthorized'
2

2 Answers

1
votes

If you follow the App Service walkthrough for importing certificates from Key Vault, it'll tell you that your app needs read permissions to access certificates from the vault. But to initially import your certificate to Key Vault as you're doing, you'll need to grant your service principal certificate import permissions as well. Trying to import a certificate without import permissions will yield a "Forbidden" error like the one you're seeing.

There are also new packages for working with Key Vault in Python that replace azure-keyvault:

azure-identity is the package that should be used with these for authentication.

Here's an example of importing a certificate using azure-keyvault-certificates:

from azure.identity import DefaultAzureCredential
from azure.keyvault.certificates import CertificateClient

KEY_VAULT_URI = 'https://<vault>.vault.azure.net/'

credential = DefaultAzureCredential()
client = CertificateClient(KEY_VAULT_URI, credential)

with open('example.pfx', 'rb') as f:
    data = f.read()

client.import_certificate("cert-name", data.encode(), password="password")

You can provide the same credentials that you used for ServicePrincipalCredentials by setting environment variables corresponding to the client_id, secret, and tenant:

export AZURE_CLIENT_ID="<client>"
export AZURE_CLIENT_SECRET="<secret>"
export AZURE_TENANT_ID="<tenant>"

(I work on the Azure SDK in Python)

0
votes

According to your description, based on my understanding, I think you want to upload a certificate and use it on Azure App Service.

Per my experience for Azure Python SDK, there seems not to be any Python API for directly uploading a certificate to Azure App Service. However, there is a workaround way for doing it via import a certificate into Azure Key Vault and use it from Azure App Service. And for more details, please see the docuemtn list below.

  1. The Import Certificate REST API of Key Valut. And the related Azure Python API is the method import_certificate from here, you can refer to the reference for key Vault to know how to use it.
  2. There are two documents about using Key Vault certificate from Azue WebApp: Use Azure Key Vault from a Web Application & Deploying Azure Web App Certificate through Key Vault. The Create Or Update REST API of Certificates on Azure App Service is used for deploying, and the related Python API is create_or_update, for which usage, please refer to here.

Hope it helps.


As Azure Python SDK reference of KeyVault for Access Policy said, as below.

Access policies

Some operations require the correct access policies for your credentials.

If you get an “Unauthorized” error, please add the correct access policies to this credentials using the Azure Portal, the Azure CLI or the Key Vault Management SDK itself

Here is the steps for set access policies for certificates operations via Azure CLI.

  1. Get Azure AD service principals for your application, command azure ad sp show --search <your-application-display-name>, then copy the Service Principal Names(spn) like xxxx-xxxx-xxxxx-xxxx-xxxx.

  2. Set policy for certificate operations, command azure keyvault set-policy brucechen --spn <your-applicaiton-spn> --perms-to-certificates <perms-to-certificates, such as [\"all\"]>. Explaination for The <perms-to-certificates> as below.

JSON-encoded array of strings representing certificate operations; each string can be one of [all, get, list, delete, create, import, update, managecontacts, getissuers, listissuers, setissuers, deleteissuer