Skip to content

Commit b866ad5

Browse files
committed
docs: add Alauda Build of SPIRE workload security documentation
1 parent 21d7bc8 commit b866ad5

3 files changed

Lines changed: 366 additions & 0 deletions

File tree

.cspell/terms.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ cephclusters
2222
cephfilesystems
2323
cephobjectstores
2424
cephobjectstoreusers
25+
ghostunnel
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
weight: 40
3+
---
4+
5+
# Workload Security
6+
7+
<Overview />
Lines changed: 358 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,358 @@
1+
---
2+
weight: 10
3+
title: SPIRE
4+
---
5+
6+
# Alauda Build of SPIRE
7+
8+
SPIRE (the SPIFFE Runtime Environment) is a toolchain for establishing trust between software systems across a wide variety of hosting platforms. SPIRE exposes the [SPIFFE](https://spiffe.io/) (Secure Production Identity Framework for Everyone) API, which allows workloads to securely authenticate each other without the need for shared secrets or hardcoded credentials.
9+
10+
In the Alauda Container Platform (ACP), SPIRE is provided as a cluster plugin to enhance workload security by providing cryptographically verifiable identities (SVIDs) for all workloads.
11+
12+
## Core Components
13+
14+
The SPIRE plugin includes several components to manage identities:
15+
16+
- **SPIRE Server**: The central authority that manages trust and issues identities.
17+
- **SPIRE Agent**: Runs on every node and delivers identities to local workloads.
18+
- **SPIFFE CSI Driver**: A Container Storage Interface driver that mounts SVIDs as volumes into Pods.
19+
- **SPIRE Controller Manager**: Automates the registration of Kubernetes workloads.
20+
- **OIDC Discovery Provider**: Exposes an OIDC discovery document for SPIRE's trust domain.
21+
22+
## Workflow
23+
24+
The SPIRE plugin operates based on a zero-trust model. The following high-level workflow describes how identities are established and delivered:
25+
26+
1. **Deployment**: The SPIRE Server, Agent, and CSI Driver are deployed as cluster plugins.
27+
2. **Node Attestation**: When a node starts, the SPIRE Agent connects to the SPIRE Server and identifies the node (e.g., using Kubernetes node labels and security tokens).
28+
3. **Agent SVID Issuance**: The SPIRE Server evaluates the node's identity against its policies and issues an **Agent SVID** and a Trust Bundle (CA Certificate) to the Agent.
29+
4. **Workload Request**: A workload (such as a Pod) starts on the node and requests a secure identity from the local SPIRE Agent's Workload API (exposed via the SPIFFE CSI Driver).
30+
5. **Workload Attestation**: The SPIRE Agent gathers metadata about the workload (e.g., namespace, service account, labels) and sends it to the SPIRE Server.
31+
6. **Workload SVID Issuance**: The SPIRE Server verifies the workload information against its registration entries and issues a **Workload SVID**.
32+
7. **SVID Delivery**: The SPIRE Agent receives the SVID and delivers it to the workload. The SPIFFE CSI Driver mounts this identity as a volume into the Pod.
33+
8. **Secure Communication**: The workload now has a cryptographically verifiable identity and can use it to perform mTLS-authenticated communication with other SPIFFE-aware services.
34+
35+
## Installation
36+
37+
### Prerequisites
38+
39+
- A running Alauda Container Platform cluster.
40+
- An available **StorageClass** in the cluster for persistent storage.
41+
- Sufficient resources for the SPIRE stack.
42+
43+
### Install via Console
44+
45+
1. Log in to the ACP console and navigate to **Administrator**.
46+
2. Click **Marketplace** > **Cluster Plugins**.
47+
3. Select the target cluster in the top navigation bar.
48+
4. Search for **Alauda Build of SPIRE** and click to view its details.
49+
5. Click **Install**.
50+
6. In the configuration step, update the following parameters:
51+
- **Cluster Name**: The unique identifier for your cluster (e.g., `dce-cluster`).
52+
- **Trust Domain**: The trust domain name (e.g., `example.org`).
53+
- **Common Name**: The common name for the SPIRE CA.
54+
- **Storage Class**: Select an available storage class for SPIRE Server data storage.
55+
7. Click **Confirm** to complete the installation.
56+
57+
## Usage
58+
59+
### Using SPIFFE IDs in Workloads
60+
61+
Once SPIRE is installed, workloads can obtain their SVIDs using the SPIFFE CSI Driver.
62+
63+
1. **Enable SPIFFE for a Pod**: Add the SPIFFE CSI volume to your Pod specification.
64+
65+
```yaml
66+
apiVersion: v1
67+
kind: Pod
68+
metadata:
69+
name: example-workload
70+
spec:
71+
containers:
72+
- name: app
73+
image: alpine
74+
volumeMounts:
75+
- name: spiffe-workload-api
76+
mountPath: /run/spiffe.io/public
77+
readOnly: true
78+
volumes:
79+
- name: spiffe-workload-api
80+
csi:
81+
driver: 'csi.spiffe.io'
82+
readOnly: true
83+
```
84+
85+
2. **Workload Authentication**: Your application can now use the SPIFFE Workload API at `/run/spiffe.io/public` to retrieve its identity and certificates.
86+
87+
### Workload Registration
88+
89+
By default, the **SPIRE Controller Manager** automatically creates SPIRE entries for Kubernetes workloads based on their labels or service accounts. You can customize this behavior using annotations on your workloads.
90+
91+
### End-to-End Implementation Example
92+
93+
The following example demonstrates a complete SPIRE deployment showing how to set up mutual TLS (mTLS) authentication between workloads using SPIFFE identities.
94+
95+
<Steps>
96+
97+
### Implementation Goals and Architecture
98+
99+
This example shows how to:
100+
101+
- Deploy SPIRE Server and Agent in a single Kubernetes cluster
102+
- Complete Node Attestation using k8s_psat
103+
- Automatically issue SPIFFE IDs and X.509 SVIDs for example workloads
104+
- Verify that authorized workloads can successfully obtain identities while unauthorized workloads cannot
105+
106+
The architecture consists of:
107+
108+
- **Server Workload**: SPIFFE ID `spiffe://example.org/ns/example/sa/server-sa`, retrieves certificates via Workload API, enables mTLS trusting only specific Client SPIFFE ID
109+
- **Client Workload**: SPIFFE ID `spiffe://example.org/ns/example/sa/client-sa`, retrieves certificates via Workload API, accesses Server using mTLS
110+
- Both communicate with **SPIRE Agent** which talks to **SPIRE Server**
111+
112+
### Prerequisites
113+
114+
Before starting, ensure you have:
115+
116+
- A running Kubernetes cluster with storage component deployed
117+
- Kubelet API listening on 127.0.0.1
118+
- The `example` namespace created: `kubectl create namespace example`
119+
120+
### SPIRE Deployment
121+
122+
Deploy SPIRE using the official Helm chart with production-ready configuration:
123+
124+
1. Create a `values.yaml` file with the following content:
125+
126+
```yaml
127+
global:
128+
openshift: false
129+
spire:
130+
recommendations:
131+
enabled: true
132+
namespaces:
133+
create: true
134+
ingressControllerType: ''
135+
clusterName: example-cluster
136+
trustDomain: example.org
137+
caSubject:
138+
country: CN
139+
organization: Example
140+
commonName: example.org
141+
persistence:
142+
storageClass: your-storage-class
143+
```
144+
145+
2. Deploy SPIRE CRDs and main components:
146+
147+
```bash
148+
helm upgrade --install --create-namespace -n spire spire-crds spire-crds \
149+
--repo https://spiffe.github.io/helm-charts-hardened/
150+
151+
helm upgrade --install -n spire spire spire \
152+
--repo https://spiffe.github.io/helm-charts-hardened -f values.yaml
153+
```
154+
155+
3. Verify all pods are running:
156+
157+
```bash
158+
kubectl get pods -n spire
159+
```
160+
161+
Expected output should show all SPIRE components in `Running` state:
162+
163+
```
164+
NAME READY STATUS RESTARTS AGE
165+
spire-agent-xxx 1/1 Running 0 17h
166+
spire-server-0 2/2 Running 0 18h
167+
spire-spiffe-csi-driver-xxx 2/2 Running 0 19h
168+
spire-spiffe-oidc-discovery-provider-xxx 2/2 Running 0 17h
169+
```
170+
171+
### Example Workload Registration
172+
173+
Register the client and server workloads with SPIRE:
174+
175+
1. Register the client workload:
176+
177+
```bash
178+
kubectl exec -n spire spire-server-0 -- \
179+
/opt/spire/bin/spire-server entry create \
180+
-spiffeID spiffe://example.org/ns/example/sa/client-sa \
181+
-parentID spiffe://example.org/ns/spire/sa/spire-agent \
182+
-selector k8s:ns:example
183+
```
184+
185+
2. Register the server workload:
186+
187+
```bash
188+
kubectl exec -n spire spire-server-0 -- \
189+
/opt/spire/bin/spire-server entry create \
190+
-spiffeID spiffe://example.org/ns/example/sa/server-sa \
191+
-parentID spiffe://example.org/ns/spire/sa/spire-agent \
192+
-selector k8s:ns:example
193+
```
194+
195+
Both commands will return entry IDs confirming successful registration.
196+
197+
### Workload Deployment
198+
199+
Deploy the workloads that use ghostunnel to handle mTLS with SPIRE identities.
200+
201+
#### Deploy Server Workload
202+
203+
Create the server workload that exposes an HTTPS endpoint with mTLS:
204+
205+
```yaml
206+
apiVersion: v1
207+
kind: ServiceAccount
208+
metadata:
209+
name: server-sa
210+
namespace: example
211+
---
212+
apiVersion: apps/v1
213+
kind: Deployment
214+
metadata:
215+
name: server-workload
216+
namespace: example
217+
spec:
218+
replicas: 1
219+
selector:
220+
matchLabels:
221+
app: server-workload
222+
template:
223+
metadata:
224+
labels:
225+
app: server-workload
226+
spec:
227+
containers:
228+
- args:
229+
- echo 'Authenticated SPIFFE Content' > index.html && python3 -m http.server 8080 --bind 127.0.0.1
230+
command:
231+
- /bin/sh
232+
- -c
233+
image: python:3.9-alpine
234+
imagePullPolicy: IfNotPresent
235+
name: my-app
236+
ports:
237+
- containerPort: 8080
238+
protocol: TCP
239+
- args:
240+
- server
241+
- --listen
242+
- :8443
243+
- --use-workload-api-addr=unix:/run/spire/sockets/api.sock
244+
- --target
245+
- 127.0.0.1:8080
246+
- --allow-uri
247+
- spiffe://example.org/ns/example/sa/client-sa
248+
image: docker-mirrors.alauda.cn/ghostunnel/ghostunnel:v1.9.0
249+
imagePullPolicy: Always
250+
name: ghostunnel
251+
ports:
252+
- containerPort: 8443
253+
protocol: TCP
254+
volumeMounts:
255+
- mountPath: /run/spire/sockets
256+
name: spiffe-socket
257+
serviceAccount: server-sa
258+
serviceAccountName: server-sa
259+
volumes:
260+
- hostPath:
261+
path: /run/spire/agent-sockets
262+
type: Directory
263+
name: spiffe-socket
264+
```
265+
266+
Apply with: `kubectl apply -f server-workload.yaml`
267+
268+
#### Deploy Client Workload
269+
270+
Create the client workload that connects to the server using mTLS:
271+
272+
```yaml
273+
apiVersion: v1
274+
kind: ServiceAccount
275+
metadata:
276+
name: client-sa
277+
namespace: example
278+
---
279+
apiVersion: apps/v1
280+
kind: Deployment
281+
metadata:
282+
name: client-workload
283+
namespace: example
284+
spec:
285+
replicas: 1
286+
selector:
287+
matchLabels:
288+
app: client-workload
289+
template:
290+
metadata:
291+
labels:
292+
app: client-workload
293+
spec:
294+
serviceAccountName: client-sa
295+
containers:
296+
- args:
297+
- client
298+
- --listen
299+
- 127.0.0.1:8080
300+
- --target
301+
- server-workload:8443
302+
- --use-workload-api-addr=unix:/run/spire/sockets/api.sock
303+
- --verify-uri
304+
- spiffe://example.org/ns/example/sa/server-sa
305+
image: ghostunnel/ghostunnel:v1.9.0
306+
imagePullPolicy: IfNotPresent
307+
name: ghostunnel
308+
ports:
309+
- containerPort: 8080
310+
protocol: TCP
311+
volumeMounts:
312+
- mountPath: /run/spire/sockets
313+
name: spiffe-socket
314+
volumes:
315+
- hostPath:
316+
path: /run/spire/agent-sockets
317+
type: Directory
318+
name: spiffe-socket
319+
```
320+
321+
Apply with: `kubectl apply -f client-workload.yaml`
322+
323+
### Verification
324+
325+
Test the mTLS authentication with success and failure scenarios.
326+
327+
#### Authentication Success
328+
329+
Execute from the client workload pod:
330+
331+
```bash
332+
kubectl exec -n example deploy/client-workload -c ghostunnel -- curl -s http://127.0.0.1:8080
333+
```
334+
335+
**Expected Output:**
336+
337+
```
338+
Authenticated SPIFFE Content
339+
```
340+
341+
This confirms successful mTLS authentication.
342+
343+
#### Authentication Failure
344+
345+
To demonstrate proper security enforcement, modify the client's `--verify-uri` parameter to an incorrect URI (e.g., `spiffe://example.org/ns/example/sa/server` instead of `spiffe://example.org/ns/example/sa/server-sa`):
346+
347+
```bash
348+
kubectl exec -n example deploy/client-workload -c ghostunnel -- curl -s http://127.0.0.1:8080
349+
```
350+
351+
**Expected Result:**
352+
353+
- Command terminates with exit code 56
354+
- Client logs show: `unauthorized: invalid principal, or principal not allowed`
355+
356+
This demonstrates that SPIRE properly enforces authentication and rejects unauthorized connections.
357+
358+
</Steps>

0 commit comments

Comments
 (0)