Google Secret Manager Configuration Provider for ASP.NET Core
Tags: secretmanager, configurationprovider, aspnetcore, appengine
Published: 2021-08-18 21:12:51

If you are brave enough to run ASP.NET Core applications on Google Cloud Platform, sooner or later you will encounter a question on how to store your application settings in a secure way. In Azure we have Key Vault for that purpose, which is nicely integrated with ASP.NET Core thanks to the built-in Configuration Provider. In GCP, the corresponding service is called [Google Secret Manager](https://cloud.google.com/secret-manager).
Secret Manager is a secure and convenient storage system for API keys, passwords, certificates, and other sensitive data, and certainly is a good place to store application settings as well. However there is no integration with ASP.NET Core out of the box.
Fear not! ASP.NET Core supports [Custom configuration providers](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-5.0#custom-configuration-provider), and we will try to develop one for the Google Secret Manager now.

##SecretManagerConfigurationSource 
First of all, we need to create a class that implements IConfigurationSource. The only purpose of which is to return an instance of our custom provider, which we develop shortly.

```C#
public class SecretManagerConfigurationSource : IConfigurationSource
    {
        public IConfigurationProvider Build(IConfigurationBuilder builder)
        {
            return new SecretManagerConfigurationProvider();
        }
    }
```

##SecretManagerConfigurationProvider
Next, let's start creating our main component, SecretManagerConfigurationProvider, which needs to inherit from the ConfigurationProvider abstract class:

```C#
public class SecretManagerConfigurationProvider : ConfigurationProvider
```

To retrieve secrets from the Secret Manager, we can use SecretManagerServiceClient from Google.Cloud.SecretManager.V1 Nuget package. We will also need a Google Project ID where the Secret Manager is enabled and your application is running. 

How can we get a Project ID? We can, for example, put it into applications settings. But in fact, we can get it easily at runtime using Google API:

```C#
public static string GetProjectId()
{
    var instance = Google.Api.Gax.Platform.Instance();
    var projectId = instance?.ProjectId;
    if (string.IsNullOrEmpty(projectId))
    {
        return null;
    }
    return projectId;
}
```
Returning to our Configuration Provider, we are ready to initialize it in the constructor:
```C#
public SecretManagerConfigurationProvider()
{
    _client = SecretManagerServiceClient.Create();
    _projectId = GoogleProject.GetProjectId();
}
```
The next step is to overload the "Load" method and populate a Dictionary of key/value pairs that is exposed as Data property in the parent class.
```C#
var secrets = _client.ListSecrets(new ProjectName(_projectId));
foreach (var secret in secrets)
{
   var secretVersionName = new SecretVersionName(secret.SecretName.ProjectId, secret.SecretName.SecretId, "latest");
   var secretVersion = _client.AccessSecretVersion(secretVersionName);
   Set(secret.SecretName.SecretId, secretVersion.Payload.Data.ToStringUtf8());
}
```

##SecretManagerConfigurationExtensions
Finally, let's add a convenience extension method to easily add our new configuration provider to the ASP.NET Core application.
```C#
public static IConfigurationBuilder AddGoogleSecretsManager(this IConfigurationBuilder configurationBuilder)
{
    configurationBuilder.Add(new SecretManagerConfigurationSource());

    return configurationBuilder;
}
```
Typically, you'd use this method in Program.cs file:
```C#
public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((_, config) => config.AddGoogleSecretsManager())
        .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>());
```

The full source code of Google Secret Manager Configuration Provider, with more error handling, comments, and tests can be found in this Github repo:
{% github https://github.com/i-b1/GoogleSecretManagerConfigurationProvider no-readme %}

More than that, you can download a [IB.Google.SecretManager.ConfigurationProvider NuGet package](https://www.nuget.org/packages/IB.Google.SecretManager.ConfigurationProvider/) and use freely in your projects

And that is essentially everything that was needed to implement a custom configuration provider. Now you can start using Google Secret Manager to store your applications settings in a more secure way, simplify your CD pipelines by removing those variables from different stages, and stop worrying about those pesky cat hackers.

![cat hacker](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ljfwvfv43kekas0qdqi.png)<sub><sup>(Image credit: iridi/Getty Images)</sup></sub>