@datacules/agent-identity-store-spiffe 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +106 -0
- package/package.json +44 -0
package/README.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# `@datacules/agent-identity-store-spiffe`
|
|
2
|
+
|
|
3
|
+
SPIFFE/SPIRE workload identity credential store for [`@datacules/agent-identity`](https://github.com/hvrcharon1/agent-identity).
|
|
4
|
+
|
|
5
|
+
Instead of static long-lived API keys stored in a vault, this store uses the **SPIFFE Workload API** to fetch short-lived **X.509 SVIDs** (SPIFFE Verifiable Identity Documents) on demand. A full store compromise yields only workload metadata — no usable credential material.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## How it works
|
|
10
|
+
|
|
11
|
+
1. On `resolve()`, the store looks up credential metadata by `ref`.
|
|
12
|
+
2. It calls the SPIRE Workload API socket to fetch the current X.509 SVID bundle for that workload.
|
|
13
|
+
3. The SVID's PEM certificate chain is returned as the live credential value.
|
|
14
|
+
4. Downstream services verify the chain against the trust bundle — no static API key ever travels over the wire.
|
|
15
|
+
5. SVIDs are cached in memory until 5 minutes before expiry (configurable), then re-fetched transparently.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @datacules/agent-identity-store-spiffe @spiffe/spiffe-workload-api
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { SpiffeCredentialStore } from '@datacules/agent-identity-store-spiffe';
|
|
31
|
+
import { createRouterFromStore } from '@datacules/agent-identity';
|
|
32
|
+
|
|
33
|
+
const store = new SpiffeCredentialStore({
|
|
34
|
+
trustDomain: 'acme.org',
|
|
35
|
+
endpointSocket: 'unix:///run/spire/sockets/agent.sock', // or SPIFFE_ENDPOINT_SOCKET env
|
|
36
|
+
credentials: [
|
|
37
|
+
{
|
|
38
|
+
id: 'cred-orders-service',
|
|
39
|
+
ref: 'orders-service', // matched against SVID hint or path segment
|
|
40
|
+
kind: 'fixed',
|
|
41
|
+
name: 'Orders service workload identity',
|
|
42
|
+
scope: 'all',
|
|
43
|
+
status: 'active',
|
|
44
|
+
provider: 'local',
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const router = createRouterFromStore(store, rules, logger);
|
|
50
|
+
const resolved = await router.resolveAsync(ctx);
|
|
51
|
+
// resolved.ref contains the PEM X.509 SVID — pass it to mTLS or a
|
|
52
|
+
// downstream service that verifies SPIFFE SVIDs
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Configuration
|
|
58
|
+
|
|
59
|
+
| Option | Type | Default | Description |
|
|
60
|
+
|--------|------|---------|-------------|
|
|
61
|
+
| `credentials` | `Credential[]` | required | Static metadata for each workload |
|
|
62
|
+
| `endpointSocket` | `string` | `SPIFFE_ENDPOINT_SOCKET` env or `/tmp/spire-agent/public/api.sock` | SPIFFE Workload API socket path |
|
|
63
|
+
| `trustDomain` | `string` | `example.org` | SPIFFE trust domain (e.g. `acme.org`) |
|
|
64
|
+
| `cacheTtlSeconds` | `number` | `3300` (55 min) | How long to cache SVIDs before re-fetching |
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## SVID matching
|
|
69
|
+
|
|
70
|
+
The store matches a credential `ref` to an SVID using three strategies (first match wins):
|
|
71
|
+
|
|
72
|
+
1. **Hint match** — SVID `hint` field equals the credential `ref`
|
|
73
|
+
2. **Path suffix** — SPIFFE ID ends with `/<ref>` (e.g. `spiffe://acme.org/orders-service`)
|
|
74
|
+
3. **Exact SPIFFE ID** — SPIFFE ID equals `spiffe://<trustDomain>/<ref>`
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## SPIRE server setup
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Register a workload entry for your service
|
|
82
|
+
spire-server entry create \
|
|
83
|
+
-spiffeID spiffe://acme.org/orders-service \
|
|
84
|
+
-parentID spiffe://acme.org/agent/prod \
|
|
85
|
+
-selector k8s:pod-label:app:orders-service
|
|
86
|
+
|
|
87
|
+
# The SPIRE agent on the node will attest the workload and issue SVIDs
|
|
88
|
+
# automatically. No API key management required.
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Zero-trust architecture
|
|
94
|
+
|
|
95
|
+
Combine with `@datacules/agent-identity-otel` for full observability:
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { withOtel } from '@datacules/agent-identity-otel';
|
|
99
|
+
|
|
100
|
+
const router = withOtel(
|
|
101
|
+
createRouterFromStore(spiffeStore, rules, logger),
|
|
102
|
+
{ tracer: trace.getTracer('agent-identity') }
|
|
103
|
+
);
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Every SVID fetch, cache hit/miss, and credential resolution is traced.
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@datacules/agent-identity-store-spiffe",
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "SPIFFE/SPIRE workload identity credential store for @datacules/agent-identity",
|
|
5
|
+
"private": false,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/esm/index.js",
|
|
10
|
+
"require": "./dist/cjs/index.js",
|
|
11
|
+
"types": "./dist/types/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"main": "./dist/cjs/index.js",
|
|
15
|
+
"module": "./dist/esm/index.js",
|
|
16
|
+
"types": "./dist/types/index.d.ts",
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc -p tsconfig.build.json && tsc -p tsconfig.cjs.json",
|
|
23
|
+
"type-check": "tsc --noEmit"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@datacules/agent-identity": "*"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"@spiffe/spiffe-workload-api": "^1.0.0"
|
|
30
|
+
},
|
|
31
|
+
"peerDependenciesMeta": {
|
|
32
|
+
"@spiffe/spiffe-workload-api": {
|
|
33
|
+
"optional": true
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"typescript": "^5"
|
|
38
|
+
},
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "https://github.com/hvrcharon1/agent-identity"
|
|
43
|
+
}
|
|
44
|
+
}
|