Pulumi: Function App, Key Vault, and Access Policy

My Brain Dump

How can a Function App access Azure Key Vault secrets?

Known Issue and workaround:

I referenced the issue I was observing and used the recommended work around.

Below is the workaround.

Function App

First, provide an identity value to the Function App declaration:

        Identity = new FunctionAppIdentityArgs { Type = "SystemAssigned" },

Here’s a code snippet that includes the declaration:

    return
        new FunctionApp(functionApp, new FunctionAppArgs()
        {
            Identity = new FunctionAppIdentityArgs { Type = "SystemAssigned" },
            Name     = functionApp,
            Location = resourceGroup.Location,
            ResourceGroupName  = resourceGroup.Name,
            AppServicePlanId   = plan.Id,
            StorageAccountName = storageAccount.Name,
            AppSettings = new InputMap<string>() { appSettings, lookup },
            StorageAccountAccessKey = storageAccount.PrimaryAccessKey
        });
ObjectId = functionApps.First().Identity.Apply(v => v.PrincipalId ?? "11111111-1111-1111-1111-111111111111")

Key Vault

Here’s a code snippet for the Key Vault:

new Classic.KeyVault.Inputs.KeyVaultAccessPolicyArgs
{
    TenantId = current.TenantId,

    //////////////////////////////////////////////////////////////////////
    // THIS LINE
    ObjectId = functionApps.First().Identity.Apply(v => v.PrincipalId ?? "11111111-1111-1111-1111-111111111111"),
    //////////////////////////////////////////////////////////////////////

    KeyPermissions = new[]
    {
        "List", "Create", "Get"
    },
    SecretPermissions = new[]
    {
        "List", "Get", "Set", "Delete", "Purge", "Recover"
    },
},

Here’s the full KeyVault declaration:

using System.Linq;
using Pulumi;
using Pulumi.Azure.AppService;
using Pulumi.AzureNative.Resources;
using System.Collections.Generic;
using Classic = Pulumi.Azure;

namespace IaC.MyApp.Client;

public static class ClassicVault
{
    public static Classic.KeyVault.KeyVault Build(ResourceGroup resourceGroup, string vaultName, IEnumerable<FunctionApp> functionApps)
    {
        var current = Classic.Core.GetClientConfig.InvokeAsync().Result;

        return
            new Classic.KeyVault.KeyVault(vaultName, new Classic.KeyVault.KeyVaultArgs()
            {
                Name     = vaultName,
                Location = resourceGroup.Location,
                ResourceGroupName = resourceGroup.Name,
                EnabledForDiskEncryption = true,
                TenantId = current.TenantId,
                SoftDeleteRetentionDays = 7,
                PurgeProtectionEnabled  = false,
                SkuName = "standard",
                AccessPolicies = new[]
                {
                new Classic.KeyVault.Inputs.KeyVaultAccessPolicyArgs
                {
                     TenantId = current.TenantId,
                     ObjectId = current.ObjectId,
                     KeyPermissions = new[]
                     {
                         "List", "Create", "Get"
                     },
                     SecretPermissions = new[]
                     {
                         "List", "Get", "Set", "Delete", "Purge", "Recover"
                     },
                 },

                new Classic.KeyVault.Inputs.KeyVaultAccessPolicyArgs
                {
                    TenantId = current.TenantId,
                    ObjectId = functionApps.First().Identity.Apply(v => v.PrincipalId ?? "11111111-1111-1111-1111-111111111111"),
                    KeyPermissions = new[]
                    {
                        "List", "Create", "Get"
                    },
                    SecretPermissions = new[]
                    {
                        "List", "Get", "Set", "Delete", "Purge", "Recover"
                    },
                },
            },
            });
}

    }

Declare Azure Resources

var functionApps = FunctionsApps  .Build(resourceGroup, storageAccount, plan, container, busNamespace, authRule, configuration.AppProfiles);
var vault        = ClassicVault   .Build(resourceGroup, KeyVault, functionApps);
var secrets      = ClassicSecrets .Build(vault, new LabelValues(configuration.Secrets));
Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: