Ivan L
Ivan L

Reputation: 87

DotNet User secrets stored in Google Secret Manager

I need to deploy a dotnet web app to Google Cloud Run and want to use the user secrets file to store credentials. Currently, they are in appsettings which is not secure. Has anyone done this using Google Secret Manager?

If there are existing examples or snippets they would be appreciated.

Thanks.

Upvotes: 5

Views: 3134

Answers (2)

John Hanley
John Hanley

Reputation: 81454

Google Cloud Run and Google Secret Manager work well together. The key is to grant privileges to the Cloud Run service account to access Secret Manager. This eliminates needing secrets in your application to access Secret Manager.

Access control

Is it best to store the key-value pairs, a json blob?

This depends on the amount of data being stored. Normally you create a secret with a name (secretId) and assign data to the secret (via API or the CLI gcloud). In your application, you read the secret by name (secretId).

I would like to pull the values at startup and not during build time.

The link that Seth Vargo (duplicated here) provided has examples in C# and many other languages. Your application reads secrets from Secret Manager at run-time.

Creating secrets and versions

Guillaume Blaquiere wrote an article showing how to use Secret Manager, Cloud Run and environment variables. Definitely worth reading.

Secret Manager: Improve Cloud Run security without changing the code

Upvotes: 5

granadaCoder
granadaCoder

Reputation: 27904

IMHO, it is "best" to use a dedicated secret-engine.

Most of the secret engines:

Hashicorp Vault << probably the most flexible..some call it the "swiss army knife" of secrets

Thycotic Secret Store

Azure KeyVault (azure cloud)

AKS (AWS) (amazon cloud)

(and your buddy, Google)

are similar.

If you are using Kubernetes, you can code up a concrete that will read values from the Kubernetes "mounted secrets". (I prefer the virtual file mounted secrets).

What I do is create an abstraction, and then code up a concrete(s) to my implmentation choice.

For development environment, you can also code a concrete to this : https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-3.1&tabs=windows

But for production, I use the below abstraction, and code up my concrete to one of the solutions above.

https://pbhadani.com/posts/google-secret-manager/

using System.Threading;
using System.Threading.Tasks;


public interface ISecretRetriever
{
    Task<SecretModel> GetSecret(string secretName);

    Task<SecretModel> GetSecret(string secretName, CancellationToken ct);
}

..

using System.Collections.Generic;
using System.Linq;

[System.Diagnostics.DebuggerDisplay("SecretName='{SecretName}', SubSecretsCount='{SubSecrets.Count}'")]
public class SecretModel
{


    public SecretModel()
    {
        this.SubSecrets = new List<SubSecret>();
    }

    public string SecretName { get; set; }

    public ICollection<SubSecret> SubSecrets { get; set; }
}

..

using System.Security;

[System.Diagnostics.DebuggerDisplay("KeyName = '{KeyName}', SecretValueLength='{null == SecretValue ? 0 : SecretValue.Length}'")]
public class SubSecret
{
    public string KeyName { get; set; }

    public SecureString SecretValue { get; set; }
}

Then your IoC registrations will look something like this:

        if (hostingEnvironment.IsDevelopment()) /* https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.hosting.hostingenvironmentextensions.isdevelopment?view=aspnetcore-3.1 */
        {
            /* code your LowerEnvironmentsInsecureSecretRetriever to https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-3.1&tabs=windows */
            services.AddSingleton<ISecretRetriever, LowerEnvironmentsInsecureSecretRetriever>();
        }
        else
        {
            /* code your HashicorpVaultSecretRetriever to HashicorpVault (or use a different one */
            services.AddSingleton<ISecretRetriever, HashicorpVaultSecretRetriever>();
        }
        

Upvotes: -1

Related Questions