@r8s/recipes 0.1.0 → 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/dist/app.d.ts +11 -2
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +16 -13
- package/dist/app.js.map +1 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +48 -84
- package/dist/auth.js.map +1 -1
- package/dist/database.d.ts +97 -5
- package/dist/database.d.ts.map +1 -1
- package/dist/database.js +196 -86
- package/dist/database.js.map +1 -1
- package/dist/dns-provider.js +1 -1
- package/dist/dns-provider.js.map +1 -1
- package/dist/endpoint-provider.d.ts.map +1 -1
- package/dist/endpoint-provider.js +22 -2
- package/dist/endpoint-provider.js.map +1 -1
- package/dist/endpoint.d.ts +18 -1
- package/dist/endpoint.d.ts.map +1 -1
- package/dist/endpoint.js +92 -37
- package/dist/endpoint.js.map +1 -1
- package/dist/errors.d.ts +16 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +19 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -1
- package/dist/index.js.map +1 -1
- package/dist/operators.d.ts +16 -2
- package/dist/operators.d.ts.map +1 -1
- package/dist/operators.js +26 -0
- package/dist/operators.js.map +1 -1
- package/dist/platform.d.ts +9 -0
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js.map +1 -1
- package/dist/r8s-cluster.d.ts +105 -0
- package/dist/r8s-cluster.d.ts.map +1 -0
- package/dist/r8s-cluster.js +187 -0
- package/dist/r8s-cluster.js.map +1 -0
- package/dist/secret-provider.d.ts +15 -2
- package/dist/secret-provider.d.ts.map +1 -1
- package/dist/secret-provider.js +77 -1
- package/dist/secret-provider.js.map +1 -1
- package/dist/static-secret.d.ts +107 -0
- package/dist/static-secret.d.ts.map +1 -0
- package/dist/static-secret.js +87 -0
- package/dist/static-secret.js.map +1 -0
- package/dist/web-service.d.ts +97 -0
- package/dist/web-service.d.ts.map +1 -1
- package/dist/web-service.js +117 -17
- package/dist/web-service.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.R8sCluster = R8sCluster;
|
|
4
|
+
const core_1 = require("@r8s/core");
|
|
5
|
+
const defaults_1 = require("@r8s/core/defaults");
|
|
6
|
+
const crds_1 = require("@r8s/crds");
|
|
7
|
+
const loki_1 = require("@r8s/crds/loki");
|
|
8
|
+
const logging_1 = require("@r8s/crds/logging");
|
|
9
|
+
const secret_provider_1 = require("./secret-provider");
|
|
10
|
+
const dns_provider_1 = require("./dns-provider");
|
|
11
|
+
const endpoint_provider_1 = require("./endpoint-provider");
|
|
12
|
+
/**
|
|
13
|
+
* R8sCluster — opinionated cluster foundation with all recommended operators.
|
|
14
|
+
*
|
|
15
|
+
* @title R8sCluster
|
|
16
|
+
* @category Complete Solution
|
|
17
|
+
*
|
|
18
|
+
* Sets up a complete cluster foundation in one component:
|
|
19
|
+
* - **cert-manager** for TLS certificate automation
|
|
20
|
+
* - **external-dns** with TSIG for secure DNS updates
|
|
21
|
+
* - **Envoy Gateway** for Gateway API routing
|
|
22
|
+
* - **OpenBao VSO** for secrets management
|
|
23
|
+
* - **Prometheus** for metrics and alerting
|
|
24
|
+
* - **Loki + FluentBit** for log aggregation of all user pods
|
|
25
|
+
*
|
|
26
|
+
* All operators are declared automatically. Children inherit routing,
|
|
27
|
+
* secrets, and DNS contexts — just add your apps.
|
|
28
|
+
*
|
|
29
|
+
* R8sCluster is cluster-scoped — it does not take a namespace. Operators
|
|
30
|
+
* install to their own namespaces (cert-manager, external-dns, etc.).
|
|
31
|
+
* Logging infrastructure lives in a dedicated namespace (default:
|
|
32
|
+
* 'logging'). App namespaces are managed by Platform or the apps
|
|
33
|
+
* themselves.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* import { R8sCluster, Platform, App, Database } from '@r8s/recipes'
|
|
37
|
+
*
|
|
38
|
+
* export default (
|
|
39
|
+
* <>
|
|
40
|
+
* <R8sCluster
|
|
41
|
+
* secrets={{ mount: 'secret', path: 'production' }}
|
|
42
|
+
* dns={{ server: 'ns1.example.com', zone: 'example.com', tsigPath: 'dns/tsig' }}
|
|
43
|
+
* >
|
|
44
|
+
* <Platform namespace="production">
|
|
45
|
+
* <Database name="api-db" storage="20Gi" />
|
|
46
|
+
* <App name="api" image="api:v1" host="api.example.com" />
|
|
47
|
+
* </Platform>
|
|
48
|
+
* </R8sCluster>
|
|
49
|
+
* </>
|
|
50
|
+
* )
|
|
51
|
+
*/
|
|
52
|
+
function R8sCluster(props) {
|
|
53
|
+
const { secrets, dns, gatewayClassName = 'eg', labels, operators: preinstalled = [], logsNamespace = 'logging', logsStorageClass = 'standard', children, } = props;
|
|
54
|
+
// Build the operator list — R8sCluster declares all cluster operators
|
|
55
|
+
// so children don't have to. Children can still declare more (e.g.
|
|
56
|
+
// cnpg, keycloak) via their own logic.
|
|
57
|
+
const sharedOperators = (0, core_1.useContext)(defaults_1.OperatorContext);
|
|
58
|
+
const declared = [];
|
|
59
|
+
const clusterOperators = [
|
|
60
|
+
'cert-manager',
|
|
61
|
+
'external-dns',
|
|
62
|
+
'envoy-gateway',
|
|
63
|
+
'vault-secrets-operator',
|
|
64
|
+
'prometheus',
|
|
65
|
+
'loki',
|
|
66
|
+
'logging-operator',
|
|
67
|
+
];
|
|
68
|
+
for (const opName of clusterOperators) {
|
|
69
|
+
const alreadyDeclared = sharedOperators.some((op) => op.name === opName) ||
|
|
70
|
+
preinstalled.some((op) => op.name === opName) ||
|
|
71
|
+
declared.some((op) => op.name === opName);
|
|
72
|
+
if (!alreadyDeclared && crds_1.operators[opName]) {
|
|
73
|
+
declared.push(crds_1.operators[opName]());
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Build the secrets provider (OpenBao VSO)
|
|
77
|
+
const secretProvider = (0, secret_provider_1.OpenBao)({
|
|
78
|
+
mount: secrets.mount,
|
|
79
|
+
path: secrets.path,
|
|
80
|
+
authRef: secrets.authRef,
|
|
81
|
+
});
|
|
82
|
+
// Build the DNS provider (ExternalDNS with TSIG)
|
|
83
|
+
const dnsProvider = (0, dns_provider_1.ExternalDns)({
|
|
84
|
+
server: dns.server,
|
|
85
|
+
zone: dns.zone,
|
|
86
|
+
tsig: {
|
|
87
|
+
path: dns.tsigPath,
|
|
88
|
+
key: dns.tsigKey ?? 'secret',
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
// Build the endpoint provider (Envoy Gateway)
|
|
92
|
+
const endpointProvider = (0, endpoint_provider_1.EnvoyGateway)({ className: gatewayClassName });
|
|
93
|
+
// Cluster-level logging: FluentBit collects logs from ALL pods
|
|
94
|
+
// and ships to Loki. Resources live in the logs namespace.
|
|
95
|
+
const loggingName = 'cluster-logging';
|
|
96
|
+
const lokiName = 'cluster-loki';
|
|
97
|
+
const lokiOutputName = 'cluster-loki-output';
|
|
98
|
+
const lokiStorageSecret = 'cluster-loki-storage';
|
|
99
|
+
const clusterResources = [];
|
|
100
|
+
// LokiStack — log aggregation backend (in logs namespace)
|
|
101
|
+
clusterResources.push((0, loki_1.LokiStackComponent)({
|
|
102
|
+
metadata: { name: lokiName, namespace: logsNamespace },
|
|
103
|
+
spec: {
|
|
104
|
+
size: '1x.small',
|
|
105
|
+
storageClassName: logsStorageClass,
|
|
106
|
+
storage: {
|
|
107
|
+
schemas: [{ version: 'v13', effectiveDate: '2024-01-01' }],
|
|
108
|
+
secret: { name: lokiStorageSecret, type: 's3' },
|
|
109
|
+
},
|
|
110
|
+
tenants: {
|
|
111
|
+
mode: 'static',
|
|
112
|
+
authentication: [{ tenantName: 'application', tenantId: 'app' }],
|
|
113
|
+
authorization: {
|
|
114
|
+
roles: [
|
|
115
|
+
{
|
|
116
|
+
name: 'app-reader',
|
|
117
|
+
permissions: ['read'],
|
|
118
|
+
resources: ['logs'],
|
|
119
|
+
tenants: ['application'],
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
roleBindings: [
|
|
123
|
+
{
|
|
124
|
+
name: 'app-reader-binding',
|
|
125
|
+
roles: ['app-reader'],
|
|
126
|
+
subjects: [{ kind: 'group', name: 'system:authenticated' }],
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
}));
|
|
133
|
+
// Logging — Banzai Cloud Logging Operator with FluentBit
|
|
134
|
+
// FluentBit runs as a DaemonSet on every node, collecting all
|
|
135
|
+
// container logs from /var/log/containers/.
|
|
136
|
+
clusterResources.push((0, logging_1.LoggingComponent)({
|
|
137
|
+
metadata: { name: loggingName, namespace: logsNamespace },
|
|
138
|
+
spec: {
|
|
139
|
+
fluentd: {},
|
|
140
|
+
fluentbit: {},
|
|
141
|
+
controlNamespace: logsNamespace,
|
|
142
|
+
},
|
|
143
|
+
}));
|
|
144
|
+
// Output — ship logs to Loki gateway
|
|
145
|
+
clusterResources.push((0, logging_1.OutputComponent)({
|
|
146
|
+
metadata: { name: lokiOutputName, namespace: logsNamespace },
|
|
147
|
+
spec: {
|
|
148
|
+
loki: {
|
|
149
|
+
url: `http://loki-gateway.${logsNamespace}.svc.cluster.local`,
|
|
150
|
+
tenant: 'application',
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
}));
|
|
154
|
+
// Flow — match ALL pods (empty selector = match everything)
|
|
155
|
+
clusterResources.push((0, logging_1.FlowComponent)({
|
|
156
|
+
metadata: { name: 'cluster-flow', namespace: logsNamespace },
|
|
157
|
+
spec: {
|
|
158
|
+
match: [{ select: { labels: {} } }],
|
|
159
|
+
localOutputRefs: [lokiOutputName],
|
|
160
|
+
},
|
|
161
|
+
}));
|
|
162
|
+
// Assemble the full context stack. R8sCluster does NOT set a namespace
|
|
163
|
+
// context — it's cluster-scoped. Children (or Platform) handle
|
|
164
|
+
// app namespaces.
|
|
165
|
+
let result = children;
|
|
166
|
+
// Cluster-level resources first (LokiStack, Logging, Flow, Output)
|
|
167
|
+
result = (0, core_1.jsx)(core_1.Fragment, {
|
|
168
|
+
children: [...clusterResources, result],
|
|
169
|
+
});
|
|
170
|
+
// Apply DNS context (inside SecretProvider so it can access TSIG secret)
|
|
171
|
+
result = (0, core_1.jsx)(dns_provider_1.DnsProvider, { provider: dnsProvider, children: result });
|
|
172
|
+
// Apply secrets context (OpenBao VSO)
|
|
173
|
+
result = (0, core_1.jsx)(secret_provider_1.SecretProvider, { provider: secretProvider, children: result });
|
|
174
|
+
// Apply routing context (Envoy Gateway)
|
|
175
|
+
result = (0, core_1.jsx)(endpoint_provider_1.EndpointProvider, { provider: endpointProvider, children: result });
|
|
176
|
+
// Apply operators context — merge parent operators + preinstalled + declared
|
|
177
|
+
const allOperators = [...sharedOperators, ...preinstalled, ...declared];
|
|
178
|
+
if (allOperators.length > 0) {
|
|
179
|
+
result = (0, core_1.jsx)(defaults_1.OperatorContext.Provider, { value: allOperators, children: result });
|
|
180
|
+
}
|
|
181
|
+
// Apply labels context
|
|
182
|
+
if (labels) {
|
|
183
|
+
result = (0, core_1.jsx)(defaults_1.Labels.Provider, { value: labels, children: result });
|
|
184
|
+
}
|
|
185
|
+
return result;
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=r8s-cluster.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"r8s-cluster.js","sourceRoot":"","sources":["../src/r8s-cluster.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
import { type SecretProvider as SecretProviderConfig } from '@r8s/core/defaults';
|
|
1
|
+
import { type SecretProvider as SecretProviderConfig, type SecretProvisioner } from '@r8s/core/defaults';
|
|
2
|
+
/**
|
|
3
|
+
* Provisioner resolution — THE single identity-aware point in the platform.
|
|
4
|
+
* Everything downstream codes against the `provision()` capability; new
|
|
5
|
+
* backends plug in by carrying their own provisioner on the context value
|
|
6
|
+
* (or by being registered here — the orchestration point).
|
|
7
|
+
*/
|
|
8
|
+
export declare function provisionerForSecretProvider(provider: SecretProviderConfig | null | undefined): SecretProvisioner | undefined;
|
|
9
|
+
/** Can this provider provision secrets? (capability check, not identity) */
|
|
10
|
+
export declare function canProvisionSecrets(provider: SecretProviderConfig | null | undefined): provider is SecretProviderConfig;
|
|
2
11
|
/**
|
|
3
12
|
* OpenBao configuration component.
|
|
4
13
|
*
|
|
@@ -14,6 +23,8 @@ export interface OpenBaoProps {
|
|
|
14
23
|
path?: string;
|
|
15
24
|
/** Auth reference (OpenBaoAuth name) */
|
|
16
25
|
authRef?: string;
|
|
26
|
+
/** Re-sync interval for rotation (e.g. '3600s') — rendered as refreshAfter */
|
|
27
|
+
refreshAfter?: string;
|
|
17
28
|
}
|
|
18
29
|
export declare function OpenBao(props: OpenBaoProps): SecretProviderConfig;
|
|
19
30
|
/**
|
|
@@ -26,6 +37,8 @@ export interface VaultProps {
|
|
|
26
37
|
path?: string;
|
|
27
38
|
/** Auth reference (VaultAuth name) */
|
|
28
39
|
authRef?: string;
|
|
40
|
+
/** Re-sync interval for rotation (e.g. '3600s') — rendered as refreshAfter */
|
|
41
|
+
refreshAfter?: string;
|
|
29
42
|
}
|
|
30
43
|
export declare function Vault(props: VaultProps): SecretProviderConfig;
|
|
31
44
|
/**
|
|
@@ -111,7 +124,7 @@ export interface SecretProviderProps {
|
|
|
111
124
|
*
|
|
112
125
|
* export default (
|
|
113
126
|
* <SecretProvider provider="sealed-secrets">
|
|
114
|
-
* <Database name="app-db"
|
|
127
|
+
* <Database name="app-db" />
|
|
115
128
|
* </SecretProvider>
|
|
116
129
|
* )
|
|
117
130
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret-provider.d.ts","sourceRoot":"","sources":["../src/secret-provider.tsx"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"secret-provider.d.ts","sourceRoot":"","sources":["../src/secret-provider.tsx"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,cAAc,IAAI,oBAAoB,EAC3C,KAAK,iBAAiB,EAEvB,MAAM,oBAAoB,CAAA;AAI3B;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,oBAAoB,GAAG,IAAI,GAAG,SAAS,GAChD,iBAAiB,GAAG,SAAS,CAO/B;AAED,4EAA4E;AAC5E,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,oBAAoB,GAAG,IAAI,GAAG,SAAS,GAChD,QAAQ,IAAI,oBAAoB,CAElC;AA2DD;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,iEAAiE;IACjE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,oBAAoB,CAQjE;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,gCAAgC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,oBAAoB,CAQ7D;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,8EAA8E;IAC9E,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,oBAAoB,CAI7E;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;CAAG;AAEtC,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,oBAAoB,CAI7E;AAED,kDAAkD;AAClD,MAAM,MAAM,mBAAmB,GAC7B,SAAS,GAAG,OAAO,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,oBAAoB,CAAA;AAElF,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,QAAQ,EAAE,mBAAmB,CAAA;IAC7B,uBAAuB;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,kCA0CxD"}
|
package/dist/secret-provider.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.provisionerForSecretProvider = provisionerForSecretProvider;
|
|
4
|
+
exports.canProvisionSecrets = canProvisionSecrets;
|
|
3
5
|
exports.OpenBao = OpenBao;
|
|
4
6
|
exports.Vault = Vault;
|
|
5
7
|
exports.SealedSecrets = SealedSecrets;
|
|
@@ -9,12 +11,85 @@ const core_1 = require("@r8s/core");
|
|
|
9
11
|
const defaults_1 = require("@r8s/core/defaults");
|
|
10
12
|
const defaults_2 = require("@r8s/core/defaults");
|
|
11
13
|
const crds_1 = require("@r8s/crds");
|
|
14
|
+
/**
|
|
15
|
+
* Provisioner resolution — THE single identity-aware point in the platform.
|
|
16
|
+
* Everything downstream codes against the `provision()` capability; new
|
|
17
|
+
* backends plug in by carrying their own provisioner on the context value
|
|
18
|
+
* (or by being registered here — the orchestration point).
|
|
19
|
+
*/
|
|
20
|
+
function provisionerForSecretProvider(provider) {
|
|
21
|
+
if (!provider)
|
|
22
|
+
return undefined;
|
|
23
|
+
if (typeof provider.provision === 'function')
|
|
24
|
+
return provider.provision;
|
|
25
|
+
if (provider.backend === 'vault' || provider.backend === 'openbao') {
|
|
26
|
+
return (req) => builtinProvisionStaticSecret(provider, req);
|
|
27
|
+
}
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
/** Can this provider provision secrets? (capability check, not identity) */
|
|
31
|
+
function canProvisionSecrets(provider) {
|
|
32
|
+
return provisionerForSecretProvider(provider) !== undefined;
|
|
33
|
+
}
|
|
34
|
+
/** Built-in Vault/OpenBao emission (VaultStaticSecret / OpenBaoStaticSecret) */
|
|
35
|
+
function builtinProvisionStaticSecret(provider, req) {
|
|
36
|
+
// Two modes: an EXHAUSTIVE bundle (keys/templates given — destination
|
|
37
|
+
// carries exactly those keys, excludeRaw) or a RAW SYNC (empty keys and
|
|
38
|
+
// no templates — destination passes the whole store entry through,
|
|
39
|
+
// legacy Database/operator-contract shape).
|
|
40
|
+
const exhaustive = Object.keys(req.keys).length > 0 || req.templates !== undefined;
|
|
41
|
+
const spec = {
|
|
42
|
+
...(provider.backend === 'vault'
|
|
43
|
+
? { vaultAuthRef: req.authRef ?? provider.authRef }
|
|
44
|
+
: { openbaoAuthRef: req.authRef ?? provider.authRef }),
|
|
45
|
+
mount: req.mount ?? provider.mount,
|
|
46
|
+
type: 'kv-v2',
|
|
47
|
+
path: req.path,
|
|
48
|
+
refreshAfter: req.refreshAfter ?? provider.refreshAfter ?? (exhaustive ? '1h' : undefined),
|
|
49
|
+
...(req.restartTargets && req.restartTargets.length > 0
|
|
50
|
+
? { rolloutRestartTargets: req.restartTargets }
|
|
51
|
+
: {}),
|
|
52
|
+
destination: exhaustive
|
|
53
|
+
? {
|
|
54
|
+
create: true,
|
|
55
|
+
name: req.secretName ?? req.name,
|
|
56
|
+
overwrite: true,
|
|
57
|
+
transformation: {
|
|
58
|
+
excludeRaw: true,
|
|
59
|
+
templates: {
|
|
60
|
+
...Object.fromEntries(Object.entries(req.keys).map(([dest, src]) => [
|
|
61
|
+
dest,
|
|
62
|
+
{ text: `{{ .Secrets.${src} }}` },
|
|
63
|
+
])),
|
|
64
|
+
// Raw passthrough templates (literals, composed templates) win
|
|
65
|
+
// over key-mapped entries on collision
|
|
66
|
+
...Object.fromEntries(Object.entries(req.templates ?? {}).map(([dest, tpl]) => [dest, { text: tpl }])),
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
: { create: true, name: req.secretName ?? req.name },
|
|
71
|
+
};
|
|
72
|
+
return provider.backend === 'vault'
|
|
73
|
+
? (0, core_1.jsx)('VaultStaticSecret', {
|
|
74
|
+
apiVersion: 'secrets.hashicorp.com/v1beta1',
|
|
75
|
+
kind: 'VaultStaticSecret',
|
|
76
|
+
metadata: { name: req.name, namespace: req.namespace },
|
|
77
|
+
spec,
|
|
78
|
+
})
|
|
79
|
+
: (0, core_1.jsx)('OpenBaoStaticSecret', {
|
|
80
|
+
apiVersion: 'secrets.openbao.org/v1beta1',
|
|
81
|
+
kind: 'OpenBaoStaticSecret',
|
|
82
|
+
metadata: { name: req.name, namespace: req.namespace },
|
|
83
|
+
spec,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
12
86
|
function OpenBao(props) {
|
|
13
87
|
return {
|
|
14
88
|
backend: 'openbao',
|
|
15
89
|
mount: props.mount,
|
|
16
90
|
path: props.path,
|
|
17
91
|
authRef: props.authRef,
|
|
92
|
+
...(props.refreshAfter && { refreshAfter: props.refreshAfter }),
|
|
18
93
|
};
|
|
19
94
|
}
|
|
20
95
|
function Vault(props) {
|
|
@@ -23,6 +98,7 @@ function Vault(props) {
|
|
|
23
98
|
mount: props.mount,
|
|
24
99
|
path: props.path,
|
|
25
100
|
authRef: props.authRef,
|
|
101
|
+
...(props.refreshAfter && { refreshAfter: props.refreshAfter }),
|
|
26
102
|
};
|
|
27
103
|
}
|
|
28
104
|
function SealedSecrets(props) {
|
|
@@ -73,7 +149,7 @@ function ManualSecrets(props) {
|
|
|
73
149
|
*
|
|
74
150
|
* export default (
|
|
75
151
|
* <SecretProvider provider="sealed-secrets">
|
|
76
|
-
* <Database name="app-db"
|
|
152
|
+
* <Database name="app-db" />
|
|
77
153
|
* </SecretProvider>
|
|
78
154
|
* )
|
|
79
155
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret-provider.js","sourceRoot":"","sources":["../src/secret-provider.tsx"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"secret-provider.js","sourceRoot":"","sources":["../src/secret-provider.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
export interface StaticSecretProps {
|
|
2
|
+
/**
|
|
3
|
+
* Resource name (also the default for the provisioned Kubernetes
|
|
4
|
+
* Secret's name — override with secretName).
|
|
5
|
+
*/
|
|
6
|
+
name: string;
|
|
7
|
+
/** Kubernetes namespace (inherited from Platform context when omitted) */
|
|
8
|
+
namespace?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Vault/OpenBao KV v2 path holding the source keys, e.g. 'outline/app'.
|
|
11
|
+
* Build it from the provider's base path when composing:
|
|
12
|
+
* `${secretProvider.path}/myapp/credentials`.
|
|
13
|
+
*/
|
|
14
|
+
path: string;
|
|
15
|
+
/**
|
|
16
|
+
* Destination→source key mapping. The destination carries env-case
|
|
17
|
+
* names consumed by the app; the vault/store keys stay snake_case:
|
|
18
|
+
* keys={{ SECRET_KEY: 'secret_key', UTILS_SECRET: 'utils_secret' }}
|
|
19
|
+
* A string array is shorthand for identity mappings ({ KEY: 'KEY' }).
|
|
20
|
+
*
|
|
21
|
+
* Rendered as destination.transformation.templates + excludeRaw —
|
|
22
|
+
* the destination holds ONLY these keys.
|
|
23
|
+
*/
|
|
24
|
+
keys: Record<string, string> | string[];
|
|
25
|
+
/**
|
|
26
|
+
* Raw Go-template passthrough merged AFTER the keys mapping — for
|
|
27
|
+
* advanced bundles needing literals or composed templates
|
|
28
|
+
* (e.g. `AWS_ENDPOINTS: 'https://s3.berget.cloud'`). Passthrough wins
|
|
29
|
+
* over key-mapped entries on collision.
|
|
30
|
+
*/
|
|
31
|
+
templates?: Record<string, string>;
|
|
32
|
+
/** Provisioned Kubernetes Secret name (defaults to name) */
|
|
33
|
+
secretName?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Re-sync interval rendered as refreshAfter. Defaults to the provider's
|
|
36
|
+
* refreshAfter, else '1h'.
|
|
37
|
+
*/
|
|
38
|
+
refreshAfter?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Workloads restarted after rotation (rolloutRestartTargets). Pass the
|
|
41
|
+
* workloads consuming these values so a rotation actually takes effect —
|
|
42
|
+
* pod env vars do not update in place.
|
|
43
|
+
*
|
|
44
|
+
* Deliberately has no default: some consumers read the Secret at use
|
|
45
|
+
* time (e.g. CNPG barman backup credentials are read when a backup
|
|
46
|
+
* runs, and the Cluster CRD is not a supported restart target), so an
|
|
47
|
+
* automatic restart is wrong for them.
|
|
48
|
+
*/
|
|
49
|
+
restart?: {
|
|
50
|
+
kind?: string;
|
|
51
|
+
name: string;
|
|
52
|
+
apiVersion?: string;
|
|
53
|
+
}[];
|
|
54
|
+
/**
|
|
55
|
+
* Auth reference override (defaults to the provider's authRef).
|
|
56
|
+
* Rendered as vaultAuthRef / openbaoAuthRef per backend.
|
|
57
|
+
*/
|
|
58
|
+
authRef?: string;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* StaticSecret — provision a Kubernetes Secret from Vault/OpenBao,
|
|
62
|
+
* with rotation semantics that actually reach the workloads.
|
|
63
|
+
*
|
|
64
|
+
* Wraps VaultStaticSecret / OpenBaoStaticSecret with the platform's
|
|
65
|
+
* conventions baked in:
|
|
66
|
+
* - snake_case source keys templated to env-case destination keys
|
|
67
|
+
* (excludeRaw: only the declared keys land in the Secret)
|
|
68
|
+
* - destination create + overwrite (idempotent sync)
|
|
69
|
+
* - hourly refresh by default, inheriting the provider's refreshAfter
|
|
70
|
+
* - explicit, per-bundle restart semantics (app creds restart pods;
|
|
71
|
+
* backup creds read at use time never restart)
|
|
72
|
+
*
|
|
73
|
+
* Requires an active secrets backend (openbao or vault) — passive
|
|
74
|
+
* backends (manual-secrets, sealed-secrets) cannot provision: reference
|
|
75
|
+
* a pre-created Secret instead.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* import { Platform, StaticSecret } from '@r8s/recipes'
|
|
79
|
+
*
|
|
80
|
+
* export default (
|
|
81
|
+
* <Platform secrets={{ backend: 'openbao', mount: 'kv', path: 'apps' }}>
|
|
82
|
+
* <StaticSecret
|
|
83
|
+
* name="myapp-secrets"
|
|
84
|
+
* path="myapp/app"
|
|
85
|
+
* keys={{
|
|
86
|
+
* SECRET_KEY: 'secret_key',
|
|
87
|
+
* OIDC_CLIENT_ID: 'oidc_client_id',
|
|
88
|
+
* OIDC_CLIENT_SECRET: 'oidc_client_secret',
|
|
89
|
+
* }}
|
|
90
|
+
* restart={[{ kind: 'Deployment', name: 'myapp' }]}
|
|
91
|
+
* />
|
|
92
|
+
* </Platform>
|
|
93
|
+
* )
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* import { Platform, StaticSecret } from '@r8s/recipes'
|
|
97
|
+
*
|
|
98
|
+
* // backup creds: read at use time — never restart workloads
|
|
99
|
+
* export default (
|
|
100
|
+
* <Platform secrets={{ backend: 'openbao', mount: 'kv', path: 'apps' }}>
|
|
101
|
+
* <StaticSecret name="myapp-backup-creds" path="rustfs/myapp"
|
|
102
|
+
* keys={['accesskey', 'secretkey']} />
|
|
103
|
+
* </Platform>
|
|
104
|
+
* )
|
|
105
|
+
*/
|
|
106
|
+
export declare function StaticSecret(props: StaticSecretProps): import("@r8s/core").r8sElement;
|
|
107
|
+
//# sourceMappingURL=static-secret.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static-secret.d.ts","sourceRoot":"","sources":["../src/static-secret.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;;;;;;;OAQG;IACH,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,EAAE,CAAA;IACvC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAChE;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,kCAoDpD"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StaticSecret = StaticSecret;
|
|
4
|
+
const core_1 = require("@r8s/core");
|
|
5
|
+
const defaults_1 = require("@r8s/core/defaults");
|
|
6
|
+
const secret_provider_1 = require("./secret-provider");
|
|
7
|
+
/**
|
|
8
|
+
* StaticSecret — provision a Kubernetes Secret from Vault/OpenBao,
|
|
9
|
+
* with rotation semantics that actually reach the workloads.
|
|
10
|
+
*
|
|
11
|
+
* Wraps VaultStaticSecret / OpenBaoStaticSecret with the platform's
|
|
12
|
+
* conventions baked in:
|
|
13
|
+
* - snake_case source keys templated to env-case destination keys
|
|
14
|
+
* (excludeRaw: only the declared keys land in the Secret)
|
|
15
|
+
* - destination create + overwrite (idempotent sync)
|
|
16
|
+
* - hourly refresh by default, inheriting the provider's refreshAfter
|
|
17
|
+
* - explicit, per-bundle restart semantics (app creds restart pods;
|
|
18
|
+
* backup creds read at use time never restart)
|
|
19
|
+
*
|
|
20
|
+
* Requires an active secrets backend (openbao or vault) — passive
|
|
21
|
+
* backends (manual-secrets, sealed-secrets) cannot provision: reference
|
|
22
|
+
* a pre-created Secret instead.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* import { Platform, StaticSecret } from '@r8s/recipes'
|
|
26
|
+
*
|
|
27
|
+
* export default (
|
|
28
|
+
* <Platform secrets={{ backend: 'openbao', mount: 'kv', path: 'apps' }}>
|
|
29
|
+
* <StaticSecret
|
|
30
|
+
* name="myapp-secrets"
|
|
31
|
+
* path="myapp/app"
|
|
32
|
+
* keys={{
|
|
33
|
+
* SECRET_KEY: 'secret_key',
|
|
34
|
+
* OIDC_CLIENT_ID: 'oidc_client_id',
|
|
35
|
+
* OIDC_CLIENT_SECRET: 'oidc_client_secret',
|
|
36
|
+
* }}
|
|
37
|
+
* restart={[{ kind: 'Deployment', name: 'myapp' }]}
|
|
38
|
+
* />
|
|
39
|
+
* </Platform>
|
|
40
|
+
* )
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* import { Platform, StaticSecret } from '@r8s/recipes'
|
|
44
|
+
*
|
|
45
|
+
* // backup creds: read at use time — never restart workloads
|
|
46
|
+
* export default (
|
|
47
|
+
* <Platform secrets={{ backend: 'openbao', mount: 'kv', path: 'apps' }}>
|
|
48
|
+
* <StaticSecret name="myapp-backup-creds" path="rustfs/myapp"
|
|
49
|
+
* keys={['accesskey', 'secretkey']} />
|
|
50
|
+
* </Platform>
|
|
51
|
+
* )
|
|
52
|
+
*/
|
|
53
|
+
function StaticSecret(props) {
|
|
54
|
+
const { name, namespace: namespaceProp, path, keys, templates, secretName, refreshAfter, restart, authRef, } = props;
|
|
55
|
+
const secretProvider = (0, core_1.useContext)(defaults_1.SecretContext);
|
|
56
|
+
const namespace = (0, defaults_1.useNamespace)(namespaceProp);
|
|
57
|
+
const provisioner = (0, secret_provider_1.provisionerForSecretProvider)(secretProvider);
|
|
58
|
+
if (!provisioner) {
|
|
59
|
+
throw new Error(`StaticSecret "${name}" requires a provisioning secrets backend (openbao, vault,\n` +
|
|
60
|
+
`or any provider carrying a provision() hook).\n` +
|
|
61
|
+
`\n` +
|
|
62
|
+
`Fix: configure a backend on the Platform:\n` +
|
|
63
|
+
` <Platform secrets={{ backend: 'openbao', mount: 'kv', path: 'apps' }}>\n` +
|
|
64
|
+
` <StaticSecret name="${name}" path="${path}" keys={...} />\n` +
|
|
65
|
+
` </Platform>\n` +
|
|
66
|
+
`\n` +
|
|
67
|
+
`On passive backends (manual-secrets, sealed-secrets, kubernetes), create the Secret\n` +
|
|
68
|
+
`out of band and reference it directly instead of rendering this component.`);
|
|
69
|
+
}
|
|
70
|
+
const mapping = Object.fromEntries((Array.isArray(keys) ? keys.map((k) => [k, k]) : Object.entries(keys)));
|
|
71
|
+
// Default missing fields (consistent with Database/WebService restart
|
|
72
|
+
// target conventions)
|
|
73
|
+
const restartTargets = restart?.map((t) => ({ kind: 'Deployment', ...t }));
|
|
74
|
+
const el = provisioner({
|
|
75
|
+
name,
|
|
76
|
+
namespace,
|
|
77
|
+
path,
|
|
78
|
+
keys: mapping,
|
|
79
|
+
templates,
|
|
80
|
+
secretName,
|
|
81
|
+
authRef,
|
|
82
|
+
refreshAfter,
|
|
83
|
+
restartTargets,
|
|
84
|
+
});
|
|
85
|
+
return Array.isArray(el) ? (0, core_1.jsx)(core_1.Fragment, { children: el }) : el;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=static-secret.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static-secret.js","sourceRoot":"","sources":["../src/static-secret.tsx"],"names":[],"mappings":";;AA0GA,oCAoDC;AA9JD,oCAAqD;AACrD,iDAAgE;AAChE,uDAAgE;AA0DhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,SAAgB,YAAY,CAAC,KAAwB;IACnD,MAAM,EACJ,IAAI,EACJ,SAAS,EAAE,aAAa,EACxB,IAAI,EACJ,IAAI,EACJ,SAAS,EACT,UAAU,EACV,YAAY,EACZ,OAAO,EACP,OAAO,GACR,GAAG,KAAK,CAAA;IAET,MAAM,cAAc,GAAG,IAAA,iBAAU,EAAC,wBAAa,CAAC,CAAA;IAChD,MAAM,SAAS,GAAG,IAAA,uBAAY,EAAC,aAAa,CAAC,CAAA;IAC7C,MAAM,WAAW,GAAG,IAAA,8CAA4B,EAAC,cAAc,CAAC,CAAA;IAEhE,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,iBAAiB,IAAI,8DAA8D;YACjF,iDAAiD;YACjD,IAAI;YACJ,6CAA6C;YAC7C,4EAA4E;YAC5E,2BAA2B,IAAI,WAAW,IAAI,mBAAmB;YACjE,iBAAiB;YACjB,IAAI;YACJ,uFAAuF;YACvF,4EAA4E,CAC/E,CAAA;IACH,CAAC;IAED,MAAM,OAAO,GAA2B,MAAM,CAAC,WAAW,CACxD,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAuB,CAC7F,CAAA;IAED,sEAAsE;IACtE,sBAAsB;IACtB,MAAM,cAAc,GAAG,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;IAE1E,MAAM,EAAE,GAAG,WAAW,CAAC;QACrB,IAAI;QACJ,SAAS;QACT,IAAI;QACJ,IAAI,EAAE,OAAO;QACb,SAAS;QACT,UAAU;QACV,OAAO;QACP,YAAY;QACZ,cAAc;KACf,CAAC,CAAA;IACF,OAAO,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAA,UAAG,EAAC,eAAQ,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAE,EAA6B,CAAA;AAC7F,CAAC"}
|