This tutorial shows you how to use the Dapr secrets API to access secrets from secret stores. Dapr allows us to deploy the same microservice from the local machines to Kubernetes. Correspondingly, this quickstart has instructions for deploying this project locally or in Kubernetes.
This quickstart requires you to have the following installed on your machine:
Also, unless you have already done so, clone the repository with the quickstarts and cd
into the right directory:
git clone [-b <dapr_version_tag>] https://github.com/dapr/quickstarts.git
cd quickstarts
Note: See https://github.com/dapr/quickstarts#supported-dapr-runtime-version for supported tags. Use
git clone https://github.com/dapr/quickstarts.git
when using the edge version of dapr runtime.
Follow instructions to download and install the Dapr CLI and initialize Dapr.
Navigate to the secretstore quickstart and the node folder within that location.
cd secretstore/node
In the app.js
you'll find a simple express
application, which exposes a few routes and handlers. First, take a look at the top of the file:
const daprPort = process.env.DAPR_HTTP_PORT || 3500;
const secretStoreName = process.env.SECRET_STORE;
const secretName = 'mysecret'
The secretStoreName
is read from an environment variable where the value kubernetes
is injected for a Kubernetes deployment and for local development the environment variable must be set to localsecretstore
value.
Next take a look at the getsecret
handler:
app.get('/getsecret', (_req, res) => {
const url = `${secretsUrl}/${secretStoreName}/${secretName}?metadata.namespace=default`
console.log("Fetching URL: %s", url)
fetch(url)
.then(res => res.json())
.then(json => {
let secretBuffer = new Buffer(json["mysecret"])
let encodedSecret = secretBuffer.toString('base64')
console.log("Base64 encoded secret is: %s", encodedSecret)
return res.send(encodedSecret)
})
});
The code gets the the secret called mysecret
from the secret store and displays a Base64 encoded version of the secret.
In secrets.json
file, you'll find a secret mysecret
.
{
"mysecret": "abcd"
}
In the components folder, there is a local-secret-store.yaml
which defines a local file secret store component to be used by Dapr.
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: localsecretstore
namespace: default
spec:
type: secretstores.local.file
version: v1
metadata:
- name: secretsFile
value: secrets.json
- name: nestedSeparator
value: ":"
The component defines a local secret store with the secrets file path as the secrets.json
file.
Note: You can also use a local secret store that uses environment variables for secrets instead of a local file.
Export Secret Store name as environment variable:
Linux/Mac OS:
export SECRET_STORE="localsecretstore"
Windows:
set SECRET_STORE=localsecretstore
Install dependencies
npm install
Run Node.js app with Dapr with the local secret store component:
dapr run --app-id nodeapp --resources-path ./components --app-port 3000 --dapr-http-port 3500 node app.js
The command starts the Dapr application and finally after it is completely initialized, you should see the logs
Updating metadata for app command: node app.js
✅ You're up and running! Both Dapr and your app logs will appear here.
Make a request to the node app to fetch the secret. You can use the command below:
curl -k http://localhost:3000/getsecret
The output should be your base64 encoded secret YWJjZA==
The application logs should be similar to the following:
== APP == Fetching URL: http://localhost:3500/v1.0/secrets/localsecretstore/mysecret?metadata.namespace=default
== APP == Base64 encoded secret is: YWJjZA==
To stop your services from running, simply stop the "dapr run" process. Alternatively, you can spin down each of your services with the Dapr CLI "stop" command. For example, to spin down both services, run these commands in a new command line terminal:
dapr stop --app-id nodeapp
To see that services have stopped running, run dapr list
, noting that your service no longer appears!
The first thing you need is an RBAC enabled Kubernetes cluster. This could be running on your machine using Minikube, or it could be a fully-fledged cluser in Azure using AKS.
Once you have a cluster, follow the steps below to deploy Dapr to it. For more details, see Deploy Dapr on a Kubernetes cluster.
Please note, the CLI will install to the dapr-system namespace by default. If this namespace does not exist, the CLI will create it. If you need to deploy to a different namespace, you can use
-n mynamespace
.
dapr init --kubernetes --wait
Sample output:
⌛ Making the jump to hyperspace...
Note: To install Dapr using Helm, see here: https://docs.dapr.io/getting-started/install-dapr-kubernetes/#install-with-helm-advanced
✅ Deploying the Dapr control plane to your cluster...
✅ Success! Dapr has been installed to namespace dapr-system. To verify, run `dapr status -k' in your terminal. To get started, go here: https://aka.ms/dapr-getting-started
Without the
--wait
flag the Dapr CLI will exit as soon as the kubernetes deployments are created. Kubernetes deployments are asyncronous by default, so we use--wait
here to make sure the dapr control plane is completely deployed and running before continuing.
Dapr can use a number of different secret stores (AWS Secret Manager, Azure Key Vault, GCP Secret Manager, Kubernetes, etc) to retrieve secrets. For this demo, you'll use the Kubernetes secret store (For instructions on other secret stores, please refer to this documentation).
- Add your secret to a file
./mysecret
. For example, if your password is "abcd", then the contents of./mysecret
should be "abcd"
Note: For Windows make sure the file does not contain an extension as the name of the file becomes the metadata key to retrieve the secret.
- Create the secret in the Kubernetes secret store. Note, the name of the secret here is "mysecret" and will be used in a later step.
kubectl create secret generic mysecret --from-file ./mysecret
- You can check that the secret is indeed stored in the Kubernetes secret store by running the command:
kubectl get secret mysecret -o yaml
You can see the output as below where the secret is stored in the secret store in Base64 encoded format
% kubectl get secret mysecret -o yaml
apiVersion: v1
data:
mysecret: U0dmQXAzcUc5Qg==
kind: Secret
metadata:
creationTimestamp: "2020-09-30T17:33:12Z"
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
.: {}
f:mysecret: {}
f:type: {}
manager: kubectl-create
operation: Update
time: "2020-09-30T17:33:12Z"
name: mysecret
namespace: default
resourceVersion: "6617"
selfLink: /api/v1/namespaces/default/secrets/mysecret
uid: 4734ad91-0863-4dec-a200-5e191b8cab20
type: Opaque
kubectl apply -f deploy/node.yaml
Kubernetes deployments are asyncronous. This means you'll need to wait for the deployment to complete before moving on to the next steps. You can do so with the following command:
kubectl rollout status deploy/nodeapp
There are several different ways to access a Kubernetes service depending on which platform you are using. Port forwarding is one consistent way to access a service, whether it is hosted locally or on a cloud Kubernetes provider like AKS.
kubectl port-forward service/nodeapp 8000:80
This will make your service available on http://localhost:8000.
Optional: If you are using a public cloud provider, you can substitue your EXTERNAL-IP address instead of port forwarding. You can find it with:
kubectl get svc nodeapp
Make a request to the node app to fetch the secret. You can use the command below:
curl -k http://localhost:8000/getsecret
The output should be your base64 encoded secret
Now that the node app is running, watch messages come through.
Get the logs of the Node.js app:
kubectl logs --selector=app=node -c node
If all went well, you should see logs like this:
Node App listening on port 3000!
Fetching URL: http://localhost:3500/v1.0/secrets/kubernetes/mysecret?metadata.namespace=default
Base64 encoded secret is: eHl6OTg3Ng==
In these logs, you can see that the node app is making a request to dapr to fetch the secret from the secret store. Note: mysecret is the secret that you created in Step 2
Once you're done, you can spin down your Kubernetes resources by navigating to the ./deploy
directory and running:
kubectl delete -f ./deploy/node.yaml
kubectl delete secret mysecret
This will spin down the node app.
If you want to update the node app, you can do the following:
- Update Node code as you see fit!
- Navigate to the node app directory you want to build a new image for.
- Run
docker build -t <YOUR_IMAGE_NAME> .
. You can name your image whatever you like. If you're planning on hosting it on docker hub, then it should start with<YOUR_DOCKERHUB_USERNAME>/
. - Once your image has built you can see it on your machines by running
docker images
. - To publish your docker image to docker hub (or another registry), first login:
docker login
. Then rundocker push <YOUR IMAGE NAME>
. - Update your .yaml file to reflect the new image name.
- Deploy your updated Dapr enabled app:
kubectl apply -f node.yaml
.
- Explore additional quickstarts