little-library-54601
10/18/2023, 8:57 PM// EXPLANATION OF WHAT'S GOING ON HERE...
//
// For background, see: <https://github.com/pulumi/pulumi-azure-native/issues/578>
//
// TL;DR - Azure has a circular dependency between WebAppHostNameBinding and Certificate
// a) A binding for the FQDN must exist to create a certificate for that FQDN
// b) For the binding to be TLS-enabled, it needs the thumbprint of the certificate
//
// The solution here requires *TWO* "pulumi up" executions:
// 1) Determines that the binding does not exist, so creates it without a thumbprint
// 2) Once the binding exist, creates the certificate and updates the binding with the thumbprint
// (Technically, per Pulumi, it replaces the binding)
var customDnsFqdn = config.Require("CustomDnsFqdn");
// apiAppService and rgName are available in this scope
try
{
var inputArgs = Output.Tuple<string, string>(apiAppService.Name, rgName);
// We don't have access to the app service or resource group names until
// "Apply" can resolve them.
//
// And we can't use the non-async version of "Invoke" because the exception
// thrown when the resource isn't found in that version aborts the program
// immediately - "catch" doesn't work.
inputArgs.Apply(args =>
{
var bindingLookupArgs = new GetWebAppHostNameBindingArgs
{
HostName = customDnsFqdn,
Name = args.Item1,
ResourceGroupName = args.Item2,
};
var bindingLookupResult = GetWebAppHostNameBinding.InvokeAsync(bindingLookupArgs).Result;
return "found";
});
// If we get here, the initial binding exists; so we can create the certificate
// and update the binding
var managedCert = new Certificate("mycertname", new()
{
ServerFarmId = apiAppService.ServerFarmId!,
CanonicalName = customDnsFqdn,
HostNames = new[]
{
customDnsFqdn,
},
Location = "eastus",
ResourceGroupName = rgName
});
var customDomain = new WebAppHostNameBinding("mybindingname", new()
{
HostName = customDnsFqdn,
HostNameType = HostNameType.Verified,
ResourceGroupName = rgName,
Name = apiAppService.Name,
SiteName = apiAppService.Name,
SslState = SslState.SniEnabled,
Thumbprint = managedCert.Thumbprint
});
}
catch
{
<http://Log.Info|Log.Info>($"***** WebAppHostNameBinding DOES NOT EXIST *****");
// Do nothing - we've verified that the resource doesn't exist
// If we get here, we create an initial binding for the FQDN so
// that the subsequent "pulumi up" can create the certificate
var prodCustomDomain = new WebAppHostNameBinding("mybindingname", new()
{
HostName = customDnsFqdn,
HostNameType = HostNameType.Verified,
ResourceGroupName = rgName,
Name = apiAppService.Name,
SiteName = apiAppService.Name
});
}