pepr 0.42.0 → 0.42.2
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 -0
- package/dist/cli/build.d.ts.map +1 -1
- package/dist/cli/build.helpers.d.ts +66 -0
- package/dist/cli/build.helpers.d.ts.map +1 -1
- package/dist/cli/deploy.d.ts +15 -0
- package/dist/cli/deploy.d.ts.map +1 -1
- package/dist/cli/dev.d.ts.map +1 -1
- package/dist/cli/format.d.ts.map +1 -1
- package/dist/cli/format.helpers.d.ts +3 -0
- package/dist/cli/format.helpers.d.ts.map +1 -0
- package/dist/cli/init/enums.d.ts +10 -0
- package/dist/cli/init/enums.d.ts.map +1 -0
- package/dist/cli/init/index.d.ts.map +1 -1
- package/dist/cli/init/templates.d.ts +15 -11
- package/dist/cli/init/templates.d.ts.map +1 -1
- package/dist/cli/init/utils.d.ts.map +1 -1
- package/dist/cli/init/walkthrough.d.ts +3 -2
- package/dist/cli/init/walkthrough.d.ts.map +1 -1
- package/dist/cli/kfc.d.ts.map +1 -1
- package/dist/cli/monitor.d.ts +23 -0
- package/dist/cli/monitor.d.ts.map +1 -1
- package/dist/cli/root.d.ts.map +1 -1
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/uuid.d.ts.map +1 -1
- package/dist/cli.js +483 -586
- package/dist/controller.js +1 -195
- package/dist/fixtures/loader.d.ts.map +1 -1
- package/dist/lib/assets/deploy.d.ts.map +1 -1
- package/dist/lib/assets/destroy.d.ts.map +1 -1
- package/dist/lib/assets/helm.d.ts +1 -1
- 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/pods.d.ts +6 -22
- package/dist/lib/assets/pods.d.ts.map +1 -1
- package/dist/lib/assets/rbac.d.ts.map +1 -1
- package/dist/lib/assets/webhooks.d.ts.map +1 -1
- package/dist/lib/assets/yaml.d.ts.map +1 -1
- package/dist/lib/controller/index.d.ts +2 -2
- package/dist/lib/controller/index.d.ts.map +1 -1
- package/dist/lib/controller/store.d.ts +1 -2
- package/dist/lib/controller/store.d.ts.map +1 -1
- package/dist/lib/controller/storeCache.d.ts +2 -1
- package/dist/lib/controller/storeCache.d.ts.map +1 -1
- package/dist/lib/{capability.d.ts → core/capability.d.ts} +1 -1
- package/dist/lib/core/capability.d.ts.map +1 -0
- package/dist/lib/{module.d.ts → core/module.d.ts} +2 -2
- package/dist/lib/core/module.d.ts.map +1 -0
- package/dist/lib/core/queue.d.ts.map +1 -0
- package/dist/lib/{schedule.d.ts → core/schedule.d.ts} +0 -1
- package/dist/lib/core/schedule.d.ts.map +1 -0
- package/dist/lib/{storage.d.ts → core/storage.d.ts} +4 -4
- package/dist/lib/core/storage.d.ts.map +1 -0
- package/dist/lib/deploymentChecks.d.ts.map +1 -1
- package/dist/lib/errors.d.ts +0 -5
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/filesystemService.d.ts.map +1 -1
- package/dist/lib/filter/adjudicators/adjudicators.d.ts +5 -4
- package/dist/lib/filter/adjudicators/adjudicators.d.ts.map +1 -1
- package/dist/lib/filter/filter.d.ts +33 -1
- package/dist/lib/filter/filter.d.ts.map +1 -1
- package/dist/lib/finalizer.d.ts.map +1 -1
- package/dist/lib/helpers.d.ts +4 -9
- package/dist/lib/helpers.d.ts.map +1 -1
- package/dist/lib/included-files.d.ts.map +1 -1
- package/dist/lib/mutate-request.d.ts +2 -2
- package/dist/lib/mutate-request.d.ts.map +1 -1
- package/dist/lib/processors/mutate-processor.d.ts +28 -0
- package/dist/lib/processors/mutate-processor.d.ts.map +1 -0
- package/dist/lib/processors/validate-processor.d.ts +9 -0
- package/dist/lib/processors/validate-processor.d.ts.map +1 -0
- package/dist/lib/{watch-processor.d.ts → processors/watch-processor.d.ts} +2 -2
- package/dist/lib/processors/watch-processor.d.ts.map +1 -0
- package/dist/lib/telemetry/logger.d.ts.map +1 -1
- package/dist/lib/telemetry/metrics.d.ts.map +1 -1
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/validate-request.d.ts +2 -2
- package/dist/lib/validate-request.d.ts.map +1 -1
- package/dist/lib.d.ts +2 -2
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +508 -341
- package/dist/lib.js.map +4 -4
- package/dist/sdk/heredoc.d.ts.map +1 -1
- package/package.json +9 -9
- package/src/cli/build.helpers.ts +180 -0
- package/src/cli/build.ts +85 -133
- package/src/cli/deploy.ts +113 -74
- package/src/cli/dev.ts +2 -2
- package/src/cli/format.helpers.ts +27 -0
- package/src/cli/format.ts +4 -18
- package/src/cli/init/enums.ts +9 -0
- package/src/cli/init/index.ts +4 -3
- package/src/cli/init/templates.ts +30 -2
- package/src/cli/init/utils.ts +3 -3
- package/src/cli/init/walkthrough.ts +7 -8
- package/src/cli/kfc.ts +1 -1
- package/src/cli/monitor.ts +108 -65
- package/src/cli/root.ts +1 -1
- package/src/cli/update.ts +1 -1
- package/src/cli/uuid.ts +1 -1
- package/src/fixtures/loader.ts +2 -2
- package/src/lib/assets/deploy.ts +11 -11
- package/src/lib/assets/destroy.ts +1 -1
- package/src/lib/assets/helm.ts +6 -6
- package/src/lib/assets/index.ts +23 -23
- package/src/lib/assets/pods.ts +11 -6
- package/src/lib/assets/webhooks.ts +31 -46
- package/src/lib/assets/yaml.ts +12 -9
- package/src/lib/controller/index.ts +13 -11
- package/src/lib/controller/store.ts +25 -12
- package/src/lib/controller/storeCache.ts +16 -3
- package/src/lib/{capability.ts → core/capability.ts} +25 -14
- package/src/lib/{module.ts → core/module.ts} +10 -10
- package/src/lib/{queue.ts → core/queue.ts} +13 -5
- package/src/lib/{storage.ts → core/storage.ts} +33 -24
- package/src/lib/deploymentChecks.ts +2 -2
- package/src/lib/errors.ts +3 -8
- package/src/lib/filesystemService.ts +1 -1
- package/src/lib/filter/adjudicators/adjudicators.ts +40 -9
- package/src/lib/filter/filter.ts +204 -111
- package/src/lib/finalizer.ts +2 -2
- package/src/lib/helpers.ts +20 -133
- package/src/lib/included-files.ts +1 -1
- package/src/lib/mutate-request.ts +11 -11
- package/src/lib/processors/mutate-processor.ts +225 -0
- package/src/lib/processors/validate-processor.ts +93 -0
- package/src/lib/{watch-processor.ts → processors/watch-processor.ts} +19 -15
- package/src/lib/telemetry/logger.ts +3 -1
- package/src/lib/tls.ts +5 -1
- package/src/lib/utils.ts +5 -5
- package/src/lib/validate-request.ts +4 -4
- package/src/lib.ts +2 -2
- package/src/runtime/controller.ts +2 -2
- package/src/sdk/cosign.ts +4 -4
- package/src/sdk/heredoc.ts +1 -1
- package/dist/lib/capability.d.ts.map +0 -1
- package/dist/lib/module.d.ts.map +0 -1
- package/dist/lib/mutate-processor.d.ts +0 -6
- package/dist/lib/mutate-processor.d.ts.map +0 -1
- package/dist/lib/queue.d.ts.map +0 -1
- package/dist/lib/schedule.d.ts.map +0 -1
- package/dist/lib/storage.d.ts.map +0 -1
- package/dist/lib/validate-processor.d.ts +0 -6
- package/dist/lib/validate-processor.d.ts.map +0 -1
- package/dist/lib/watch-processor.d.ts.map +0 -1
- package/src/lib/mutate-processor.ts +0 -165
- package/src/lib/validate-processor.ts +0 -85
- /package/dist/lib/{queue.d.ts → core/queue.d.ts} +0 -0
- /package/src/lib/{schedule.ts → core/schedule.ts} +0 -0
package/src/cli/root.ts
CHANGED
package/src/cli/update.ts
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
import { write } from "./init/utils";
|
|
18
18
|
import { RootCmd } from "./root";
|
|
19
19
|
|
|
20
|
-
export default function (program: RootCmd) {
|
|
20
|
+
export default function (program: RootCmd): void {
|
|
21
21
|
program
|
|
22
22
|
.command("update")
|
|
23
23
|
.description("Update this Pepr module. Not recommended for prod as it may change files.")
|
package/src/cli/uuid.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { KubernetesListObject } from "@kubernetes/client-node";
|
|
|
5
5
|
import { K8s, kind } from "kubernetes-fluent-client";
|
|
6
6
|
import { RootCmd } from "./root";
|
|
7
7
|
|
|
8
|
-
export default function (program: RootCmd) {
|
|
8
|
+
export default function (program: RootCmd): void {
|
|
9
9
|
program
|
|
10
10
|
.command("uuid [uuid]")
|
|
11
11
|
.description("Module UUID(s) currently deployed in the cluster")
|
package/src/fixtures/loader.ts
CHANGED
|
@@ -14,11 +14,11 @@ export function AdmissionRequestCreatePod() {
|
|
|
14
14
|
return cloneObject<kind.Pod>(admissionRequestCreatePod);
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export function AdmissionRequestDeletePod() {
|
|
17
|
+
export function AdmissionRequestDeletePod(): AdmissionRequest<kind.Pod> {
|
|
18
18
|
return cloneObject<kind.Pod>(admissionRequestDeletePod);
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
export function AdmissionRequestCreateClusterRole() {
|
|
21
|
+
export function AdmissionRequestCreateClusterRole(): AdmissionRequest<kind.ClusterRole> {
|
|
22
22
|
return cloneObject<kind.ClusterRole>(admissionRequestCreateClusterRole);
|
|
23
23
|
}
|
|
24
24
|
|
package/src/lib/assets/deploy.ts
CHANGED
|
@@ -9,17 +9,17 @@ import { V1PolicyRule as PolicyRule } from "@kubernetes/client-node";
|
|
|
9
9
|
import { Assets } from ".";
|
|
10
10
|
import Log from "../telemetry/logger";
|
|
11
11
|
import { apiTokenSecret, service, tlsSecret, watcherService } from "./networking";
|
|
12
|
-
import {
|
|
12
|
+
import { getDeployment, getModuleSecret, getNamespace, getWatcher } from "./pods";
|
|
13
13
|
import { clusterRole, clusterRoleBinding, serviceAccount, storeRole, storeRoleBinding } from "./rbac";
|
|
14
14
|
import { peprStoreCRD } from "./store";
|
|
15
15
|
import { webhookConfig } from "./webhooks";
|
|
16
16
|
import { CapabilityExport, ImagePullSecret } from "../types";
|
|
17
17
|
|
|
18
|
-
export async function deployImagePullSecret(imagePullSecret: ImagePullSecret, name: string) {
|
|
18
|
+
export async function deployImagePullSecret(imagePullSecret: ImagePullSecret, name: string): Promise<void> {
|
|
19
19
|
try {
|
|
20
20
|
await K8s(kind.Namespace).Get("pepr-system");
|
|
21
21
|
} catch {
|
|
22
|
-
await K8s(kind.Namespace).Apply(
|
|
22
|
+
await K8s(kind.Namespace).Apply(getNamespace());
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
try {
|
|
@@ -42,13 +42,13 @@ export async function deployImagePullSecret(imagePullSecret: ImagePullSecret, na
|
|
|
42
42
|
Log.error(e);
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
-
export async function deploy(assets: Assets, force: boolean, webhookTimeout?: number) {
|
|
45
|
+
export async function deploy(assets: Assets, force: boolean, webhookTimeout?: number): Promise<void> {
|
|
46
46
|
Log.info("Establishing connection to Kubernetes");
|
|
47
47
|
|
|
48
48
|
const { name, host, path } = assets;
|
|
49
49
|
|
|
50
50
|
Log.info("Applying pepr-system namespace");
|
|
51
|
-
await K8s(kind.Namespace).Apply(
|
|
51
|
+
await K8s(kind.Namespace).Apply(getNamespace(assets.config.customLabels?.namespace));
|
|
52
52
|
|
|
53
53
|
// Create the mutating webhook configuration if it is needed
|
|
54
54
|
const mutateWebhook = await webhookConfig(assets, "mutate", webhookTimeout);
|
|
@@ -95,7 +95,7 @@ async function setupRBAC(
|
|
|
95
95
|
capabilities: CapabilityExport[],
|
|
96
96
|
force: boolean,
|
|
97
97
|
config: { rbacMode?: string; rbac?: PolicyRule[] },
|
|
98
|
-
) {
|
|
98
|
+
): Promise<void> {
|
|
99
99
|
const { rbacMode, rbac } = config;
|
|
100
100
|
|
|
101
101
|
Log.info("Applying cluster role binding");
|
|
@@ -119,11 +119,11 @@ async function setupRBAC(
|
|
|
119
119
|
await K8s(kind.RoleBinding).Apply(roleBinding, { force });
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
async function setupController(assets: Assets, code: Buffer, hash: string, force: boolean) {
|
|
122
|
+
async function setupController(assets: Assets, code: Buffer, hash: string, force: boolean): Promise<void> {
|
|
123
123
|
const { name } = assets;
|
|
124
124
|
|
|
125
125
|
Log.info("Applying module secret");
|
|
126
|
-
const mod =
|
|
126
|
+
const mod = getModuleSecret(name, code, hash);
|
|
127
127
|
await K8s(kind.Secret).Apply(mod, { force });
|
|
128
128
|
|
|
129
129
|
Log.info("Applying controller service");
|
|
@@ -139,14 +139,14 @@ async function setupController(assets: Assets, code: Buffer, hash: string, force
|
|
|
139
139
|
await K8s(kind.Secret).Apply(apiToken, { force });
|
|
140
140
|
|
|
141
141
|
Log.info("Applying deployment");
|
|
142
|
-
const dep =
|
|
142
|
+
const dep = getDeployment(assets, hash, assets.buildTimestamp);
|
|
143
143
|
await K8s(kind.Deployment).Apply(dep, { force });
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
// Setup the watcher deployment and service
|
|
147
|
-
async function setupWatcher(assets: Assets, hash: string, force: boolean) {
|
|
147
|
+
async function setupWatcher(assets: Assets, hash: string, force: boolean): Promise<void> {
|
|
148
148
|
// If the module has a watcher, deploy it
|
|
149
|
-
const watchDeployment =
|
|
149
|
+
const watchDeployment = getWatcher(assets, hash, assets.buildTimestamp);
|
|
150
150
|
if (watchDeployment) {
|
|
151
151
|
Log.info("Applying watcher deployment");
|
|
152
152
|
await K8s(kind.Deployment).Apply(watchDeployment, { force });
|
|
@@ -6,7 +6,7 @@ import { K8s, kind } from "kubernetes-fluent-client";
|
|
|
6
6
|
import Log from "../telemetry/logger";
|
|
7
7
|
import { peprStoreCRD } from "./store";
|
|
8
8
|
|
|
9
|
-
export async function destroyModule(name: string) {
|
|
9
|
+
export async function destroyModule(name: string): Promise<void> {
|
|
10
10
|
const namespace = "pepr-system";
|
|
11
11
|
|
|
12
12
|
Log.info("Destroying Pepr module");
|
package/src/lib/assets/helm.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
3
|
|
|
4
|
-
export function clusterRoleTemplate() {
|
|
4
|
+
export function clusterRoleTemplate(): string {
|
|
5
5
|
return `
|
|
6
6
|
apiVersion: rbac.authorization.k8s.io/v1
|
|
7
7
|
kind: ClusterRole
|
|
@@ -15,7 +15,7 @@ export function clusterRoleTemplate() {
|
|
|
15
15
|
`;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
export function
|
|
18
|
+
export function namespaceTemplate(): string {
|
|
19
19
|
return `
|
|
20
20
|
apiVersion: v1
|
|
21
21
|
kind: Namespace
|
|
@@ -32,7 +32,7 @@ export function nsTemplate() {
|
|
|
32
32
|
`;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
export function chartYaml(name: string, description?: string) {
|
|
35
|
+
export function chartYaml(name: string, description?: string): string {
|
|
36
36
|
return `
|
|
37
37
|
apiVersion: v2
|
|
38
38
|
name: ${name}
|
|
@@ -61,7 +61,7 @@ export function chartYaml(name: string, description?: string) {
|
|
|
61
61
|
`;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
export function watcherDeployTemplate(buildTimestamp: string) {
|
|
64
|
+
export function watcherDeployTemplate(buildTimestamp: string): string {
|
|
65
65
|
return `
|
|
66
66
|
apiVersion: apps/v1
|
|
67
67
|
kind: Deployment
|
|
@@ -142,7 +142,7 @@ export function watcherDeployTemplate(buildTimestamp: string) {
|
|
|
142
142
|
`;
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
-
export function admissionDeployTemplate(buildTimestamp: string) {
|
|
145
|
+
export function admissionDeployTemplate(buildTimestamp: string): string {
|
|
146
146
|
return `
|
|
147
147
|
apiVersion: apps/v1
|
|
148
148
|
kind: Deployment
|
|
@@ -228,7 +228,7 @@ export function admissionDeployTemplate(buildTimestamp: string) {
|
|
|
228
228
|
`;
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
-
export function serviceMonitorTemplate(name: string) {
|
|
231
|
+
export function serviceMonitorTemplate(name: string): string {
|
|
232
232
|
return `
|
|
233
233
|
{{- if .Values.${name}.serviceMonitor.enabled }}
|
|
234
234
|
apiVersion: monitoring.coreos.com/v1
|
package/src/lib/assets/index.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import crypto from "crypto";
|
|
5
5
|
import { dumpYaml } from "@kubernetes/client-node";
|
|
6
6
|
import { kind } from "kubernetes-fluent-client";
|
|
7
|
-
import { ModuleConfig } from "../module";
|
|
7
|
+
import { ModuleConfig } from "../core/module";
|
|
8
8
|
import { TLSOut, genTLS } from "../tls";
|
|
9
9
|
import { CapabilityExport } from "../types";
|
|
10
10
|
import { WebhookIgnore } from "../k8s";
|
|
@@ -16,7 +16,7 @@ import { dedent } from "../helpers";
|
|
|
16
16
|
import { resolve } from "path";
|
|
17
17
|
import {
|
|
18
18
|
chartYaml,
|
|
19
|
-
|
|
19
|
+
namespaceTemplate,
|
|
20
20
|
admissionDeployTemplate,
|
|
21
21
|
watcherDeployTemplate,
|
|
22
22
|
clusterRoleTemplate,
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
import { promises as fs } from "fs";
|
|
26
26
|
import { webhookConfig } from "./webhooks";
|
|
27
27
|
import { apiTokenSecret, service, tlsSecret, watcherService } from "./networking";
|
|
28
|
-
import {
|
|
28
|
+
import { getWatcher, getModuleSecret } from "./pods";
|
|
29
29
|
|
|
30
30
|
import { clusterRoleBinding, serviceAccount, storeRole, storeRoleBinding } from "./rbac";
|
|
31
31
|
import { createDirectoryIfNotExists } from "../filesystemService";
|
|
@@ -51,7 +51,7 @@ function createWebhookYaml(
|
|
|
51
51
|
);
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
function helmLayout(basePath: string, unique: string) {
|
|
54
|
+
function helmLayout(basePath: string, unique: string): Record<string, Record<string, string>> {
|
|
55
55
|
const helm: Record<string, Record<string, string>> = {
|
|
56
56
|
dirs: {
|
|
57
57
|
chart: resolve(`${basePath}/${unique}-chart`),
|
|
@@ -119,20 +119,20 @@ export class Assets {
|
|
|
119
119
|
this.apiToken = crypto.randomBytes(32).toString("hex");
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
setHash = (hash: string) => {
|
|
122
|
+
setHash = (hash: string): void => {
|
|
123
123
|
this.hash = hash;
|
|
124
124
|
};
|
|
125
125
|
|
|
126
|
-
deploy = async (force: boolean, webhookTimeout?: number) => {
|
|
126
|
+
deploy = async (force: boolean, webhookTimeout?: number): Promise<void> => {
|
|
127
127
|
this.capabilities = await loadCapabilities(this.path);
|
|
128
128
|
await deploy(this, force, webhookTimeout);
|
|
129
129
|
};
|
|
130
130
|
|
|
131
|
-
zarfYaml = (path: string) => zarfYaml(this, path);
|
|
131
|
+
zarfYaml = (path: string): string => zarfYaml(this, path);
|
|
132
132
|
|
|
133
|
-
zarfYamlChart = (path: string) => zarfYamlChart(this, path);
|
|
133
|
+
zarfYamlChart = (path: string): string => zarfYamlChart(this, path);
|
|
134
134
|
|
|
135
|
-
allYaml = async (imagePullSecret?: string) => {
|
|
135
|
+
allYaml = async (imagePullSecret?: string): Promise<string> => {
|
|
136
136
|
this.capabilities = await loadCapabilities(this.path);
|
|
137
137
|
// give error if namespaces are not respected
|
|
138
138
|
for (const capability of this.capabilities) {
|
|
@@ -143,7 +143,7 @@ export class Assets {
|
|
|
143
143
|
};
|
|
144
144
|
|
|
145
145
|
/* eslint max-statements: ["warn", 21] */
|
|
146
|
-
generateHelmChart = async (basePath: string) => {
|
|
146
|
+
generateHelmChart = async (basePath: string): Promise<void> => {
|
|
147
147
|
const helm = helmLayout(basePath, this.config.uuid);
|
|
148
148
|
|
|
149
149
|
try {
|
|
@@ -156,18 +156,18 @@ export class Assets {
|
|
|
156
156
|
const code = await fs.readFile(this.path);
|
|
157
157
|
|
|
158
158
|
const pairs: [string, () => string][] = [
|
|
159
|
-
[helm.files.chartYaml, () => dedent(chartYaml(this.config.uuid, this.config.description || ""))],
|
|
160
|
-
[helm.files.namespaceYaml, () => dedent(
|
|
161
|
-
[helm.files.watcherServiceYaml, () => toYaml(watcherService(this.name))],
|
|
162
|
-
[helm.files.admissionServiceYaml, () => toYaml(service(this.name))],
|
|
163
|
-
[helm.files.tlsSecretYaml, () => toYaml(tlsSecret(this.name, this.tls))],
|
|
164
|
-
[helm.files.apiTokenSecretYaml, () => toYaml(apiTokenSecret(this.name, this.apiToken))],
|
|
165
|
-
[helm.files.storeRoleYaml, () => toYaml(storeRole(this.name))],
|
|
166
|
-
[helm.files.storeRoleBindingYaml, () => toYaml(storeRoleBinding(this.name))],
|
|
167
|
-
[helm.files.clusterRoleYaml, () => dedent(clusterRoleTemplate())],
|
|
168
|
-
[helm.files.clusterRoleBindingYaml, () => toYaml(clusterRoleBinding(this.name))],
|
|
169
|
-
[helm.files.serviceAccountYaml, () => toYaml(serviceAccount(this.name))],
|
|
170
|
-
[helm.files.moduleSecretYaml, () => toYaml(
|
|
159
|
+
[helm.files.chartYaml, (): string => dedent(chartYaml(this.config.uuid, this.config.description || ""))],
|
|
160
|
+
[helm.files.namespaceYaml, (): string => dedent(namespaceTemplate())],
|
|
161
|
+
[helm.files.watcherServiceYaml, (): string => toYaml(watcherService(this.name))],
|
|
162
|
+
[helm.files.admissionServiceYaml, (): string => toYaml(service(this.name))],
|
|
163
|
+
[helm.files.tlsSecretYaml, (): string => toYaml(tlsSecret(this.name, this.tls))],
|
|
164
|
+
[helm.files.apiTokenSecretYaml, (): string => toYaml(apiTokenSecret(this.name, this.apiToken))],
|
|
165
|
+
[helm.files.storeRoleYaml, (): string => toYaml(storeRole(this.name))],
|
|
166
|
+
[helm.files.storeRoleBindingYaml, (): string => toYaml(storeRoleBinding(this.name))],
|
|
167
|
+
[helm.files.clusterRoleYaml, (): string => dedent(clusterRoleTemplate())],
|
|
168
|
+
[helm.files.clusterRoleBindingYaml, (): string => toYaml(clusterRoleBinding(this.name))],
|
|
169
|
+
[helm.files.serviceAccountYaml, (): string => toYaml(serviceAccount(this.name))],
|
|
170
|
+
[helm.files.moduleSecretYaml, (): string => toYaml(getModuleSecret(this.name, code, this.hash))],
|
|
171
171
|
];
|
|
172
172
|
await Promise.all(pairs.map(async ([file, content]) => await fs.writeFile(file, content())));
|
|
173
173
|
|
|
@@ -191,7 +191,7 @@ export class Assets {
|
|
|
191
191
|
await fs.writeFile(helm.files.validationWebhookYaml, createWebhookYaml(this, validateWebhook));
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
-
const watchDeployment =
|
|
194
|
+
const watchDeployment = getWatcher(this, this.hash, this.buildTimestamp);
|
|
195
195
|
if (watchDeployment) {
|
|
196
196
|
await fs.writeFile(helm.files.watcherDeploymentYaml, dedent(watcherDeployTemplate(this.buildTimestamp)));
|
|
197
197
|
await fs.writeFile(helm.files.watcherServiceMonitorYaml, dedent(serviceMonitorTemplate("watcher")));
|
package/src/lib/assets/pods.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
3
|
|
|
4
|
-
import { V1EnvVar } from "@kubernetes/client-node";
|
|
4
|
+
import { KubernetesObject, V1EnvVar } from "@kubernetes/client-node";
|
|
5
5
|
import { kind } from "kubernetes-fluent-client";
|
|
6
6
|
import { gzipSync } from "zlib";
|
|
7
7
|
import { secretOverLimit } from "../helpers";
|
|
8
8
|
import { Assets } from ".";
|
|
9
|
-
import { ModuleConfig } from "../module";
|
|
9
|
+
import { ModuleConfig } from "../core/module";
|
|
10
10
|
import { Binding } from "../types";
|
|
11
11
|
|
|
12
12
|
/** Generate the pepr-system namespace */
|
|
13
|
-
export function
|
|
13
|
+
export function getNamespace(namespaceLabels?: Record<string, string>): KubernetesObject {
|
|
14
14
|
if (namespaceLabels) {
|
|
15
15
|
return {
|
|
16
16
|
apiVersion: "v1",
|
|
@@ -31,7 +31,12 @@ export function namespace(namespaceLabels?: Record<string, string>) {
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
export function
|
|
34
|
+
export function getWatcher(
|
|
35
|
+
assets: Assets,
|
|
36
|
+
hash: string,
|
|
37
|
+
buildTimestamp: string,
|
|
38
|
+
imagePullSecret?: string,
|
|
39
|
+
): kind.Deployment | null {
|
|
35
40
|
const { name, image, capabilities, config } = assets;
|
|
36
41
|
|
|
37
42
|
let hasSchedule = false;
|
|
@@ -186,7 +191,7 @@ export function watcher(assets: Assets, hash: string, buildTimestamp: string, im
|
|
|
186
191
|
return deploy;
|
|
187
192
|
}
|
|
188
193
|
|
|
189
|
-
export function
|
|
194
|
+
export function getDeployment(
|
|
190
195
|
assets: Assets,
|
|
191
196
|
hash: string,
|
|
192
197
|
buildTimestamp: string,
|
|
@@ -336,7 +341,7 @@ export function deployment(
|
|
|
336
341
|
return deploy;
|
|
337
342
|
}
|
|
338
343
|
|
|
339
|
-
export function
|
|
344
|
+
export function getModuleSecret(name: string, data: Buffer, hash: string): kind.Secret {
|
|
340
345
|
// Compress the data
|
|
341
346
|
const compressed = gzipSync(data);
|
|
342
347
|
const path = `module-${hash}.js.gz`;
|
|
@@ -11,6 +11,7 @@ import { concat, equals, uniqWith } from "ramda";
|
|
|
11
11
|
|
|
12
12
|
import { Assets } from ".";
|
|
13
13
|
import { Event } from "../enums";
|
|
14
|
+
import { Binding } from "../types";
|
|
14
15
|
|
|
15
16
|
const peprIgnoreLabel: V1LabelSelectorRequirement = {
|
|
16
17
|
key: "pepr.dev",
|
|
@@ -20,57 +21,41 @@ const peprIgnoreLabel: V1LabelSelectorRequirement = {
|
|
|
20
21
|
|
|
21
22
|
const peprIgnoreNamespaces: string[] = ["kube-system", "pepr-system"];
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
const validateRule = (binding: Binding, isMutateWebhook: boolean): V1RuleWithOperations | undefined => {
|
|
25
|
+
const { event, kind, isMutate, isValidate } = binding;
|
|
26
|
+
|
|
27
|
+
// Skip invalid bindings based on webhook type
|
|
28
|
+
if ((isMutateWebhook && !isMutate) || (!isMutateWebhook && !isValidate)) {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Translate event to operations
|
|
33
|
+
const operations = event === Event.CREATE_OR_UPDATE ? [Event.CREATE, Event.UPDATE] : [event];
|
|
34
|
+
|
|
35
|
+
// Use the plural property if it exists, otherwise use lowercase kind + s
|
|
36
|
+
const resource = kind.plural || `${kind.kind.toLowerCase()}s`;
|
|
37
|
+
|
|
38
|
+
const ruleObject: V1RuleWithOperations = {
|
|
39
|
+
apiGroups: [kind.group],
|
|
40
|
+
apiVersions: [kind.version || "*"],
|
|
41
|
+
operations,
|
|
42
|
+
resources: [resource, ...(resource === "pods" ? ["pods/ephemeralcontainers"] : [])],
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
return ruleObject;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export async function generateWebhookRules(assets: Assets, isMutateWebhook: boolean): Promise<V1RuleWithOperations[]> {
|
|
24
49
|
const { config, capabilities } = assets;
|
|
25
|
-
const rules: V1RuleWithOperations[] = [];
|
|
26
50
|
|
|
27
|
-
|
|
28
|
-
for (const capability of capabilities) {
|
|
51
|
+
const rules = capabilities.flatMap(capability => {
|
|
29
52
|
console.info(`Module ${config.uuid} has capability: ${capability.name}`);
|
|
30
53
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
// If the module doesn't have a callback for the event, skip it
|
|
36
|
-
if (isMutateWebhook && !isMutate) {
|
|
37
|
-
continue;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (!isMutateWebhook && !isValidate) {
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const operations: string[] = [];
|
|
45
|
-
|
|
46
|
-
// CreateOrUpdate is a Pepr-specific event that is translated to Create and Update
|
|
47
|
-
if (event === Event.CREATE_OR_UPDATE) {
|
|
48
|
-
operations.push(Event.CREATE, Event.UPDATE);
|
|
49
|
-
} else {
|
|
50
|
-
operations.push(event);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Use the plural property if it exists, otherwise use lowercase kind + s
|
|
54
|
-
const resource = kind.plural || `${kind.kind.toLowerCase()}s`;
|
|
55
|
-
|
|
56
|
-
const ruleObject = {
|
|
57
|
-
apiGroups: [kind.group],
|
|
58
|
-
apiVersions: [kind.version || "*"],
|
|
59
|
-
operations,
|
|
60
|
-
resources: [resource],
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
// If the resource is pods, add ephemeralcontainers as well
|
|
64
|
-
if (resource === "pods") {
|
|
65
|
-
ruleObject.resources.push("pods/ephemeralcontainers");
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Add the rule to the rules array
|
|
69
|
-
rules.push(ruleObject);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
54
|
+
return capability.bindings
|
|
55
|
+
.map(binding => validateRule(binding, isMutateWebhook))
|
|
56
|
+
.filter((rule): rule is V1RuleWithOperations => !!rule);
|
|
57
|
+
});
|
|
72
58
|
|
|
73
|
-
// Return the rules with duplicates removed
|
|
74
59
|
return uniqWith(equals, rules);
|
|
75
60
|
}
|
|
76
61
|
|
package/src/lib/assets/yaml.ts
CHANGED
|
@@ -6,13 +6,16 @@ import crypto from "crypto";
|
|
|
6
6
|
import { promises as fs } from "fs";
|
|
7
7
|
import { Assets } from ".";
|
|
8
8
|
import { apiTokenSecret, service, tlsSecret, watcherService } from "./networking";
|
|
9
|
-
import {
|
|
9
|
+
import { getDeployment, getModuleSecret, getNamespace, getWatcher } 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
14
|
// Helm Chart overrides file (values.yaml) generated from assets
|
|
15
|
-
export async function overridesFile(
|
|
15
|
+
export async function overridesFile(
|
|
16
|
+
{ hash, name, image, config, apiToken, capabilities }: Assets,
|
|
17
|
+
path: string,
|
|
18
|
+
): Promise<void> {
|
|
16
19
|
const rbacOverrides = clusterRole(name, capabilities, config.rbacMode, config.rbac).rules;
|
|
17
20
|
|
|
18
21
|
const overrides = {
|
|
@@ -166,7 +169,7 @@ export async function overridesFile({ hash, name, image, config, apiToken, capab
|
|
|
166
169
|
|
|
167
170
|
await fs.writeFile(path, dumpYaml(overrides, { noRefs: true, forceQuotes: true }));
|
|
168
171
|
}
|
|
169
|
-
export function zarfYaml({ name, image, config }: Assets, path: string) {
|
|
172
|
+
export function zarfYaml({ name, image, config }: Assets, path: string): string {
|
|
170
173
|
const zarfCfg = {
|
|
171
174
|
kind: "ZarfPackageConfig",
|
|
172
175
|
metadata: {
|
|
@@ -194,7 +197,7 @@ export function zarfYaml({ name, image, config }: Assets, path: string) {
|
|
|
194
197
|
return dumpYaml(zarfCfg, { noRefs: true });
|
|
195
198
|
}
|
|
196
199
|
|
|
197
|
-
export function zarfYamlChart({ name, image, config }: Assets, path: string) {
|
|
200
|
+
export function zarfYamlChart({ name, image, config }: Assets, path: string): string {
|
|
198
201
|
const zarfCfg = {
|
|
199
202
|
kind: "ZarfPackageConfig",
|
|
200
203
|
metadata: {
|
|
@@ -223,7 +226,7 @@ export function zarfYamlChart({ name, image, config }: Assets, path: string) {
|
|
|
223
226
|
return dumpYaml(zarfCfg, { noRefs: true });
|
|
224
227
|
}
|
|
225
228
|
|
|
226
|
-
export async function allYaml(assets: Assets, imagePullSecret?: string) {
|
|
229
|
+
export async function allYaml(assets: Assets, imagePullSecret?: string): Promise<string> {
|
|
227
230
|
const { name, tls, apiToken, path, config } = assets;
|
|
228
231
|
const code = await fs.readFile(path);
|
|
229
232
|
|
|
@@ -232,19 +235,19 @@ export async function allYaml(assets: Assets, imagePullSecret?: string) {
|
|
|
232
235
|
|
|
233
236
|
const mutateWebhook = await webhookConfig(assets, "mutate", assets.config.webhookTimeout);
|
|
234
237
|
const validateWebhook = await webhookConfig(assets, "validate", assets.config.webhookTimeout);
|
|
235
|
-
const watchDeployment =
|
|
238
|
+
const watchDeployment = getWatcher(assets, assets.hash, assets.buildTimestamp, imagePullSecret);
|
|
236
239
|
|
|
237
240
|
const resources = [
|
|
238
|
-
|
|
241
|
+
getNamespace(assets.config.customLabels?.namespace),
|
|
239
242
|
clusterRole(name, assets.capabilities, config.rbacMode, config.rbac),
|
|
240
243
|
clusterRoleBinding(name),
|
|
241
244
|
serviceAccount(name),
|
|
242
245
|
apiTokenSecret(name, apiToken),
|
|
243
246
|
tlsSecret(name, tls),
|
|
244
|
-
|
|
247
|
+
getDeployment(assets, assets.hash, assets.buildTimestamp, imagePullSecret),
|
|
245
248
|
service(name),
|
|
246
249
|
watcherService(name),
|
|
247
|
-
|
|
250
|
+
getModuleSecret(name, code, assets.hash),
|
|
248
251
|
storeRole(name),
|
|
249
252
|
storeRoleBinding(name),
|
|
250
253
|
];
|
|
@@ -5,13 +5,13 @@ import express, { NextFunction } from "express";
|
|
|
5
5
|
import fs from "fs";
|
|
6
6
|
import https from "https";
|
|
7
7
|
|
|
8
|
-
import { Capability } from "../capability";
|
|
8
|
+
import { Capability } from "../core/capability";
|
|
9
9
|
import { MutateResponse, ValidateResponse } from "../k8s";
|
|
10
10
|
import Log from "../telemetry/logger";
|
|
11
11
|
import { metricsCollector, MetricsCollector } from "../telemetry/metrics";
|
|
12
|
-
import { ModuleConfig, isWatchMode } from "../module";
|
|
13
|
-
import { mutateProcessor } from "../mutate-processor";
|
|
14
|
-
import { validateProcessor } from "../validate-processor";
|
|
12
|
+
import { ModuleConfig, isWatchMode } from "../core/module";
|
|
13
|
+
import { mutateProcessor } from "../processors/mutate-processor";
|
|
14
|
+
import { validateProcessor } from "../processors/validate-processor";
|
|
15
15
|
import { StoreController } from "./store";
|
|
16
16
|
import { AdmissionRequest } from "../types";
|
|
17
17
|
import { karForMutate, karForValidate, KubeAdmissionReview } from "./index.util";
|
|
@@ -78,7 +78,7 @@ export class Controller {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
/** Start the webhook server */
|
|
81
|
-
startServer = (port: number) => {
|
|
81
|
+
startServer = (port: number): void => {
|
|
82
82
|
if (this.#running) {
|
|
83
83
|
throw new Error("Cannot start Pepr module: Pepr module was not instantiated with deferStart=true");
|
|
84
84
|
}
|
|
@@ -133,7 +133,7 @@ export class Controller {
|
|
|
133
133
|
});
|
|
134
134
|
};
|
|
135
135
|
|
|
136
|
-
#bindEndpoints = () => {
|
|
136
|
+
#bindEndpoints = (): void => {
|
|
137
137
|
// Health check endpoint
|
|
138
138
|
this.#app.get("/healthz", Controller.#healthz);
|
|
139
139
|
|
|
@@ -162,7 +162,7 @@ export class Controller {
|
|
|
162
162
|
* @param next The next middleware function
|
|
163
163
|
* @returns
|
|
164
164
|
*/
|
|
165
|
-
#validateToken = (req: express.Request, res: express.Response, next: NextFunction) => {
|
|
165
|
+
#validateToken = (req: express.Request, res: express.Response, next: NextFunction): void => {
|
|
166
166
|
// Validate the token
|
|
167
167
|
const { token } = req.params;
|
|
168
168
|
if (token !== this.#token) {
|
|
@@ -183,7 +183,7 @@ export class Controller {
|
|
|
183
183
|
* @param req the incoming request
|
|
184
184
|
* @param res the outgoing response
|
|
185
185
|
*/
|
|
186
|
-
#metrics = async (req: express.Request, res: express.Response) => {
|
|
186
|
+
#metrics = async (req: express.Request, res: express.Response): Promise<void> => {
|
|
187
187
|
try {
|
|
188
188
|
// https://github.com/prometheus/docs/blob/main/content/docs/instrumenting/exposition_formats.md#basic-info
|
|
189
189
|
res.set("Content-Type", "text/plain; version=0.0.4");
|
|
@@ -200,7 +200,9 @@ export class Controller {
|
|
|
200
200
|
* @param admissionKind the type of admission request
|
|
201
201
|
* @returns the request handler
|
|
202
202
|
*/
|
|
203
|
-
#admissionReq = (
|
|
203
|
+
#admissionReq = (
|
|
204
|
+
admissionKind: "Mutate" | "Validate",
|
|
205
|
+
): ((req: express.Request, res: express.Response) => Promise<void>) => {
|
|
204
206
|
// Create the admission request handler
|
|
205
207
|
return async (req: express.Request, res: express.Response) => {
|
|
206
208
|
// Start the metrics timer
|
|
@@ -259,7 +261,7 @@ export class Controller {
|
|
|
259
261
|
* @param res the outgoing response
|
|
260
262
|
* @param next the next middleware function
|
|
261
263
|
*/
|
|
262
|
-
static #logger(req: express.Request, res: express.Response, next: express.NextFunction) {
|
|
264
|
+
static #logger(req: express.Request, res: express.Response, next: express.NextFunction): void {
|
|
263
265
|
const startTime = Date.now();
|
|
264
266
|
|
|
265
267
|
res.on("finish", () => {
|
|
@@ -288,7 +290,7 @@ export class Controller {
|
|
|
288
290
|
* @param req the incoming request
|
|
289
291
|
* @param res the outgoing response
|
|
290
292
|
*/
|
|
291
|
-
static #healthz(req: express.Request, res: express.Response) {
|
|
293
|
+
static #healthz(req: express.Request, res: express.Response): void {
|
|
292
294
|
try {
|
|
293
295
|
res.send("OK");
|
|
294
296
|
} catch (err) {
|