Storing Azure Function API Keys

I have recently been deploying Azure Functions and have required API keys for invoking other Azure Functions with in the service.

I first created a registry for storing API keys:

module KeyRegistry

    let mutable keyFor : Map<string,string> = Map.ofSeq <| seq []

I then created the following class to register the API keys:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using Azure.Security.KeyVault.Secrets;
using Azure.Identity;

using static KeyRegistry;
using static System.Environment;
using static Courier.DataTransfer;

namespace Courier.ServiceBus
{
    public static class ServiceKeys
    {
        static Dictionary<string,string> _secrets  = new Dictionary<string, string>();
        static string       _keyVaultName;
        static SecretClient _secretClient;

        static ServiceKeys()
        {
            _keyVaultName = GetEnvironmentVariable("KEY_VAULT_NAME");
            _secrets      = Secrets.Register();

            var vaultUrl   = $"https://{_keyVaultName}.vault.azure.net";
            var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions() { ExcludeVisualStudioCodeCredential = true });
            _secretClient  = new SecretClient(new Uri(vaultUrl), credential);
        }


        public static bool Initialized;

        public static async Task Initialize()
        {
            try
            {
                foreach (var entry in _secrets)
                {
                    var secretName    = entry.Value.ToString();
                    var vaultResponse = await _secretClient.GetSecretAsync(secretName);
                    var secret        = vaultResponse.Value;

                    var host       = secretName.Split('-')[0];
                    var service    = secretName.Split('-')[1];
                    var serviceKey = new ServiceKey(host, service, secret.Value);

                    keyFor = keyFor.Add(serviceKey.Service, serviceKey.Key);
                }

                Initialized = true;
            }

            catch(Exception ex)
            {
                var error = ex.GetBaseException().Message;
                Debug.WriteLine(error);

                throw;
            }
        }
    }
}

The keys could then be used as follows:

let resource(service:string) = DevOps.Configuration.Instance.Value |> function
    | Dev  -> service
    | QA   -> service |> function
              | "MyFn"      -> $"{service}?code={keyFor.[service]}"
              | "MyOtherFn" -> $"{service}?code={keyFor.[service]}"
              | _ -> "Service key not found"

    | PROD -> service |> function
              | "MyFn"      -> $"{service}?code={keyFor.[service]}"
              | "MyOtherFn" -> $"{service}?code={keyFor.[service]}"
              | _ -> "Service key not found"

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: