简体   繁体   中英

How to add new certificate for a listener of an Azure Application gateway with Python

everyone.

I am a beginner on Internet and Azure. I have a question about adding a certificate to a listener of an Azure application gateway with Python. I describe my problem in detail as follows.

1. Background

The Azure environment I use is:

Resource group name: My_ResourceGroup
Subscription ID: sub_id
Tenant ID: tenant_id
Client: my_client
Service principal password: sp_password

2. Top-domain and sub-domain

In resource group My_ResourceGroup , there are two Azure DNS providers with zones contoso.com and chen.contoso.com respectively. The contoso.com is the top domain while the chen.contoso.com is the sub-domain.

For chen.contoso.com , I created an A record with name www and IP 10.10.10.10 (note that this IP is just used for testing). I also generated a certificate ( cert.pfx file) for this domain in order to use HTTPS.

3. Install cert.pfx certificate to a listener

I have a off-the-shelf Azure application gateway contoso-appgw in resource group My_ResourceGroup . In this gateway, there is a listener contoso-appgw-hl and there has been a certificate cert0.pfx in this listener .

What I want to do is appending (or, installing) the cert.pfx certificate to the listener contoso-appgw-hl with Azure Python SDK. After this operation, there should be two certificates in listener contoso-appgw-hl : cert0.pfx (the old one) and cert.pfx (the new one).

4. My code and the references

My Python code is as follows:

from azure.common.credentials import ServicePrincipalCredentials
from azure.mgmt.resource import ResourceManagementClient
from azure.mgmt.network import NetworkManagementClient

# Replace this with your subscription id
subscription_id = 'sub_id'

# Tenant ID for your Azure subscription
TENANT_ID = 'tenant_id'

# Your service principal App ID
CLIENT = 'client'

# Your service principal password
KEY = 'sp_password'

credentials = ServicePrincipalCredentials(
        client_id = CLIENT,
        secret = KEY,
        tenant = TENANT_ID
    )

network_client = NetworkManagementClient(credentials, subscription_id)

network_client.application_gateways.create_or_update(
    'My_ResourceGroup',
    'contoso-appgw',
    {
        'location': 'East US 2',
        'http_listeners': [
            {
                'name': 'contoso-appgw-hl',
                'protocol': 'Https',

                'ssl_certificate': {
                    'data': 'cert.pfx',
                    'name': 'chenkui',
                    'password': '123abc'
                }
            }
        ]
    }
)

I wrote my code based on the following resources:

  1. Sample code: azure application manage sample code
  2. Azure document: definition of create_or_update function

Note that the cert.pfx in my code is a Base-64 format certificate because based on the document a Base-64 format certificate is needed.

5. Error message

The above code is failed. The error message shown in Azure Portal --> contoso-appgw --> Activity log of the above code is:

Operation name:
    Create or Update Application Gateway

Error code:
    InvalidRequestFormat

Message:
    Cannot parse the request.

Even I use the Azure Portal (ie instead of using Python code, use GUI Portal in browser), adding the certificate is also failed. The error message shown in Azure Portal --> contoso-appgw --> Activity log is:

Operation name:
    Create or Update Application Gateway

Error code: 
    ApplicationGatewaySslCertificateDataMustBeSpecified

Message:
    Data must be specified for Certificate /subscriptions/c72b5b1b-771e-4b65-ba34-a7db981c9dcf/resourceGroups/My_ResourceGroup/providers/Microsoft.Network/applicationGateways/contoso-appgw/sslCertificates/chenkui.

6. My question

My questions are given as follows:

  1. What are the meaning of these error messages?
  2. Why are these errors given?
  3. What is the problem of my code and how to solve it?

Thank you very much!

If you want to covert listener from http to https, you can use the following powershell script :

$appgw= Get-AzApplicationGateway -Name "AppGWname" -ResourceGroupName "RG Name"

#$listener= Get-AzApplicationGatewayHttpListener -Name listener1 -ApplicationGateway $appgw

$FEC= Get-AzApplicationGatewayFrontendIPConfig -Name "FrontendIP" -ApplicationGateway $appgw


Add-AzApplicationGatewayFrontendPort -ApplicationGateway $appgw -Name "Name of the Port" -Port 443 

$port = Get-AzApplicationGatewayFrontendPort -ApplicationGateway $appgw -Name "Name of Port"

$passwd = ConvertTo-SecureString  "Passoword" -AsPlainText -Force 


Add-AzApplicationGatewaySSLCertificate -Name "Name of the cert" -CertificateFile "Full path of the cert with.pfx" -Password $passwd -ApplicationGateway $appgw

$cert =Get-AzApplicationGatewaySSLCertificate -Name "Name of cert" -ApplicationGateway $appgw

Set-AzApplicationGatewayHttpListener -ApplicationGateway $appgw -Name "Name of the listener" -FrontendIPConfiguration $FEC -FrontendPort $port -Protocol Https -SslCertificate $cert

Set-AzApplicationGateway -ApplicationGateway $appgw

I have found a method to update an existing application gateway. When using create_or_update function to update an existing Azure resource, you must get it first. Otherwise, create_or_update will create a new resource instead of updating an existing one.

The following link is a good example. It creates and updates an Azure VM. Create and manage Windows VMs in Azure using Python

Because creating and managing resources in Azure has a uniform method, we can apply the idea given in above link to manage application gateway. The code is as follows.

import base64

from azure.common.credentials import ServicePrincipalCredentials
from azure.mgmt.resource import ResourceManagementClient
from azure.mgmt.network import NetworkManagementClient
from azure.mgmt.network.v2019_06_01.models import ApplicationGateway, ApplicationGatewaySslCertificate


def test_appgw():
    # create credentials
    credentials = ServicePrincipalCredentials(
            client_id = CLIENT,
            secret = KEY,
            tenant = TENANT_ID
        )

    # create network client
    network_client = NetworkManagementClient(credentials, subscription_id)

    # get an existing application gateway
    app_gw = network_client.application_gateways.get(RESOURCE_GROUP_NAME, APPLICATION_GATEWAY_NAME)

    # read the pfx certificate and convert it to base-64 string
    with open('certificate.pfx', 'rb') as binary_cert:
        base64_cert = base64.b64encode(binary_cert.read())
        cert_data = base64_cert.decode('utf-8')

    # create an SSL certificate
    ssl_cert = ApplicationGatewaySslCertificate(
        name=ANY_NAME_IS_OK,
        data=cert_data,
        password=THE_PASSWARD_USED_TO_CREATE_CERTIFICATE
    )

    # app_gw.ssl_certificates is a Python list, so we append the new certificate in it
    app_gw.ssl_certificates.append(ssl_cert)

    # update the application gateway
    network_client.application_gateways.create_or_update(
        RESOURCE_GROUP_NAME,
        APPLICATION_GATEWAY_NAME,
        app_gw
    )

if __name__ == "__main__":
    test_appgw()

Note:

  1. Using get function to obtain an existing application gateway;
  2. The first parameter name of ApplicationGatewaySslCertificate class is a string. You can use any name you like;
  3. The second parameter data is a string. It is NOT a name of a certificate, but a Base-64 string of the content of a pfx certificate;
  4. The third parameter password is a string. It should be the password by which you create your pfx certificate.

Hope this help you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM