Skip to content

Commit 549cf83

Browse files
authored
Merge pull request #203 from vdice/docs/external-variable-providers
docs(topics): add external variable providers guide
2 parents ab91cb8 + 258036c commit 549cf83

File tree

2 files changed

+255
-0
lines changed

2 files changed

+255
-0
lines changed

content/en/docs/topics/assigning-variables.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ weight: 11
1010

1111
By using variables, you can alter application behavior without recompiling your SpinApp. When running in Kubernetes, you can either provide constant values for variables, or reference them from Kubernetes primitives such as `ConfigMaps` and `Secrets`. This tutorial guides your through the process of assigning variables to your `SpinApp`.
1212

13+
> Note: If you'd like to learn how to configure your application with an external variable provider like [Vault](https://vaultproject.io) or [Azure Key Vault](https://azure.microsoft.com/en-us/products/key-vault), see the [External Variable Provider guide](./external-variable-providers.md)
14+
1315
## Prerequisites
1416

1517
For this tutorial in particular, you should either have the Spin Operator [running locally]({{< ref "running-locally" >}}) or [running on your Kubernetes cluster]({{< ref "running-on-a-cluster" >}}).
Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
---
2+
title: External Variable Providers
3+
description: Configure external variable providers for your Spin App.
4+
date: 2024-07-17
5+
categories: [Spin Operator]
6+
tags: [Tutorials]
7+
weight: 12
8+
---
9+
10+
In the [Assigning Variables](./assigning-variables.md) guide, you learned how to configure variables on the SpinApp via its [variables](../reference/spin-app.md#spinappspecvariablesindex) section, either by supplying values in-line or via a Kubernetes ConfigMap or Secret.
11+
12+
You can also utilize an external service like [Vault](https://vaultproject.io) or [Azure Key Vault](https://azure.microsoft.com/en-us/products/key-vault) to provide variable values for your application. This guide will show you how to use and configure both services in tandem with corresponding sample applications.
13+
14+
## Prerequisites
15+
16+
To follow along with this tutorial, you'll need:
17+
18+
- A Kubernetes cluster running SpinKube. See the [Installation](../install/_index.md) guides for more information.
19+
- The [kubectl CLI](https://kubernetes.io/docs/tasks/tools/#kubectl)
20+
- The [spin CLI](https://developer.fermyon.com/spin/v2/install )
21+
- The [kube plugin for Spin](https://github.com/spinkube/spin-plugin-kube?tab=readme-ov-file#install)
22+
23+
## Supported providers
24+
25+
Spin currently supports [Vault](#vault-provider) and [Azure Key Vault](#azure-key-vault-provider) as external variable providers. Configuration is supplied to the application via a [Runtime Configuration file](https://developer.fermyon.com/spin/v2/dynamic-configuration#dynamic-and-runtime-application-configuration).
26+
27+
In SpinKube, this configuration file can be supplied in the form of a Kubernetes secret and linked to a SpinApp via its [runtimeConfig.loadFromSecret](https://www.spinkube.dev/docs/reference/spin-app/#spinappspecruntimeconfig) section.
28+
29+
> Note: `loadFromSecret` takes precedence over any other `runtimeConfig` configuration. Thus, *all* runtime configuration must be contained in the Kubernetes secret, including [SQLite](../reference/spin-app.md#spinappspecruntimeconfigsqlitedatabasesindex), [Key Value](../reference/spin-app.md#spinappspecruntimeconfigkeyvaluestoresindex) and [LLM](../reference/spin-app.md#spinappspecruntimeconfigllmcompute) options that might otherwise be specified via their dedicated specs.
30+
31+
Let's look at examples utilizing specific provider configuration next.
32+
33+
# Vault provider
34+
35+
[Vault](https://vaultproject.io) is a popular choice for storing secrets and serving as a secure key-value store.
36+
37+
This guide assumes you have:
38+
39+
- A [Vault cluster](https://www.vaultproject.io/)
40+
- The [vault CLI](https://developer.hashicorp.com/vault/docs/install)
41+
42+
### Build and publish the Spin application
43+
44+
We'll use the [variable explorer app](https://github.com/spinkube/spin-operator/tree/main/apps/variable-explorer) to test this integration.
45+
46+
First, clone the repository locally and navigate to the `variable-explorer` directory:
47+
48+
```bash
49+
git clone [email protected]:spinkube/spin-operator.git
50+
cd apps/variable-explorer
51+
```
52+
53+
Now, build and push the application to a registry you have access to. Here we'll use [ttl.sh](https://ttl.sh):
54+
55+
```bash
56+
spin build
57+
spin registry push ttl.sh/variable-explorer:1h
58+
```
59+
60+
### Create the `runtime-config.toml` file
61+
62+
Here's a sample `runtime-config.toml` file containing Vault provider configuration:
63+
64+
```toml
65+
[[config_provider]]
66+
type = "vault"
67+
url = "https://my-vault-server:8200"
68+
token = "my_token"
69+
mount = "admin/secret"
70+
```
71+
72+
To use this sample, you'll want to update the `url` and `token` fields with values applicable to your Vault cluster. The `mount` value will depend on the Vault namespace and `kv-v2` secrets engine name. In this sample, the namespace is `admin` and the engine is named `secret`, eg by running `vault secrets enable --path=secret kv-v2`.
73+
74+
### Create the secrets in Vault
75+
76+
Create the `log_level`, `platform_name` and `db_password` secrets used by the variable-explorer application in Vault:
77+
78+
```bash
79+
vault kv put secret/log_level value=INFO
80+
vault kv put secret/platform_name value=Kubernetes
81+
vault kv put secret/db_password value=secret_sauce
82+
```
83+
84+
### Create the SpinApp and Secret
85+
86+
Next, scaffold the SpinApp and Secret resource (containing the `runtime-config.toml` data) together in one go via the `kube` plugin:
87+
88+
```bash
89+
spin kube scaffold -f ttl.sh/variable-explorer:1h -c runtime-config.toml -o scaffold.yaml
90+
```
91+
92+
### Deploy the application
93+
94+
```bash
95+
kubectl apply -f scaffold.yaml
96+
```
97+
98+
### Test the application
99+
100+
You are now ready to test the application and verify that all variables are passed correctly to the SpinApp from the Vault provider.
101+
102+
Configure port forwarding from your local machine to the corresponding Kubernetes `Service`:
103+
104+
```bash
105+
kubectl port-forward services/variable-explorer 8080:80
106+
107+
Forwarding from 127.0.0.1:8080 -> 80
108+
Forwarding from [::1]:8080 -> 80
109+
```
110+
111+
When port forwarding is established, you can send an HTTP request to the variable-explorer from within an additional terminal session:
112+
113+
```bash
114+
curl http://localhost:8080
115+
Hello from Kubernetes
116+
```
117+
118+
Finally, you can use `kubectl logs` to see all logs produced by the variable-explorer at runtime:
119+
120+
```bash
121+
kubectl logs -l core.spinoperator.dev/app-name=variable-explorer
122+
123+
# Log Level: INFO
124+
# Platform Name: Kubernetes
125+
# DB Password: secret_sauce
126+
```
127+
128+
# Azure Key Vault provider
129+
130+
[Azure Key Vault](https://azure.microsoft.com/en-us/products/key-vault) is a secure secret store for distributed applications hosted on the [Azure](https://azure.microsoft.com) platform.
131+
132+
This guide assumes you have:
133+
134+
- An [Azure account](https://azure.microsoft.com/en-us/free/)
135+
- The [az CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli)
136+
137+
### Build and publish the Spin application
138+
139+
We'll use the [Azure Key Vault Provider](https://github.com/fermyon/enterprise-architectures-and-patterns/tree/main/application-variable-providers/azure-key-vault-provider) sample application for this exercise.
140+
141+
First, clone the repository locally and navigate to the `azure-key-vault-provider` directory:
142+
143+
```bash
144+
git clone [email protected]:fermyon/enterprise-architectures-and-patterns.git
145+
cd enterprise-architectures-and-patterns/application-variable-providers/azure-key-vault-provider
146+
```
147+
148+
Now, build and push the application to a registry you have access to. Here we'll use [ttl.sh](https://ttl.sh):
149+
150+
```bash
151+
spin build
152+
spin registry push ttl.sh/azure-key-vault-provider:1h
153+
```
154+
155+
The next steps will guide you in creating and configuring an Azure Key Vault and populating the runtime configuration file with connection credentials.
156+
157+
### Deploy Azure Key Vault
158+
159+
```bash
160+
# Variable Definition
161+
KV_NAME=spinkube-keyvault
162+
LOCATION=westus2
163+
RG_NAME=rg-spinkube-keyvault
164+
165+
# Create Azure Resource Group and Azure Key Vault
166+
az group create -n $RG_NAME -l $LOCATION
167+
az keyvault create -n $KV_NAME \
168+
-g $RG_NAME \
169+
-l $LOCATION \
170+
--enable-rbac-authorization true
171+
172+
# Grab the Azure Resource Identifier of the Azure Key Vault instance
173+
KV_SCOPE=$(az keyvault show -n $KV_NAME -g $RG_NAME -otsv --query "id")
174+
```
175+
176+
### Add a Secret to the Azure Key Vault instance
177+
178+
```bash
179+
# Grab the ID of the currently signed in user in Azure CLI
180+
CURRENT_USER_ID=$(az ad signed-in-user show -otsv --query "id")
181+
182+
# Make the currently signed in user a Key Vault Secrets Officer
183+
# on the scope of the new Azure Key Vault instance
184+
az role assignment create --assignee $CURRENT_USER_ID \
185+
--role "Key Vault Secrets Officer" \
186+
--scope $KV_SCOPE
187+
188+
# Create a test secret called 'secret` in the Azure Key Vault instance
189+
az keyvault secret set -n secret --vault-name $KV_NAME --value secret_value -o none
190+
```
191+
192+
### Create a Service Principal and Role Assignment for Spin
193+
194+
```bash
195+
SP_NAME=sp-spinkube-keyvault
196+
SP=$(az ad sp create-for-rbac -n $SP_NAME -ojson)
197+
198+
CLIENT_ID=$(echo $SP | jq -r '.appId')
199+
CLIENT_SECRET=$(echo $SP | jq -r '.password')
200+
TENANT_ID=$(echo $SP | jq -r '.tenant')
201+
202+
az role assignment create --assignee $CLIENT_ID \
203+
--role "Key Vault Secrets User" \
204+
--scope $KV_SCOPE
205+
```
206+
207+
### Create the `runtime-config.toml` file
208+
209+
Create a `runtime-config.toml` file with the following contents, substituting in the values for `KV_NAME`, `CLIENT_ID`, `CLIENT_SECRET` and `TENANT_ID` from the previous steps.
210+
211+
```toml
212+
[[config_provider]]
213+
type = "azure_key_vault"
214+
vault_url = "https://<$KV_NAME>.vault.azure.net/"
215+
client_id = "<$CLIENT_ID>"
216+
client_secret = "<$CLIENT_SECRET>"
217+
tenant_id = "<$TENANT_ID>"
218+
authority_host = "AzurePublicCloud"
219+
```
220+
221+
### Create the SpinApp and Secret
222+
223+
Scaffold the SpinApp and Secret resource (containing the `runtime-config.toml` data) together in one go via the `kube` plugin:
224+
225+
```bash
226+
spin kube scaffold -f ttl.sh/azure-key-vault-provider:1h -c runtime-config.toml -o scaffold.yaml
227+
```
228+
229+
### Deploy the application
230+
231+
```bash
232+
kubectl apply -f scaffold.yaml
233+
```
234+
235+
### Test the application
236+
237+
Now you are ready to test the application and verify that the secret resolves its value from Azure Key Vault.
238+
239+
Configure port forwarding from your local machine to the corresponding Kubernetes `Service`:
240+
241+
```bash
242+
kubectl port-forward services/azure-key-vault-provider 8080:80
243+
244+
Forwarding from 127.0.0.1:8080 -> 80
245+
Forwarding from [::1]:8080 -> 80
246+
```
247+
248+
When port forwarding is established, you can send an HTTP request to the azure-key-vault-provider app from within an additional terminal session:
249+
250+
```bash
251+
curl http://localhost:8080
252+
Loaded secret from Azure Key Vault: secret_value
253+
```

0 commit comments

Comments
 (0)