DEV Community

Carlos Mendible
Carlos Mendible

Posted on • Originally published at carlos.mendible.com on

Reading Kubernetes Secrets with Dapr and .NET Core

Dapr is an event-driven, portable runtime for building microservices on cloud and edge.

Dapr supports the fundamental features you’ll need such as: service invocation, state management, publish/subscribe messaging and since version 0.5.0 the ability to read from secret stores!

This post will show you to read kubernetes secrets using Dapr and .NET Core:

Prerequistes

Create an .NET Core project and add dependencies

Open the command line and type:

dotnet new web -o dapr.k8s.secrets
cd dapr.k8s.secrets
dotnet add package Dapr.Client -v 0.5.0-preview02
Enter fullscreen mode Exit fullscreen mode

Update Startup.cs

Update Startup.cs with the following contents in order to expose a secret endpoint and use Dapr to fetch a kubernetes secret:

namespace dapr.k8s.secrets
{
    using System.Text.Json;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.Hosting;
    using Microsoft.Extensions.DependencyInjection;
    using Dapr.Client;
    using System;
    using System.Collections.Generic;

    public class Startup
    {
        // Dapr listens for requets on localhost
        const string localhost = "127.0.0.1";

        // Get the Dapr gRPC port
        static string daprPort => Environment.GetEnvironmentVariable("DAPR_GRPC_PORT") ?? "50001";

        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            // Create Dapr Client
            var client = new DaprClientBuilder()
                .UseEndpoint($"https://{localhost}:{daprPort}")
                .Build();

            // Add the DaprClient to DI.
            services.AddSingleton<DaprClient>(client);
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, DaprClient client)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                // Add the secrets route
                endpoints.MapGet("secret", Secret);
            });

            async Task Secret(HttpContext context)
            {
                // Get the secret from kubernetes
                var secretValues = await client.GetSecretAsync(
                    "kubernetes", // Name of the Dapr Secret Store
                    "super-secret", // Name of the k8s secret
                    new Dictionary<string, string>() { { "namespace", "default" } }); // Namespace where the k8s secret is deployed

                // Get the secret value
                var secretValue = secretValues["super-secret"];

                context.Response.ContentType = "application/json";
                await JsonSerializer.SerializeAsync(context.Response.Body, secretValue);
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Create a Dockerfile with the following contents:

FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS builder
WORKDIR /app
# caches restore result by copying csproj file separately
COPY *.csproj .
RUN dotnet restore
COPY . .
RUN dotnet publish --output /app/ --configuration Release
RUN sed -n 's:.*<AssemblyName>\(.*\)</AssemblyName>.*:\1:p' *.csproj > __assemblyname
RUN if [! -s __assemblyname]; then filename=$(ls *.csproj); echo ${filename%.*} >__assemblyname; fi
# Stage 2
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
WORKDIR /app
COPY --from=builder /app .
ENV PORT 80
EXPOSE 80
ENTRYPOINT dotnet $(cat /app/__assemblyname).dll
Enter fullscreen mode Exit fullscreen mode

Build the Docker image and push it to a container registry

I’ll be pushing the container to Docker Hub:

docker build -t cmendibl3/dapr-k8s-secrets:1.0.0 .
docker push cmendibl3/dapr-k8s-secrets:1.0.0
Enter fullscreen mode Exit fullscreen mode

Create manifest and deploy the application to kubernetes

Create a deployment.yaml with the following contents (remember to replace the image with your own values):

--------
# ASP.NET Core Application
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: dapr-k8s-secrets
namespace: default
spec:
replicas: 1
template:
metadata:
labels:
app: dapr-k8s-secrets
aadpodidbinding: requires-vault
annotations:
dapr.io/enabled: "true"
dapr.io/id: "dapr-k8s-secrets"
dapr.io/port: "80"
spec:
containers:
- name: dapr-k8s-secrets
image: cmendibl3/dapr-k8s-secrets:1.0.0
ports:
- containerPort: 80
imagePullPolicy: Always
--------
# Create a Kubernetes Secret
apiVersion: v1
kind: Secret
metadata:
name: super-secret
namespace: default
type: Opaque
data:
super-secret: eW91ciBzdXBlciBzZWNyZXQK
--------
# If RBAC is enabled in K8s, give the default service account access to read secrets in the default namespace
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: dapr-secret-reader
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: secret-reader
subjects:
- kind: ServiceAccount
name: default
namespace: default
Enter fullscreen mode Exit fullscreen mode

If you haven’t installed Dapr in your kuberntes cluster run:

dapr init --kubernetes
Enter fullscreen mode Exit fullscreen mode

Now deploy the application to kubernetes:

kubectl apply -f ./deployment.yaml
Enter fullscreen mode Exit fullscreen mode

Test the application

Get the pod name and execute a port forward to test the API

$pod = kubectl get po --selector=app=dapr-k8s-secrets -n default -o jsonpath='{.items[*].metadata.name}'
kubectl port-forward $pod 80:80
Enter fullscreen mode Exit fullscreen mode

Run the following command in other terminal:

curl http://localhost/secret
Enter fullscreen mode Exit fullscreen mode

If everything is working you should read:

"your super secret"
Enter fullscreen mode Exit fullscreen mode

Hope it helps!

Please find all code and files here, and learn more about Dapr and the Secret API here

Top comments (0)