Hi, I was wondering if anyone could provide me wit...
# azure
a
Hi, I was wondering if anyone could provide me with some guidance. I'm currently converting my solutions ARM template over to Pulumi. I have Pulumi creating a resource group, app service plan, web app, app insights, a CNAME and TXT record, a hostname binding and a managed certificate however I'm stuck now at the point where I want to update the hostname binding with the certificate thumbprint. Does anyone have any ideas on what this final step entails?
b
I'm not familiar with this nomenclature, can you share some code?
a
I've created a hostname binding using:
Copy code
private WebAppHostNameBinding CreateHostnameBinding(string resourceNamePrefix, ResourceGroup resourceGroup,WebApp webApp, string hostName, RecordSet txtRecord)
    {
        var hostnameBindingArgs = new WebAppHostNameBindingArgs
        {
            Name = webApp.Name,
            ResourceGroupName = resourceGroup.Name,
            SslState = SslState.Disabled,
            CustomHostNameDnsRecordType = CustomHostNameDnsRecordType.CName,
            HostName = hostName,
            HostNameType = HostNameType.Verified,
            AzureResourceType = AzureResourceType.Website,
        };

        var dependsArgs = new CustomResourceOptions
        {
            DependsOn = new InputList<Pulumi.Resource> { txtRecord }
        };

        return new WebAppHostNameBinding($"{resourceNamePrefix}hostnameBinding", hostnameBindingArgs, dependsArgs);         
  }
so that I can then call:
Copy code
private Pulumi.AzureNative.Web.Certificate CreateCertificate(string resourceNamePrefix, ResourceGroup resourceGroup, AppServicePlan appServicePlan, string hostname, WebAppHostNameBinding hostNameBinding )
    {
        var certificateArgs = new Pulumi.AzureNative.Web.CertificateArgs
        {
            Name = $"{resourceNamePrefix}managedCertificate",
            CanonicalName = hostname,
            ResourceGroupName = resourceGroup.Name,
            Location = resourceGroup.Location,
            ServerFarmId = appServicePlan.Id,
        };

        var dependsArgs = new CustomResourceOptions
        {
            DependsOn = new InputList<Pulumi.Resource> { hostNameBinding }
        };

        var managedCertificate = new Pulumi.AzureNative.Web.Certificate($"{resourceNamePrefix}managedCertificate",certificateArgs, dependsArgs);

        return managedCertificate;
    }
to create a managed certificate the final step I need to do is update the hostname binding so that sni is enabled using the managed certificate thumbpring. I thought something along the lines of:
Copy code
private void CreateCustomDomain(string resourceNamePrefix, ResourceGroup resourceGroup, AppServicePlan appServicePlan, WebApp webApp, string hostName, Certificate certificate)
    {
        var customDomainArgs = new Pulumi.AzureNative.AppPlatform.CustomDomainArgs
        {
            AppName = webApp.Name,
            ServiceName = appServicePlan.Name,
            ResourceGroupName = resourceGroup.Name,
            DomainName = hostName,
            Properties = new Pulumi.AzureNative.AppPlatform.Inputs.CustomDomainPropertiesArgs
            {
                CertName = certificate.Name,
                Thumbprint = certificate.Thumbprint
            }
        };

        var dependsArgs = new CustomResourceOptions
        {
            DependsOn = new InputList<Pulumi.Resource> { appServicePlan,webApp,resourceGroup }
        };

        var customDomain = new Pulumi.AzureNative.AppPlatform.CustomDomain($"{resourceNamePrefix}CustomDomain", customDomainArgs, dependsArgs);
    }
but calling this code errors with Code="ParentResourceNotFound" stating that it can't find the specified app service plan
for anyone interested the solution was this:
private void SetHostnameBindingCertificateThumbprint(string resourceNamePrefix, ResourceGroup resourceGroup, Certificate certificate, WebAppHostNameBinding hostNameBinding)
{
var dependsArgs = new CustomResourceOptions
{
DependsOn = new InputList<Pulumi.Resource> { certificate, hostNameBinding }
};
var template = new Dictionary<string, object>
{
{ "$schema", "<https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#>" },
{ "contentVersion", "1.0.0.0" },
{ "resources",new object[]{new Dictionary<string,object> {
{"type","Microsoft.Web/sites/hostnameBindings" },
{"name", hostNameBinding.Name },
{"apiVersion","2020-12-01" },
{"location", resourceGroup.Location },
{"properties", new Dictionary<string,object>{ { "sslState","SniEnabled"},{ "thumbprint", certificate.Thumbprint} } }
} }
}
};
var deploymentArgs = new Pulumi.AzureNative.Resources.DeploymentArgs
{
DeploymentName = $"{ resourceNamePrefix }Deployment-NestedDeployment",
ResourceGroupName = resourceGroup.Name,
Properties = new Pulumi.AzureNative.Resources.Inputs.DeploymentPropertiesArgs
{
Mode = DeploymentMode.Incremental,
Template = template,
}
};
var deployment = new Pulumi.AzureNative.Resources.Deployment($"{resourceNamePrefix}deployment", deploymentArgs, dependsArgs);
}
using Pulumi.AzureNative.Resources.Deployment to run a nested template. The main "gotcha" here is that the documentation for the DeploymentPropertiesArgs says that Template should be a JObject or a "well-formated JSON string" however, after banging my head against my desk for a number of hours trying to figure out what was wrong with the json string I was trying to use (because the deployment kept failing saying that it couldn't deserialize the string to the required structure) I finally google-foo'd my way into a repo where the Template was actually being set as a Dictionary<string,object> as in the code above which actually does work. After that I spend another unspecified amount of time wondering why everything was succeeding but the hostname binding was still missing it's certificate thumbprint and that was because I'd missed the "d" off the end of SniEnable, so don't do that typo.
as a note one issue I've found here is that you have to manually deleted the TLS/SSL binding that's been created via the deployment otherwise pulumi destroy can't remove the certificate and fails