In all previous posts, we were looking at the Dapr service invocation building block. We have seen how to expose and call HTTP and gRPC services using it. In this post, we will see how Dapr ease developers life when it comes to deal with secrets, thanks to the secrets management building block.

Introduction

The little application used to illustrate the Dapr secrets management building block is leveraging Twitter and Tweetinvi an intuitive Twitter C# library for the REST and Stream API. To be able to run the application you will need to create a Twitter app. When you have created the application you will need to get the API key & secret, the Access token & secret as described on the Tweetinvi Getting Started, Steps to create my first credentials. Those four pieces of information are the ones which we want to keep secret.

Dapr secrets management building block

The secrets management building block is a building block that comes with a new capability which we didn’t talk about in the previous posts, the components.

Dapr uses a modular design where functionality is delivered as a component. Each component has an interface definition. All of the components are pluggable so that you can swap out one component with the same interface for another.

A building block can use any combination of components.

This is one of the great power of Dapr. Here is the interface declaration for the secrets management building block which each component needs to implement.

SecretStore
1
2
3
4
5
6
7
8
9
10
type SecretStore interface {
// Init authenticates with the actual secret store and performs other init operation
Init(metadata Metadata) error

// GetSecret retrieves a secret using a key and returns a map of decrypted string/string values
GetSecret(req GetSecretRequest) (GetSecretResponse, error)

// BulkGetSecrets retrieves all secrets in the store and returns a map of decrypted string/string values
BulkGetSecret(req BulkGetSecretRequest) (BulkGetSecretResponse, error)
}

Currently, we can have access transparently to all of those components to handle secrets:

In this post, we are using local file storage to store the Twitter secrets, which should be used only for development. This could be easily replaced by one of the other components for production.

Client

Components folder

This is the first time we are seeing the components folder in which you can define components for your application. In today’s post, we are defining a local secret store for local development and this is the only thing you would need to change when you would be ready to go into production with your application. The super nice part is that you could go to Azure, AWS, Google Cloud Platform, or any places in which secret components exist just by the change of a configuration file.

local-secret-store.yaml
1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: local-secret-store
namespace: default
spec:
type: secretstores.local.file
metadata:
- name: secretsFile
value: ./client/components/secrets.json
- name: nestedSeparator
value: ":"

In this configuration we are defining the name of the component, local-secret-store to be able to reference it from our code. Then, the type of component secretstores.local.file and where the secret file is stored.

And here is the local secrets file.

You should not push this file to your code repository, as it contains your secrets!

secrets.json
1
2
3
4
5
6
7
8
{
"twitterSecrets": {
"consumerKey": "TOADD",
"consumerSecret": "TOADD",
"accessToken": "TOADD",
"accessSecret": "TOADD"
}
}

Starting Dapr sidecar

You can use the start.ps1 PowerShell script if you have Windows Terminal installed, and it will start the Dapr sidecar. It executes the following:

dapr.exe run –dapr-grpc-port 50001 –components-path .\client\components\

We just define the default gRPC port which the Dapr .NET SDK will be using in our application to connect to the secrets building block and the local file storage component to get the secrets. We also need to tell Dapr in which folder our components are defined.

Application

Our super simple application is again a C# 9 top-level statements application using the Dapr .NET SDK to access the Dapr secrets building block and the local file storage component by calling one of its API GetBulkSecretAsync. Then we build a twitterClient using Tweetinvi getting information from the authenticated user, of which you provided the secrets, to display her description.

Program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using System;
using System.Linq;
using Dapr.Client;
using Tweetinvi;

Console.WriteLine("Hello Dapr secrets!");

var daprClient = new DaprClientBuilder().Build();

var twitterSecrets = daprClient.GetBulkSecretAsync("local-secret-store").Result;

var consumerKey = twitterSecrets["twitterSecrets:consumerKey"].Values.First();
var consumerSecret = twitterSecrets["twitterSecrets:consumerSecret"].Values.First();
var accessToken = twitterSecrets["twitterSecrets:accessToken"].Values.First();
var accessSecret = twitterSecrets["twitterSecrets:accessSecret"].Values.First();

var twitterClient =
new TwitterClient(consumerKey, consumerSecret, accessToken, accessSecret);

var user = await twitterClient.Users.GetAuthenticatedUserAsync();
Console.WriteLine(user.Description);

Here you can see the result:

Hello Dapr secrets!
Team Leader, Distinguished Solution Architect with a passion for shipping high quality products by empowering development team and culture

Conclusion

We have seen that Dapr provides a very easy and nice way to retrieve secrets that will be used by your application. From a security point of view, this provides the advantage to not store your secrets in your application code or on system environment variables. It also provides an abstraction on top of a set of secrets stores which let you develop your application without being tight to concrete implementation and let you choose at the time of deployment which secrets store your want to use, without changing one line of code of your application.

You can get access to the code of this blog post on GitHub in the Secrets folder.