pepr 0.38.3 → 0.39.0
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/cli/build.d.ts +1 -1
- package/dist/cli/build.d.ts.map +1 -1
- package/dist/cli/build.helpers.d.ts +19 -0
- package/dist/cli/build.helpers.d.ts.map +1 -0
- package/dist/cli/deploy.d.ts.map +1 -1
- package/dist/cli/format.d.ts.map +1 -1
- package/dist/cli/init/index.d.ts.map +1 -1
- package/dist/cli/init/templates.d.ts +6 -2
- package/dist/cli/init/templates.d.ts.map +1 -1
- package/dist/cli/monitor.d.ts.map +1 -1
- package/dist/cli.js +278 -225
- package/dist/controller.js +37 -27
- package/dist/lib/assets/deploy.d.ts.map +1 -1
- package/dist/lib/assets/helm.d.ts +1 -0
- package/dist/lib/assets/helm.d.ts.map +1 -1
- package/dist/lib/assets/index.d.ts +1 -1
- package/dist/lib/assets/index.d.ts.map +1 -1
- package/dist/lib/assets/rbac.d.ts +31 -4
- package/dist/lib/assets/rbac.d.ts.map +1 -1
- package/dist/lib/assets/yaml.d.ts +2 -2
- package/dist/lib/assets/yaml.d.ts.map +1 -1
- package/dist/lib/capability.d.ts +2 -8
- package/dist/lib/capability.d.ts.map +1 -1
- package/dist/lib/controller/store.d.ts +1 -5
- package/dist/lib/controller/store.d.ts.map +1 -1
- package/dist/lib/controller/storeCache.d.ts +11 -0
- package/dist/lib/controller/storeCache.d.ts.map +1 -0
- package/dist/lib/enums.d.ts +17 -0
- package/dist/lib/enums.d.ts.map +1 -0
- package/dist/lib/{adjudicators.d.ts → filter/adjudicators.d.ts} +15 -13
- package/dist/lib/filter/adjudicators.d.ts.map +1 -0
- package/dist/lib/{filter.d.ts → filter/filter.d.ts} +1 -1
- package/dist/lib/filter/filter.d.ts.map +1 -0
- package/dist/lib/helpers.d.ts +1 -2
- package/dist/lib/helpers.d.ts.map +1 -1
- package/dist/lib/k8s.d.ts +1 -1
- package/dist/lib/k8s.d.ts.map +1 -1
- package/dist/lib/logger.d.ts +4 -0
- package/dist/lib/logger.d.ts.map +1 -1
- package/dist/lib/metrics.d.ts.map +1 -1
- package/dist/lib/module.d.ts +5 -0
- package/dist/lib/module.d.ts.map +1 -1
- package/dist/lib/mutate-processor.d.ts.map +1 -1
- package/dist/lib/mutate-request.d.ts +1 -60
- package/dist/lib/mutate-request.d.ts.map +1 -1
- package/dist/lib/types.d.ts +8 -24
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/validate-request.d.ts.map +1 -1
- package/dist/lib/watch-processor.d.ts.map +1 -1
- package/dist/lib.js +220 -295
- package/dist/lib.js.map +4 -4
- package/dist/sdk/cosign.d.ts +18 -0
- package/dist/sdk/cosign.d.ts.map +1 -0
- package/dist/sdk/heredoc.d.ts +2 -0
- package/dist/sdk/heredoc.d.ts.map +1 -0
- package/dist/sdk/sdk.d.ts +1 -2
- package/dist/sdk/sdk.d.ts.map +1 -1
- package/package.json +11 -7
- package/src/cli/build.helpers.ts +28 -0
- package/src/cli/build.ts +124 -121
- package/src/cli/deploy.ts +27 -24
- package/src/cli/dev.ts +3 -3
- package/src/cli/format.ts +3 -6
- package/src/cli/init/index.ts +23 -19
- package/src/cli/monitor.ts +34 -36
- package/src/lib/assets/deploy.ts +12 -3
- package/src/lib/assets/helm.ts +14 -0
- package/src/lib/assets/index.ts +12 -8
- package/src/lib/assets/rbac.ts +69 -17
- package/src/lib/assets/webhooks.ts +1 -1
- package/src/lib/assets/yaml.ts +8 -4
- package/src/lib/capability.ts +7 -12
- package/src/lib/controller/index.ts +3 -3
- package/src/lib/controller/store.ts +42 -202
- package/src/lib/controller/storeCache.ts +63 -0
- package/src/lib/enums.ts +21 -0
- package/src/lib/{adjudicators.ts → filter/adjudicators.ts} +39 -28
- package/src/lib/{filter.ts → filter/filter.ts} +3 -2
- package/src/lib/finalizer.ts +1 -1
- package/src/lib/helpers.ts +19 -15
- package/src/lib/k8s.ts +2 -2
- package/src/lib/logger.ts +41 -0
- package/src/lib/metrics.ts +3 -1
- package/src/lib/module.ts +5 -0
- package/src/lib/mutate-processor.ts +14 -12
- package/src/lib/mutate-request.ts +4 -69
- package/src/lib/types.ts +9 -28
- package/src/lib/validate-processor.ts +1 -1
- package/src/lib/validate-request.ts +2 -1
- package/src/lib/watch-processor.ts +34 -20
- package/src/sdk/cosign.ts +327 -0
- package/src/sdk/heredoc.ts +36 -0
- package/src/sdk/sdk.ts +1 -2
- package/dist/lib/adjudicators.d.ts.map +0 -1
- package/dist/lib/filter.d.ts.map +0 -1
package/src/cli/monitor.ts
CHANGED
|
@@ -49,43 +49,41 @@ export default function (program: RootCmd) {
|
|
|
49
49
|
|
|
50
50
|
for (const line of lines) {
|
|
51
51
|
// Check for `"msg":"Hello Pepr"`
|
|
52
|
-
if (line.includes(respMsg))
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
} catch {
|
|
87
|
-
// Do nothing
|
|
52
|
+
if (!line.includes(respMsg)) continue;
|
|
53
|
+
try {
|
|
54
|
+
const payload = JSON.parse(line.trim());
|
|
55
|
+
const isMutate = payload.res.patchType || payload.res.warnings;
|
|
56
|
+
|
|
57
|
+
const name = `${payload.namespace}${payload.name}`;
|
|
58
|
+
const uid = payload.res.uid;
|
|
59
|
+
|
|
60
|
+
if (isMutate) {
|
|
61
|
+
const plainPatch =
|
|
62
|
+
payload.res?.patch !== undefined && payload.res?.patch !== null
|
|
63
|
+
? atob(payload.res.patch)
|
|
64
|
+
: "";
|
|
65
|
+
|
|
66
|
+
const patch = plainPatch !== "" && JSON.stringify(JSON.parse(plainPatch), null, 2);
|
|
67
|
+
const patchType = payload.res.patchType || payload.res.warnings || "";
|
|
68
|
+
const allowOrDeny = payload.res.allowed ? "🔀" : "🚫";
|
|
69
|
+
console.log(`\n${allowOrDeny} MUTATE ${name} (${uid})`);
|
|
70
|
+
patchType.length > 0 && console.log(`\n\u001b[1;34m${patch}\u001b[0m`);
|
|
71
|
+
} else {
|
|
72
|
+
const failures = Array.isArray(payload.res) ? payload.res : [payload.res];
|
|
73
|
+
|
|
74
|
+
const filteredFailures = failures
|
|
75
|
+
.filter((r: ResponseItem) => !r.allowed)
|
|
76
|
+
.map((r: ResponseItem) => r.status.message);
|
|
77
|
+
|
|
78
|
+
console.log(
|
|
79
|
+
`\n${filteredFailures.length > 0 ? "❌" : "✅"} VALIDATE ${name} (${uid})`,
|
|
80
|
+
);
|
|
81
|
+
console.log(
|
|
82
|
+
filteredFailures.length > 0 ? `\u001b[1;31m${filteredFailures}\u001b[0m` : "",
|
|
83
|
+
);
|
|
88
84
|
}
|
|
85
|
+
} catch {
|
|
86
|
+
// Do nothing
|
|
89
87
|
}
|
|
90
88
|
}
|
|
91
89
|
});
|
package/src/lib/assets/deploy.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import crypto from "crypto";
|
|
5
5
|
import { promises as fs } from "fs";
|
|
6
6
|
import { K8s, kind } from "kubernetes-fluent-client";
|
|
7
|
+
import { V1PolicyRule as PolicyRule } from "@kubernetes/client-node";
|
|
7
8
|
|
|
8
9
|
import { Assets } from ".";
|
|
9
10
|
import Log from "../logger";
|
|
@@ -84,18 +85,25 @@ export async function deploy(assets: Assets, force: boolean, webhookTimeout?: nu
|
|
|
84
85
|
throw new Error("No code provided");
|
|
85
86
|
}
|
|
86
87
|
|
|
87
|
-
await setupRBAC(name, assets.capabilities, force);
|
|
88
|
+
await setupRBAC(name, assets.capabilities, force, assets.config);
|
|
88
89
|
await setupController(assets, code, hash, force);
|
|
89
90
|
await setupWatcher(assets, hash, force);
|
|
90
91
|
}
|
|
91
92
|
|
|
92
|
-
async function setupRBAC(
|
|
93
|
+
async function setupRBAC(
|
|
94
|
+
name: string,
|
|
95
|
+
capabilities: CapabilityExport[],
|
|
96
|
+
force: boolean,
|
|
97
|
+
config: { rbacMode?: string; rbac?: PolicyRule[] },
|
|
98
|
+
) {
|
|
99
|
+
const { rbacMode, rbac } = config;
|
|
100
|
+
|
|
93
101
|
Log.info("Applying cluster role binding");
|
|
94
102
|
const crb = clusterRoleBinding(name);
|
|
95
103
|
await K8s(kind.ClusterRoleBinding).Apply(crb, { force });
|
|
96
104
|
|
|
97
105
|
Log.info("Applying cluster role");
|
|
98
|
-
const cr = clusterRole(name, capabilities);
|
|
106
|
+
const cr = clusterRole(name, capabilities, rbacMode, rbac);
|
|
99
107
|
await K8s(kind.ClusterRole).Apply(cr, { force });
|
|
100
108
|
|
|
101
109
|
Log.info("Applying service account");
|
|
@@ -135,6 +143,7 @@ async function setupController(assets: Assets, code: Buffer, hash: string, force
|
|
|
135
143
|
await K8s(kind.Deployment).Apply(dep, { force });
|
|
136
144
|
}
|
|
137
145
|
|
|
146
|
+
// Setup the watcher deployment and service
|
|
138
147
|
async function setupWatcher(assets: Assets, hash: string, force: boolean) {
|
|
139
148
|
// If the module has a watcher, deploy it
|
|
140
149
|
const watchDeployment = watcher(assets, hash, assets.buildTimestamp);
|
package/src/lib/assets/helm.ts
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
3
|
|
|
4
|
+
export function clusterRoleTemplate() {
|
|
5
|
+
return `
|
|
6
|
+
apiVersion: rbac.authorization.k8s.io/v1
|
|
7
|
+
kind: ClusterRole
|
|
8
|
+
metadata:
|
|
9
|
+
name: {{ .Values.uuid }}
|
|
10
|
+
namespace: pepr-system
|
|
11
|
+
rules:
|
|
12
|
+
{{- if .Values.rbac }}
|
|
13
|
+
{{- toYaml .Values.rbac | nindent 2 }}
|
|
14
|
+
{{- end }}
|
|
15
|
+
`;
|
|
16
|
+
}
|
|
17
|
+
|
|
4
18
|
export function nsTemplate() {
|
|
5
19
|
return `
|
|
6
20
|
apiVersion: v1
|
package/src/lib/assets/index.ts
CHANGED
|
@@ -13,13 +13,20 @@ import { allYaml, zarfYaml, overridesFile, zarfYamlChart } from "./yaml";
|
|
|
13
13
|
import { namespaceComplianceValidator, replaceString } from "../helpers";
|
|
14
14
|
import { createDirectoryIfNotExists, dedent } from "../helpers";
|
|
15
15
|
import { resolve } from "path";
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
chartYaml,
|
|
18
|
+
nsTemplate,
|
|
19
|
+
admissionDeployTemplate,
|
|
20
|
+
watcherDeployTemplate,
|
|
21
|
+
clusterRoleTemplate,
|
|
22
|
+
serviceMonitorTemplate,
|
|
23
|
+
} from "./helm";
|
|
17
24
|
import { promises as fs } from "fs";
|
|
18
25
|
import { webhookConfig } from "./webhooks";
|
|
19
26
|
import { apiTokenSecret, service, tlsSecret, watcherService } from "./networking";
|
|
20
27
|
import { watcher, moduleSecret } from "./pods";
|
|
21
28
|
|
|
22
|
-
import {
|
|
29
|
+
import { clusterRoleBinding, serviceAccount, storeRole, storeRoleBinding } from "./rbac";
|
|
23
30
|
export class Assets {
|
|
24
31
|
readonly name: string;
|
|
25
32
|
readonly tls: TLSOut;
|
|
@@ -61,14 +68,14 @@ export class Assets {
|
|
|
61
68
|
|
|
62
69
|
zarfYamlChart = (path: string) => zarfYamlChart(this, path);
|
|
63
70
|
|
|
64
|
-
allYaml = async (
|
|
71
|
+
allYaml = async (imagePullSecret?: string) => {
|
|
65
72
|
this.capabilities = await loadCapabilities(this.path);
|
|
66
73
|
// give error if namespaces are not respected
|
|
67
74
|
for (const capability of this.capabilities) {
|
|
68
75
|
namespaceComplianceValidator(capability, this.alwaysIgnore?.namespaces);
|
|
69
76
|
}
|
|
70
77
|
|
|
71
|
-
return allYaml(this,
|
|
78
|
+
return allYaml(this, imagePullSecret);
|
|
72
79
|
};
|
|
73
80
|
|
|
74
81
|
generateHelmChart = async (basePath: string) => {
|
|
@@ -123,10 +130,7 @@ export class Assets {
|
|
|
123
130
|
await fs.writeFile(moduleSecretPath, dumpYaml(moduleSecret(this.name, code, this.hash), { noRefs: true }));
|
|
124
131
|
await fs.writeFile(storeRolePath, dumpYaml(storeRole(this.name), { noRefs: true }));
|
|
125
132
|
await fs.writeFile(storeRoleBindingPath, dumpYaml(storeRoleBinding(this.name), { noRefs: true }));
|
|
126
|
-
await fs.writeFile(
|
|
127
|
-
clusterRolePath,
|
|
128
|
-
dumpYaml(clusterRole(this.name, this.capabilities, "rbac"), { noRefs: true }),
|
|
129
|
-
);
|
|
133
|
+
await fs.writeFile(clusterRolePath, dedent(clusterRoleTemplate()));
|
|
130
134
|
await fs.writeFile(clusterRoleBindingPath, dumpYaml(clusterRoleBinding(this.name), { noRefs: true }));
|
|
131
135
|
await fs.writeFile(serviceAccountPath, dumpYaml(serviceAccount(this.name), { noRefs: true }));
|
|
132
136
|
|
package/src/lib/assets/rbac.ts
CHANGED
|
@@ -2,35 +2,63 @@
|
|
|
2
2
|
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
3
|
|
|
4
4
|
import { kind } from "kubernetes-fluent-client";
|
|
5
|
+
import { V1PolicyRule as PolicyRule } from "@kubernetes/client-node";
|
|
5
6
|
import { CapabilityExport } from "../types";
|
|
6
7
|
import { createRBACMap } from "../helpers";
|
|
8
|
+
|
|
7
9
|
/**
|
|
8
|
-
*
|
|
10
|
+
* Creates a Kubernetes ClusterRole based on capabilities and optional custom RBAC rules.
|
|
9
11
|
*
|
|
10
|
-
* @
|
|
11
|
-
* @
|
|
12
|
+
* @param {string} name - The name of the ClusterRole.
|
|
13
|
+
* @param {CapabilityExport[]} capabilities - Array of capabilities defining RBAC rules.
|
|
14
|
+
* @param {string} [rbacMode=""] - The RBAC mode; if "scoped", generates scoped rules, otherwise uses wildcard rules.
|
|
15
|
+
* @returns {kind.ClusterRole} - A Kubernetes ClusterRole object.
|
|
12
16
|
*/
|
|
13
|
-
export function clusterRole(
|
|
17
|
+
export function clusterRole(
|
|
18
|
+
name: string,
|
|
19
|
+
capabilities: CapabilityExport[],
|
|
20
|
+
rbacMode: string = "admin",
|
|
21
|
+
customRbac: PolicyRule[] | undefined,
|
|
22
|
+
): kind.ClusterRole {
|
|
23
|
+
// Create the RBAC map from capabilities
|
|
14
24
|
const rbacMap = createRBACMap(capabilities);
|
|
25
|
+
|
|
26
|
+
// Generate scoped rules from rbacMap
|
|
27
|
+
const scopedRules = Object.keys(rbacMap).map(key => {
|
|
28
|
+
let group: string;
|
|
29
|
+
key.split("/").length < 3 ? (group = "") : (group = key.split("/")[0]);
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
apiGroups: [group],
|
|
33
|
+
resources: [rbacMap[key].plural],
|
|
34
|
+
verbs: rbacMap[key].verbs,
|
|
35
|
+
};
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Merge and deduplicate custom RBAC and scoped rules
|
|
39
|
+
const mergedRBAC = [...(Array.isArray(customRbac) ? customRbac : []), ...scopedRules];
|
|
40
|
+
const deduper: Record<string, PolicyRule & { verbs: string[] }> = {};
|
|
41
|
+
|
|
42
|
+
mergedRBAC.forEach(rule => {
|
|
43
|
+
const key = `${rule.apiGroups}/${rule.resources}`;
|
|
44
|
+
if (deduper[key]) {
|
|
45
|
+
// Deduplicate verbs
|
|
46
|
+
deduper[key].verbs = Array.from(new Set([...deduper[key].verbs, ...rule.verbs]));
|
|
47
|
+
} else {
|
|
48
|
+
deduper[key] = { ...rule, verbs: rule.verbs || [] };
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Convert deduplicated RBAC rules back to an array
|
|
53
|
+
const deduplicatedRules = Object.values(deduper);
|
|
54
|
+
|
|
15
55
|
return {
|
|
16
56
|
apiVersion: "rbac.authorization.k8s.io/v1",
|
|
17
57
|
kind: "ClusterRole",
|
|
18
58
|
metadata: { name },
|
|
19
59
|
rules:
|
|
20
60
|
rbacMode === "scoped"
|
|
21
|
-
?
|
|
22
|
-
...Object.keys(rbacMap).map(key => {
|
|
23
|
-
// let group:string, version:string, kind:string;
|
|
24
|
-
let group: string;
|
|
25
|
-
key.split("/").length < 3 ? (group = "") : (group = key.split("/")[0]);
|
|
26
|
-
|
|
27
|
-
return {
|
|
28
|
-
apiGroups: [group],
|
|
29
|
-
resources: [rbacMap[key].plural],
|
|
30
|
-
verbs: rbacMap[key].verbs,
|
|
31
|
-
};
|
|
32
|
-
}),
|
|
33
|
-
]
|
|
61
|
+
? deduplicatedRules
|
|
34
62
|
: [
|
|
35
63
|
{
|
|
36
64
|
apiGroups: ["*"],
|
|
@@ -41,6 +69,12 @@ export function clusterRole(name: string, capabilities: CapabilityExport[], rbac
|
|
|
41
69
|
};
|
|
42
70
|
}
|
|
43
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Creates a Kubernetes ClusterRoleBinding for a specified ClusterRole.
|
|
74
|
+
*
|
|
75
|
+
* @param {string} name - The name of the ClusterRole to bind.
|
|
76
|
+
* @returns {kind.ClusterRoleBinding} - A Kubernetes ClusterRoleBinding object.
|
|
77
|
+
*/
|
|
44
78
|
export function clusterRoleBinding(name: string): kind.ClusterRoleBinding {
|
|
45
79
|
return {
|
|
46
80
|
apiVersion: "rbac.authorization.k8s.io/v1",
|
|
@@ -61,6 +95,12 @@ export function clusterRoleBinding(name: string): kind.ClusterRoleBinding {
|
|
|
61
95
|
};
|
|
62
96
|
}
|
|
63
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Creates a Kubernetes ServiceAccount with the specified name.
|
|
100
|
+
*
|
|
101
|
+
* @param {string} name - The name of the ServiceAccount.
|
|
102
|
+
* @returns {kind.ServiceAccount} - A Kubernetes ServiceAccount object.
|
|
103
|
+
*/
|
|
64
104
|
export function serviceAccount(name: string): kind.ServiceAccount {
|
|
65
105
|
return {
|
|
66
106
|
apiVersion: "v1",
|
|
@@ -72,6 +112,12 @@ export function serviceAccount(name: string): kind.ServiceAccount {
|
|
|
72
112
|
};
|
|
73
113
|
}
|
|
74
114
|
|
|
115
|
+
/**
|
|
116
|
+
* Creates a Kubernetes Role for managing peprstores in a specified namespace.
|
|
117
|
+
*
|
|
118
|
+
* @param {string} name - The base name of the Role.
|
|
119
|
+
* @returns {kind.Role} - A Kubernetes Role object for peprstores.
|
|
120
|
+
*/
|
|
75
121
|
export function storeRole(name: string): kind.Role {
|
|
76
122
|
name = `${name}-store`;
|
|
77
123
|
return {
|
|
@@ -89,6 +135,12 @@ export function storeRole(name: string): kind.Role {
|
|
|
89
135
|
};
|
|
90
136
|
}
|
|
91
137
|
|
|
138
|
+
/**
|
|
139
|
+
* Creates a Kubernetes RoleBinding for a specified Role in the pepr-system namespace.
|
|
140
|
+
*
|
|
141
|
+
* @param {string} name - The base name of the Role to bind.
|
|
142
|
+
* @returns {kind.RoleBinding} - A Kubernetes RoleBinding object.
|
|
143
|
+
*/
|
|
92
144
|
export function storeRoleBinding(name: string): kind.RoleBinding {
|
|
93
145
|
name = `${name}-store`;
|
|
94
146
|
return {
|
|
@@ -10,7 +10,7 @@ import { kind } from "kubernetes-fluent-client";
|
|
|
10
10
|
import { concat, equals, uniqWith } from "ramda";
|
|
11
11
|
|
|
12
12
|
import { Assets } from ".";
|
|
13
|
-
import { Event } from "../
|
|
13
|
+
import { Event } from "../enums";
|
|
14
14
|
|
|
15
15
|
const peprIgnoreLabel: V1LabelSelectorRequirement = {
|
|
16
16
|
key: "pepr.dev",
|
package/src/lib/assets/yaml.ts
CHANGED
|
@@ -10,9 +10,13 @@ import { deployment, moduleSecret, namespace, watcher } from "./pods";
|
|
|
10
10
|
import { clusterRole, clusterRoleBinding, serviceAccount, storeRole, storeRoleBinding } from "./rbac";
|
|
11
11
|
import { webhookConfig } from "./webhooks";
|
|
12
12
|
import { genEnv } from "./pods";
|
|
13
|
+
|
|
13
14
|
// Helm Chart overrides file (values.yaml) generated from assets
|
|
14
|
-
export async function overridesFile({ hash, name, image, config, apiToken }: Assets, path: string) {
|
|
15
|
+
export async function overridesFile({ hash, name, image, config, apiToken, capabilities }: Assets, path: string) {
|
|
16
|
+
const rbacOverrides = clusterRole(name, capabilities, config.rbacMode, config.rbac).rules;
|
|
17
|
+
|
|
15
18
|
const overrides = {
|
|
19
|
+
rbac: rbacOverrides,
|
|
16
20
|
secrets: {
|
|
17
21
|
apiToken: Buffer.from(apiToken).toString("base64"),
|
|
18
22
|
},
|
|
@@ -219,8 +223,8 @@ export function zarfYamlChart({ name, image, config }: Assets, path: string) {
|
|
|
219
223
|
return dumpYaml(zarfCfg, { noRefs: true });
|
|
220
224
|
}
|
|
221
225
|
|
|
222
|
-
export async function allYaml(assets: Assets,
|
|
223
|
-
const { name, tls, apiToken, path } = assets;
|
|
226
|
+
export async function allYaml(assets: Assets, imagePullSecret?: string) {
|
|
227
|
+
const { name, tls, apiToken, path, config } = assets;
|
|
224
228
|
const code = await fs.readFile(path);
|
|
225
229
|
|
|
226
230
|
// Generate a hash of the code
|
|
@@ -232,7 +236,7 @@ export async function allYaml(assets: Assets, rbacMode: string, imagePullSecret?
|
|
|
232
236
|
|
|
233
237
|
const resources = [
|
|
234
238
|
namespace(assets.config.customLabels?.namespace),
|
|
235
|
-
clusterRole(name, assets.capabilities, rbacMode),
|
|
239
|
+
clusterRole(name, assets.capabilities, config.rbacMode, config.rbac),
|
|
236
240
|
clusterRoleBinding(name),
|
|
237
241
|
serviceAccount(name),
|
|
238
242
|
apiTokenSecret(name, apiToken),
|
package/src/lib/capability.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable max-statements */
|
|
1
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
3
|
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
4
|
|
|
@@ -7,13 +8,13 @@ import Log from "./logger";
|
|
|
7
8
|
import { isBuildMode, isDevMode, isWatchMode } from "./module";
|
|
8
9
|
import { PeprStore, Storage } from "./storage";
|
|
9
10
|
import { OnSchedule, Schedule } from "./schedule";
|
|
11
|
+
import { Event } from "./enums";
|
|
10
12
|
import {
|
|
11
13
|
Binding,
|
|
12
14
|
BindingFilter,
|
|
13
15
|
BindingWithName,
|
|
14
16
|
CapabilityCfg,
|
|
15
17
|
CapabilityExport,
|
|
16
|
-
Event,
|
|
17
18
|
MutateAction,
|
|
18
19
|
MutateActionChain,
|
|
19
20
|
ValidateAction,
|
|
@@ -139,10 +140,8 @@ export class Capability implements CapabilityExport {
|
|
|
139
140
|
|
|
140
141
|
/**
|
|
141
142
|
* Register the store with the capability. This is called automatically by the Pepr controller.
|
|
142
|
-
*
|
|
143
|
-
* @param store
|
|
144
143
|
*/
|
|
145
|
-
registerScheduleStore = () => {
|
|
144
|
+
registerScheduleStore = (): Storage => {
|
|
146
145
|
Log.info(`Registering schedule store for ${this.#name}`);
|
|
147
146
|
|
|
148
147
|
if (this.#scheduleRegistered) {
|
|
@@ -152,9 +151,7 @@ export class Capability implements CapabilityExport {
|
|
|
152
151
|
this.#scheduleRegistered = true;
|
|
153
152
|
|
|
154
153
|
// Pass back any ready callback to the controller
|
|
155
|
-
return
|
|
156
|
-
scheduleStore: this.#scheduleStore,
|
|
157
|
-
};
|
|
154
|
+
return this.#scheduleStore;
|
|
158
155
|
};
|
|
159
156
|
|
|
160
157
|
/**
|
|
@@ -162,7 +159,7 @@ export class Capability implements CapabilityExport {
|
|
|
162
159
|
*
|
|
163
160
|
* @param store
|
|
164
161
|
*/
|
|
165
|
-
registerStore = () => {
|
|
162
|
+
registerStore = (): Storage => {
|
|
166
163
|
Log.info(`Registering store for ${this.#name}`);
|
|
167
164
|
|
|
168
165
|
if (this.#registered) {
|
|
@@ -172,9 +169,7 @@ export class Capability implements CapabilityExport {
|
|
|
172
169
|
this.#registered = true;
|
|
173
170
|
|
|
174
171
|
// Pass back any ready callback to the controller
|
|
175
|
-
return
|
|
176
|
-
store: this.#store,
|
|
177
|
-
};
|
|
172
|
+
return this.#store;
|
|
178
173
|
};
|
|
179
174
|
|
|
180
175
|
/**
|
|
@@ -337,7 +332,7 @@ export class Capability implements CapabilityExport {
|
|
|
337
332
|
event: Event.Update,
|
|
338
333
|
finalizeCallback: async (update: InstanceType<T>, logger = aliasLogger) => {
|
|
339
334
|
Log.info(`Executing finalize action with alias: ${binding.alias || "no alias provided"}`);
|
|
340
|
-
await finalizeCallback(update, logger);
|
|
335
|
+
return await finalizeCallback(update, logger);
|
|
341
336
|
},
|
|
342
337
|
};
|
|
343
338
|
bindings.push(watchBinding);
|
|
@@ -12,7 +12,7 @@ import { metricsCollector, MetricsCollector } from "../metrics";
|
|
|
12
12
|
import { ModuleConfig, isWatchMode } from "../module";
|
|
13
13
|
import { mutateProcessor } from "../mutate-processor";
|
|
14
14
|
import { validateProcessor } from "../validate-processor";
|
|
15
|
-
import {
|
|
15
|
+
import { StoreController } from "./store";
|
|
16
16
|
import { ResponseItem, AdmissionRequest } from "../types";
|
|
17
17
|
|
|
18
18
|
if (!process.env.PEPR_NODE_WARNINGS) {
|
|
@@ -48,12 +48,12 @@ export class Controller {
|
|
|
48
48
|
this.#capabilities = capabilities;
|
|
49
49
|
|
|
50
50
|
// Initialize the Pepr store for each capability
|
|
51
|
-
new
|
|
51
|
+
new StoreController(capabilities, `pepr-${config.uuid}-store`, () => {
|
|
52
52
|
this.#bindEndpoints();
|
|
53
53
|
onReady && onReady();
|
|
54
54
|
Log.info("✅ Controller startup complete");
|
|
55
55
|
// Initialize the schedule store for each capability
|
|
56
|
-
new
|
|
56
|
+
new StoreController(capabilities, `pepr-${config.uuid}-schedule`, () => {
|
|
57
57
|
Log.info("✅ Scheduling processed");
|
|
58
58
|
});
|
|
59
59
|
});
|