To secure an Azure Function App with a custom SSL certificate, you need to accomplish a few tasks:
- Create an Azure Function App.
- Upload the custom SSL certificate to Azure.
- Bind the SSL certificate to the custom domain associated with the Function App.
Here is a step-by-step program written in Python using Pulumi to deploy an Azure Function App and secure it with a custom SSL certificate:
Step 1: Starting Setup
You should have the Pulumi CLI installed and configured for Azure use. Your custom SSL certificate should be ready, and you need to have the domain ownership verified in Azure if it's not managed by Azure.
Step 2: Writing the Pulumi Program
For this example, we'll use the azure-native
package, which directly exposes the Azure Resource Manager (ARM) API, enabling fine-grained control over resources and features.
Before running the program, ensure you have the following:
- The custom SSL certificate file in PFX format.
- The password for the PFX certificate.
- The Azure Function App package you want to deploy.
import pulumifrom pulumi import Outputimport pulumi_azure as azurefrom pulumi_azure_native import webfrom pulumi_azure_native import resources# Replace these variables with your own informationRESOURCE_GROUP_NAME = "my-resource-group"STORAGE_ACCOUNT_NAME = "mystorageaccount"FUNCTION_APP_NAME = "my-function-app"APP_SERVICE_PLAN_NAME = "my-app-service-plan"CUSTOM_DOMAIN_NAME = "www.my-custom-domain.com"PFX_CERTIFICATE_PATH = "path/to/your/certificate.pfx"CERTIFICATE_PASSWORD = "your-certificate-password"# Create an Azure Resource Groupresource_group = resources.ResourceGroup(RESOURCE_GROUP_NAME)# Create an Azure Storage Account for the Function App to usestorage_account = azure.storage.Account(STORAGE_ACCOUNT_NAME, resource_group_name=resource_group.name, account_replication_type="LRS", account_tier="Standard", location=resource_group.location)# Create an App Service Plan for hosting the Function Appapp_service_plan = web.AppServicePlan(APP_SERVICE_PLAN_NAME, resource_group_name=resource_group.name, location=resource_group.location, kind="FunctionApp", sku=web.SkuDescriptionArgs( name="Y1", tier="Dynamic" ))# Create the Function Appfunction_app = web.WebApp(FUNCTION_APP_NAME, resource_group_name=resource_group.name, location=resource_group.location, server_farm_id=app_service_plan.id, site_config=web.SiteConfigArgs( app_settings=[ web.NameValuePairArgs(name="FUNCTIONS_EXTENSION_VERSION", value="~3"), web.NameValuePairArgs(name="FUNCTIONS_WORKER_RUNTIME", value="dotnet"), # Update the runtime accordingly web.NameValuePairArgs(name="WEBSITE_RUN_FROM_PACKAGE", value="url_to_your_function_app_package"), web.NameValuePairArgs(name="AzureWebJobsStorage", value=storage_account.primary_connection_string), ], https_only=True # Enforce HTTPS ))# Upload the SSL certificate (the certificate needs to be in PFX format)cert_blob = pulumi.FileAsset(PFX_CERTIFICATE_PATH)ssl_cert = web.Certificate("custom-ssl-cert", resource_group_name=resource_group.name, location=resource_group.location, password=CERTIFICATE_PASSWORD, pfx_blob=Output.secret(cert_blob.__getattribute__("_internal_data")), server_farm_id=app_service_plan.id)# Bind the custom domain and SSL certificate to the Function Apphostname_binding = web.WebAppCustomHostnameBinding("custom-domain-binding", resource_group_name=resource_group.name, hostname=CUSTOM_DOMAIN_NAME, web_app_name=function_app.name)ssl_binding = web.WebAppHostnameBinding("ssl-binding", resource_group_name=resource_group.name, name=function_app.name, hostname=CUSTOM_DOMAIN_NAME, ssl_state=web.SslState.SNI_ENABLED, thumbprint=ssl_cert.thumbprint)# Export the Function App URLpulumi.export("function_app_url", function_app.default_host_name.apply(lambda host_name: f"https://{host_name}"))# Export the custom domain SSL binding thumbprintpulumi.export("ssl_thumbprint", ssl_cert.thumbprint)
Step 3: Deploying with Pulumi
Run pulumi up
in your command-line interface where the above code is saved as __main__.py
. After reviewing the resource changes in the preview shown by Pulumi, confirm the deployment to create the resources in Azure.
Explanation of Resources
ResourceGroup
: A container that holds related resources for an Azure solution.Account
: An Azure Storage Account which the Function App will use to store its data.AppServicePlan
: Defines a set of compute resources where Azure App Services (including Function Apps) run.WebApp
: Represents the Function App resource itself.Certificate
: Represents the SSL certificate that will be uploaded to Azure and associated with the Function App.WebAppCustomHostnameBinding
: Binds the custom domain to the Function App.WebAppHostnameBinding
: Associates the SSL certificate (through its thumbprint) with the custom domain binding.
Please note that you need to have the custom domain registered and verified in Azure to bind the SSL certificate to the Function App successfully. The WEBSITE_RUN_FROM_PACKAGE
app setting should point to the zip file containing your Function App's code – for example, a URL to a blob in Azure Blob storage where the package is stored.
Be careful with your SSL certificates and sensitive data like passwords and connection strings. Use Pulumi's Output.secret()
to ensure they aren't printed to the console. Always review best practices regarding the security of your cloud resources.