pepr 0.45.0 → 0.45.1-nightly.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/README.md +15 -7
- package/dist/cli/build.d.ts +1 -1
- package/dist/cli/build.d.ts.map +1 -1
- package/dist/cli/build.helpers.d.ts +1 -1
- package/dist/cli/init/templates.d.ts +5 -2
- package/dist/cli/init/templates.d.ts.map +1 -1
- package/dist/cli.js +31 -37
- package/dist/controller.js +1 -1
- package/dist/lib/assets/assets.d.ts +3 -3
- package/dist/lib/assets/assets.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/networking.d.ts +1 -1
- package/dist/lib/assets/networking.d.ts.map +1 -1
- package/dist/lib/assets/pods.d.ts +1 -1
- package/dist/lib/assets/pods.d.ts.map +1 -1
- package/dist/lib/assets/yaml/overridesFile.d.ts +3 -3
- package/dist/lib/assets/yaml/overridesFile.d.ts.map +1 -1
- package/dist/lib/controller/index.d.ts +1 -1
- package/dist/lib/controller/index.d.ts.map +1 -1
- package/dist/lib/core/envChecks.d.ts +4 -0
- package/dist/lib/core/envChecks.d.ts.map +1 -0
- package/dist/lib/core/module.d.ts +1 -51
- package/dist/lib/core/module.d.ts.map +1 -1
- package/dist/lib/processors/mutate-processor.d.ts +1 -1
- package/dist/lib/processors/mutate-processor.d.ts.map +1 -1
- package/dist/lib/processors/validate-processor.d.ts +1 -1
- package/dist/lib/processors/validate-processor.d.ts.map +1 -1
- package/dist/lib/processors/watch-processor.d.ts +22 -1
- package/dist/lib/processors/watch-processor.d.ts.map +1 -1
- package/dist/lib/telemetry/metrics.d.ts +2 -3
- package/dist/lib/telemetry/metrics.d.ts.map +1 -1
- package/dist/lib/types.d.ts +45 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib.js +2019 -2019
- package/dist/lib.js.map +4 -4
- package/dist/sdk/sdk.d.ts +6 -1
- package/dist/sdk/sdk.d.ts.map +1 -1
- package/package.json +11 -8
- package/src/cli/build.helpers.ts +1 -1
- package/src/cli/build.ts +3 -11
- package/src/cli/dev.ts +1 -1
- package/src/cli/init/templates.ts +1 -1
- package/src/lib/assets/assets.ts +8 -8
- package/src/lib/assets/deploy.ts +4 -4
- package/src/lib/assets/destroy.ts +1 -1
- package/src/lib/assets/helm.ts +4 -4
- package/src/lib/assets/index.ts +2 -3
- package/src/lib/assets/networking.ts +3 -3
- package/src/lib/assets/pods.ts +5 -5
- package/src/lib/assets/webhooks.ts +5 -5
- package/src/lib/assets/yaml/generateAllYaml.ts +3 -3
- package/src/lib/assets/yaml/overridesFile.ts +4 -4
- package/src/lib/controller/index.ts +20 -19
- package/src/lib/core/capability.ts +1 -1
- package/src/lib/core/envChecks.ts +6 -0
- package/src/lib/core/module.ts +3 -62
- package/src/lib/processors/mutate-processor.ts +1 -1
- package/src/lib/processors/validate-processor.ts +1 -1
- package/src/lib/processors/watch-processor.ts +58 -33
- package/src/lib/telemetry/metrics.ts +4 -4
- package/src/lib/types.ts +48 -0
- package/src/sdk/sdk.ts +8 -4
package/dist/sdk/sdk.d.ts
CHANGED
|
@@ -19,7 +19,12 @@ export declare function containers(request: PeprValidateRequest<kind.Pod> | Pepr
|
|
|
19
19
|
* @param reportingComponent The component that is reporting the event, for example "uds.dev/operator"
|
|
20
20
|
* @param reportingInstance The instance of the component that is reporting the event, for example process.env.HOSTNAME
|
|
21
21
|
*/
|
|
22
|
-
export declare function writeEvent(cr: GenericKind, event: Partial<kind.CoreEvent>,
|
|
22
|
+
export declare function writeEvent(cr: GenericKind, event: Partial<kind.CoreEvent>, options: {
|
|
23
|
+
eventType: string;
|
|
24
|
+
eventReason: string;
|
|
25
|
+
reportingComponent: string;
|
|
26
|
+
reportingInstance: string;
|
|
27
|
+
}): Promise<void>;
|
|
23
28
|
/**
|
|
24
29
|
* Get the owner reference for a custom resource
|
|
25
30
|
* @param customResource the custom resource to get the owner reference for
|
package/dist/sdk/sdk.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/sdk/sdk.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,WAAW,EAAO,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAElE;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,OAAO,EAAE,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,EACpE,aAAa,CAAC,EAAE,YAAY,GAAG,gBAAgB,GAAG,qBAAqB,GACtE,WAAW,EAAE,CAef;AAED;;;;;;;;;GASG;AAEH,wBAAsB,UAAU,CAC9B,EAAE,EAAE,WAAW,EACf,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAC9B,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/sdk/sdk.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,WAAW,EAAO,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAElE;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,OAAO,EAAE,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,EACpE,aAAa,CAAC,EAAE,YAAY,GAAG,gBAAgB,GAAG,qBAAqB,GACtE,WAAW,EAAE,CAef;AAED;;;;;;;;;GASG;AAEH,wBAAsB,UAAU,CAC9B,EAAE,EAAE,WAAW,EACf,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAC9B,OAAO,EAAE;IACP,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;CAC3B,GACA,OAAO,CAAC,IAAI,CAAC,CAuBf;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,cAAc,EAAE,WAAW,EAC3B,kBAAkB,CAAC,EAAE,OAAO,EAC5B,UAAU,CAAC,EAAE,OAAO,GACnB,gBAAgB,EAAE,CAcpB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAYzD"}
|
package/package.json
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"!src/**/*.test.ts",
|
|
16
16
|
"!dist/**/*.test.d.ts*"
|
|
17
17
|
],
|
|
18
|
-
"version": "0.45.0",
|
|
18
|
+
"version": "0.45.1-nightly.0",
|
|
19
19
|
"main": "dist/lib.js",
|
|
20
20
|
"types": "dist/lib.d.ts",
|
|
21
21
|
"scripts": {
|
|
@@ -24,18 +24,21 @@
|
|
|
24
24
|
"prebuild": "rm -fr dist/* && npm run gen-data-json",
|
|
25
25
|
"build": "tsc && node build.mjs && npm pack",
|
|
26
26
|
"build:image": "npm run build && docker buildx build --output type=docker --tag pepr:dev .",
|
|
27
|
+
"build:image:unicorn": "npm run build && docker buildx build -f Dockerfile.unicorn --output type=docker --tag pepr:dev .",
|
|
27
28
|
"set:version": "node scripts/set-version.js",
|
|
28
|
-
"test": "npm run test:unit && npm run test:journey",
|
|
29
|
+
"test": "npm run test:unit && npm run test:journey && npm run test:journey-wasm",
|
|
29
30
|
"test:unit": "npm run gen-data-json && jest src --coverage --detectOpenHandles --coverageDirectory=./coverage --testPathIgnorePatterns='cosign.e2e.test.ts'",
|
|
30
31
|
"test:integration": "npm run test:integration:prep && npm run test:integration:run",
|
|
31
32
|
"test:integration:prep": "./integration/prep.sh",
|
|
32
33
|
"test:integration:run": "jest --maxWorkers=4 integration",
|
|
33
34
|
"test:journey": "npm run test:journey:k3d && npm run build && npm run test:journey:image && npm run test:journey:run",
|
|
34
|
-
"test:journey:
|
|
35
|
+
"test:journey:unicorn": "npm run test:journey:k3d && npm run build && npm run test:journey:image:unicorn && npm run test:journey:run",
|
|
35
36
|
"test:journey-wasm": "npm run test:journey:k3d && npm run build && npm run test:journey:image && npm run test:journey:run-wasm",
|
|
37
|
+
"test:journey-wasm:unicorn": "npm run test:journey:k3d && npm run build && npm run test:journey:image:unicorn && npm run test:journey:run-wasm",
|
|
36
38
|
"test:journey:k3d": "k3d cluster delete pepr-dev && k3d cluster create pepr-dev --k3s-arg '--debug@server:0' --wait && kubectl rollout status deployment -n kube-system",
|
|
37
39
|
"test:journey:image": "docker buildx build --output type=docker --tag pepr:dev . && k3d image import pepr:dev -c pepr-dev",
|
|
38
|
-
"test:journey:
|
|
40
|
+
"test:journey:image:unicorn": "docker buildx build -f Dockerfile.unicorn --output type=docker --tag pepr:dev . && k3d image import pepr:dev -c pepr-dev",
|
|
41
|
+
"test:journey:run": "jest --detectOpenHandles journey/entrypoint.test.ts && npm run test:journey:upgrade",
|
|
39
42
|
"test:journey:run-wasm": "jest --detectOpenHandles journey/entrypoint-wasm.test.ts",
|
|
40
43
|
"test:journey:upgrade": "npm run test:journey:k3d && npm run test:journey:image && jest --detectOpenHandles journey/pepr-upgrade.test.ts",
|
|
41
44
|
"format:check": "eslint src && prettier src --check",
|
|
@@ -49,12 +52,12 @@
|
|
|
49
52
|
"follow-redirects": "1.15.9",
|
|
50
53
|
"http-status-codes": "^2.3.0",
|
|
51
54
|
"json-pointer": "^0.6.2",
|
|
52
|
-
"kubernetes-fluent-client": "3.
|
|
55
|
+
"kubernetes-fluent-client": "3.4.0",
|
|
53
56
|
"pino": "9.6.0",
|
|
54
57
|
"pino-pretty": "13.0.0",
|
|
55
58
|
"prom-client": "15.1.3",
|
|
56
59
|
"ramda": "0.30.1",
|
|
57
|
-
"sigstore": "3.
|
|
60
|
+
"sigstore": "3.1.0"
|
|
58
61
|
},
|
|
59
62
|
"devDependencies": {
|
|
60
63
|
"@commitlint/cli": "19.7.1",
|
|
@@ -84,7 +87,7 @@
|
|
|
84
87
|
"@typescript-eslint/eslint-plugin": "8.23.0",
|
|
85
88
|
"@typescript-eslint/parser": "8.23.0",
|
|
86
89
|
"commander": "13.1.0",
|
|
87
|
-
"esbuild": "0.
|
|
90
|
+
"esbuild": "0.25.0",
|
|
88
91
|
"eslint": "8.57.0",
|
|
89
92
|
"node-forge": "1.3.1",
|
|
90
93
|
"prettier": "3.4.2",
|
|
@@ -92,4 +95,4 @@
|
|
|
92
95
|
"typescript": "5.7.3",
|
|
93
96
|
"uuid": "11.0.5"
|
|
94
97
|
}
|
|
95
|
-
}
|
|
98
|
+
}
|
package/src/cli/build.helpers.ts
CHANGED
|
@@ -94,7 +94,7 @@ export async function handleCustomOutputDir(outputDir: string): Promise<string>
|
|
|
94
94
|
* Check if the image is from Iron Bank and return the correct image
|
|
95
95
|
* @param registry The registry of the image
|
|
96
96
|
* @param image The image to check
|
|
97
|
-
* @param peprVersion The version of the
|
|
97
|
+
* @param peprVersion The version of the Pepr controller
|
|
98
98
|
* @returns The image string
|
|
99
99
|
* @example
|
|
100
100
|
*/
|
package/src/cli/build.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { RootCmd } from "./root";
|
|
|
11
11
|
import { Option } from "commander";
|
|
12
12
|
import { parseTimeout } from "../lib/helpers";
|
|
13
13
|
import { peprFormat } from "./format";
|
|
14
|
-
import { ModuleConfig } from "../lib/
|
|
14
|
+
import { ModuleConfig } from "../lib/types";
|
|
15
15
|
import {
|
|
16
16
|
watchForChanges,
|
|
17
17
|
determineRbacMode,
|
|
@@ -77,13 +77,13 @@ export default function (program: RootCmd): void {
|
|
|
77
77
|
new Option(
|
|
78
78
|
"-i, --custom-image <custom-image>",
|
|
79
79
|
"Specify a custom image (including version) for Admission and Watch Deployments. Example: 'docker.io/username/custom-pepr-controller:v1.0.0'",
|
|
80
|
-
).conflicts(["
|
|
80
|
+
).conflicts(["registryInfo", "registry"]),
|
|
81
81
|
)
|
|
82
82
|
.addOption(
|
|
83
83
|
new Option(
|
|
84
84
|
"-r, --registry-info [<registry>/<username>]",
|
|
85
85
|
"Provide the image registry and username for building and pushing a custom WASM container. Requires authentication. Builds and pushes 'registry/username/custom-pepr-controller:<current-version>'.",
|
|
86
|
-
).conflicts(["customImage", "
|
|
86
|
+
).conflicts(["customImage", "registry"]),
|
|
87
87
|
)
|
|
88
88
|
|
|
89
89
|
.option("-o, --output-dir <output directory>", "Define where to place build output")
|
|
@@ -92,12 +92,6 @@ export default function (program: RootCmd): void {
|
|
|
92
92
|
"How long the API server should wait for a webhook to respond before treating the call as a failure",
|
|
93
93
|
parseTimeout,
|
|
94
94
|
)
|
|
95
|
-
.addOption(
|
|
96
|
-
new Option(
|
|
97
|
-
"-v, --version <version>",
|
|
98
|
-
"The version of the Pepr image to use in the deployment manifests. Example: '0.27.3'.",
|
|
99
|
-
).conflicts(["customImage", "registryInfo"]),
|
|
100
|
-
)
|
|
101
95
|
.option(
|
|
102
96
|
"--withPullSecret <imagePullSecret>",
|
|
103
97
|
"Image Pull Secret: Use image pull secret for controller Deployment.",
|
|
@@ -164,8 +158,6 @@ export default function (program: RootCmd): void {
|
|
|
164
158
|
console.info(`✅ Module built successfully at ${path}`);
|
|
165
159
|
return;
|
|
166
160
|
}
|
|
167
|
-
// set the image version if provided
|
|
168
|
-
if (opts.version) cfg.pepr.peprVersion = opts.version;
|
|
169
161
|
|
|
170
162
|
// Generate a secret for the module
|
|
171
163
|
const assets = new Assets(
|
package/src/cli/dev.ts
CHANGED
|
@@ -77,7 +77,7 @@ export default function (program: RootCmd): void {
|
|
|
77
77
|
...process.env,
|
|
78
78
|
LOG_LEVEL: "debug",
|
|
79
79
|
PEPR_MODE: "dev",
|
|
80
|
-
|
|
80
|
+
PEPR_API_PATH: webhook.apiPath,
|
|
81
81
|
PEPR_PRETTY_LOGS: "true",
|
|
82
82
|
SSL_KEY_PATH: "insecure-tls.key",
|
|
83
83
|
SSL_CERT_PATH: "insecure-tls.crt",
|
|
@@ -11,7 +11,7 @@ import prettierJSON from "../../templates/.prettierrc.json";
|
|
|
11
11
|
import samplesJSON from "../../templates/capabilities/hello-pepr.samples.json";
|
|
12
12
|
import settingsJSON from "../../templates/settings.json";
|
|
13
13
|
import tsConfigJSON from "../../templates/tsconfig.module.json";
|
|
14
|
-
import { CustomLabels } from "../../lib/
|
|
14
|
+
import { CustomLabels } from "../../lib/types";
|
|
15
15
|
import { InitOptions } from "../types";
|
|
16
16
|
import { OnError, RbacMode } from "./enums";
|
|
17
17
|
import { V1PolicyRule as PolicyRule } from "@kubernetes/client-node";
|
package/src/lib/assets/assets.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import crypto from "crypto";
|
|
2
2
|
import { CapabilityExport } from "../types";
|
|
3
|
-
import { ModuleConfig } from "../
|
|
3
|
+
import { ModuleConfig } from "../types";
|
|
4
4
|
import { TLSOut, genTLS } from "../tls";
|
|
5
5
|
import { WebhookIgnore } from "../k8s";
|
|
6
6
|
import {
|
|
@@ -24,13 +24,13 @@ import { loadCapabilities } from "./loader";
|
|
|
24
24
|
import { namespaceComplianceValidator, dedent } from "../helpers";
|
|
25
25
|
import { promises as fs } from "fs";
|
|
26
26
|
import { storeRole, storeRoleBinding, clusterRoleBinding, serviceAccount } from "./rbac";
|
|
27
|
-
import { watcherService, service, tlsSecret,
|
|
27
|
+
import { watcherService, service, tlsSecret, apiPathSecret } from "./networking";
|
|
28
28
|
import { WebhookType } from "../enums";
|
|
29
29
|
|
|
30
30
|
export class Assets {
|
|
31
31
|
readonly name: string;
|
|
32
32
|
readonly tls: TLSOut;
|
|
33
|
-
readonly
|
|
33
|
+
readonly apiPath: string;
|
|
34
34
|
readonly config: ModuleConfig;
|
|
35
35
|
readonly path: string;
|
|
36
36
|
readonly alwaysIgnore!: WebhookIgnore;
|
|
@@ -53,8 +53,8 @@ export class Assets {
|
|
|
53
53
|
// Generate the ephemeral tls things
|
|
54
54
|
this.tls = genTLS(host || `${this.name}.pepr-system.svc`);
|
|
55
55
|
|
|
56
|
-
// Generate the api
|
|
57
|
-
this.
|
|
56
|
+
// Generate the api path for the controller / webhook
|
|
57
|
+
this.apiPath = crypto.randomBytes(32).toString("hex");
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
async deploy(
|
|
@@ -81,7 +81,7 @@ export class Assets {
|
|
|
81
81
|
|
|
82
82
|
allYaml = async (
|
|
83
83
|
yamlGenerationFunction: (
|
|
84
|
-
|
|
84
|
+
assets: Assets,
|
|
85
85
|
deployments: { default: V1Deployment; watch: V1Deployment | null },
|
|
86
86
|
) => Promise<string>,
|
|
87
87
|
imagePullSecret?: string,
|
|
@@ -149,7 +149,7 @@ export class Assets {
|
|
|
149
149
|
[helm.files.watcherServiceYaml, (): string => toYaml(watcherService(this.name))],
|
|
150
150
|
[helm.files.admissionServiceYaml, (): string => toYaml(service(this.name))],
|
|
151
151
|
[helm.files.tlsSecretYaml, (): string => toYaml(tlsSecret(this.name, this.tls))],
|
|
152
|
-
[helm.files.
|
|
152
|
+
[helm.files.apiPathSecretYaml, (): string => toYaml(apiPathSecret(this.name, this.apiPath))],
|
|
153
153
|
[helm.files.storeRoleYaml, (): string => toYaml(storeRole(this.name))],
|
|
154
154
|
[helm.files.storeRoleBindingYaml, (): string => toYaml(storeRoleBinding(this.name))],
|
|
155
155
|
[helm.files.clusterRoleYaml, (): string => dedent(clusterRoleTemplate())],
|
|
@@ -164,7 +164,7 @@ export class Assets {
|
|
|
164
164
|
name: this.name,
|
|
165
165
|
image: this.image,
|
|
166
166
|
config: this.config,
|
|
167
|
-
|
|
167
|
+
apiPath: this.apiPath,
|
|
168
168
|
capabilities: this.capabilities,
|
|
169
169
|
};
|
|
170
170
|
await overridesFile(overrideData, helm.files.valuesYaml, this.imagePullSecrets);
|
package/src/lib/assets/deploy.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { V1PolicyRule as PolicyRule } from "@kubernetes/client-node";
|
|
|
8
8
|
|
|
9
9
|
import { Assets } from "./assets";
|
|
10
10
|
import Log from "../telemetry/logger";
|
|
11
|
-
import {
|
|
11
|
+
import { apiPathSecret, service, tlsSecret, watcherService } from "./networking";
|
|
12
12
|
import { getDeployment, getModuleSecret, getNamespace, getWatcher } from "./pods";
|
|
13
13
|
import { clusterRole, clusterRoleBinding, serviceAccount, storeRole, storeRoleBinding } from "./rbac";
|
|
14
14
|
import { peprStoreCRD } from "./store";
|
|
@@ -136,9 +136,9 @@ async function setupController(assets: Assets, code: Buffer, hash: string, force
|
|
|
136
136
|
const tls = tlsSecret(name, assets.tls);
|
|
137
137
|
await K8s(kind.Secret).Apply(tls, { force });
|
|
138
138
|
|
|
139
|
-
Log.info("Applying API
|
|
140
|
-
const
|
|
141
|
-
await K8s(kind.Secret).Apply(
|
|
139
|
+
Log.info("Applying API path secret");
|
|
140
|
+
const apiPath = apiPathSecret(name, assets.apiPath);
|
|
141
|
+
await K8s(kind.Secret).Apply(apiPath, { force });
|
|
142
142
|
|
|
143
143
|
Log.info("Applying deployment");
|
|
144
144
|
const dep = getDeployment(assets, hash, assets.buildTimestamp);
|
|
@@ -25,7 +25,7 @@ export async function destroyModule(name: string): Promise<void> {
|
|
|
25
25
|
K8s(kind.Secret, { namespace }).Delete(`${name}-module`),
|
|
26
26
|
K8s(kind.Service, { namespace }).Delete(name),
|
|
27
27
|
K8s(kind.Secret, { namespace }).Delete(`${name}-tls`),
|
|
28
|
-
K8s(kind.Secret, { namespace }).Delete(`${name}-api-
|
|
28
|
+
K8s(kind.Secret, { namespace }).Delete(`${name}-api-path`),
|
|
29
29
|
K8s(kind.Deployment, { namespace }).Delete(name),
|
|
30
30
|
K8s(kind.Deployment, { namespace }).Delete(`${name}-watcher`),
|
|
31
31
|
K8s(kind.Service, { namespace }).Delete(`${name}-watcher`),
|
package/src/lib/assets/helm.ts
CHANGED
|
@@ -221,8 +221,8 @@ export function admissionDeployTemplate(buildTimestamp: string): string {
|
|
|
221
221
|
- name: tls-certs
|
|
222
222
|
mountPath: /etc/certs
|
|
223
223
|
readOnly: true
|
|
224
|
-
- name: api-
|
|
225
|
-
mountPath: /app/api-
|
|
224
|
+
- name: api-path
|
|
225
|
+
mountPath: /app/api-path
|
|
226
226
|
readOnly: true
|
|
227
227
|
- name: module
|
|
228
228
|
mountPath: /app/load
|
|
@@ -234,9 +234,9 @@ export function admissionDeployTemplate(buildTimestamp: string): string {
|
|
|
234
234
|
- name: tls-certs
|
|
235
235
|
secret:
|
|
236
236
|
secretName: {{ .Values.uuid }}-tls
|
|
237
|
-
- name: api-
|
|
237
|
+
- name: api-path
|
|
238
238
|
secret:
|
|
239
|
-
secretName: {{ .Values.uuid }}-api-
|
|
239
|
+
secretName: {{ .Values.uuid }}-api-path
|
|
240
240
|
- name: module
|
|
241
241
|
secret:
|
|
242
242
|
secretName: {{ .Values.uuid }}-module
|
package/src/lib/assets/index.ts
CHANGED
|
@@ -5,14 +5,13 @@ import { dumpYaml } from "@kubernetes/client-node";
|
|
|
5
5
|
import { kind } from "kubernetes-fluent-client";
|
|
6
6
|
import { replaceString } from "../helpers";
|
|
7
7
|
import { resolve } from "path";
|
|
8
|
-
import { ModuleConfig } from "../
|
|
8
|
+
import { ModuleConfig } from "../types";
|
|
9
9
|
|
|
10
10
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
11
11
|
export function toYaml(obj: any): string {
|
|
12
12
|
return dumpYaml(obj, { noRefs: true });
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
// Unit Test Me!!
|
|
16
15
|
export function createWebhookYaml(
|
|
17
16
|
name: string,
|
|
18
17
|
config: ModuleConfig,
|
|
@@ -81,7 +80,7 @@ export function helmLayout(basePath: string, unique: string): Record<string, Rec
|
|
|
81
80
|
watcherDeploymentYaml: `${helm.dirs.tmpls}/watcher-deployment.yaml`,
|
|
82
81
|
watcherServiceMonitorYaml: `${helm.dirs.tmpls}/watcher-service-monitor.yaml`,
|
|
83
82
|
tlsSecretYaml: `${helm.dirs.tmpls}/tls-secret.yaml`,
|
|
84
|
-
|
|
83
|
+
apiPathSecretYaml: `${helm.dirs.tmpls}/api-path-secret.yaml`,
|
|
85
84
|
moduleSecretYaml: `${helm.dirs.tmpls}/module-secret.yaml`,
|
|
86
85
|
storeRoleYaml: `${helm.dirs.tmpls}/store-role.yaml`,
|
|
87
86
|
storeRoleBindingYaml: `${helm.dirs.tmpls}/store-role-binding.yaml`,
|
|
@@ -5,17 +5,17 @@ import { kind } from "kubernetes-fluent-client";
|
|
|
5
5
|
|
|
6
6
|
import { TLSOut } from "../tls";
|
|
7
7
|
|
|
8
|
-
export function
|
|
8
|
+
export function apiPathSecret(name: string, apiPath: string): kind.Secret {
|
|
9
9
|
return {
|
|
10
10
|
apiVersion: "v1",
|
|
11
11
|
kind: "Secret",
|
|
12
12
|
metadata: {
|
|
13
|
-
name: `${name}-api-
|
|
13
|
+
name: `${name}-api-path`,
|
|
14
14
|
namespace: "pepr-system",
|
|
15
15
|
},
|
|
16
16
|
type: "Opaque",
|
|
17
17
|
data: {
|
|
18
|
-
value: Buffer.from(
|
|
18
|
+
value: Buffer.from(apiPath).toString("base64"),
|
|
19
19
|
},
|
|
20
20
|
};
|
|
21
21
|
}
|
package/src/lib/assets/pods.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { kind } from "kubernetes-fluent-client";
|
|
|
6
6
|
import { gzipSync } from "zlib";
|
|
7
7
|
import { secretOverLimit } from "../helpers";
|
|
8
8
|
import { Assets } from "./assets";
|
|
9
|
-
import { ModuleConfig } from "../
|
|
9
|
+
import { ModuleConfig } from "../types";
|
|
10
10
|
import { Binding } from "../types";
|
|
11
11
|
|
|
12
12
|
/** Generate the pepr-system namespace */
|
|
@@ -297,8 +297,8 @@ export function getDeployment(
|
|
|
297
297
|
readOnly: true,
|
|
298
298
|
},
|
|
299
299
|
{
|
|
300
|
-
name: "api-
|
|
301
|
-
mountPath: "/app/api-
|
|
300
|
+
name: "api-path",
|
|
301
|
+
mountPath: "/app/api-path",
|
|
302
302
|
readOnly: true,
|
|
303
303
|
},
|
|
304
304
|
{
|
|
@@ -317,9 +317,9 @@ export function getDeployment(
|
|
|
317
317
|
},
|
|
318
318
|
},
|
|
319
319
|
{
|
|
320
|
-
name: "api-
|
|
320
|
+
name: "api-path",
|
|
321
321
|
secret: {
|
|
322
|
-
secretName: `${name}-api-
|
|
322
|
+
secretName: `${name}-api-path`,
|
|
323
323
|
},
|
|
324
324
|
},
|
|
325
325
|
{
|
|
@@ -75,7 +75,7 @@ export async function webhookConfigGenerator(
|
|
|
75
75
|
): Promise<kind.MutatingWebhookConfiguration | kind.ValidatingWebhookConfiguration | null> {
|
|
76
76
|
const ignore: V1LabelSelectorRequirement[] = [];
|
|
77
77
|
|
|
78
|
-
const { name, tls, config,
|
|
78
|
+
const { name, tls, config, apiPath, host } = assets;
|
|
79
79
|
const ignoreNS = concat(peprIgnoreNamespaces, resolveIgnoreNamespaces(config?.alwaysIgnore?.namespaces));
|
|
80
80
|
|
|
81
81
|
// Add any namespaces to ignore
|
|
@@ -91,18 +91,18 @@ export async function webhookConfigGenerator(
|
|
|
91
91
|
caBundle: tls.ca,
|
|
92
92
|
};
|
|
93
93
|
|
|
94
|
-
// The URL must include the API
|
|
95
|
-
const
|
|
94
|
+
// The URL must include the API Path
|
|
95
|
+
const fullApiPath = `/${mutateOrValidate}/${apiPath}`;
|
|
96
96
|
|
|
97
97
|
// If a host is specified, use that with a port of 3000
|
|
98
98
|
if (host) {
|
|
99
|
-
clientConfig.url = `https://${host}:3000${
|
|
99
|
+
clientConfig.url = `https://${host}:3000${fullApiPath}`;
|
|
100
100
|
} else {
|
|
101
101
|
// Otherwise, use the service
|
|
102
102
|
clientConfig.service = {
|
|
103
103
|
name: name,
|
|
104
104
|
namespace: "pepr-system",
|
|
105
|
-
path:
|
|
105
|
+
path: fullApiPath,
|
|
106
106
|
};
|
|
107
107
|
}
|
|
108
108
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import crypto from "crypto";
|
|
5
5
|
import { Assets } from "../assets";
|
|
6
6
|
import { WebhookType } from "../../enums";
|
|
7
|
-
import {
|
|
7
|
+
import { apiPathSecret, service, tlsSecret, watcherService } from "../networking";
|
|
8
8
|
import { clusterRole, clusterRoleBinding, serviceAccount, storeRole, storeRoleBinding } from "../rbac";
|
|
9
9
|
import { dumpYaml, V1Deployment } from "@kubernetes/client-node";
|
|
10
10
|
import { getModuleSecret, getNamespace } from "../pods";
|
|
@@ -14,7 +14,7 @@ import { webhookConfigGenerator } from "../webhooks";
|
|
|
14
14
|
type deployments = { default: V1Deployment; watch: V1Deployment | null };
|
|
15
15
|
|
|
16
16
|
export async function generateAllYaml(assets: Assets, deployments: deployments): Promise<string> {
|
|
17
|
-
const { name, tls,
|
|
17
|
+
const { name, tls, apiPath, path, config } = assets;
|
|
18
18
|
const code = await fs.readFile(path);
|
|
19
19
|
const hash = crypto.createHash("sha256").update(code).digest("hex");
|
|
20
20
|
|
|
@@ -23,7 +23,7 @@ export async function generateAllYaml(assets: Assets, deployments: deployments):
|
|
|
23
23
|
clusterRole(name, assets.capabilities, config.rbacMode, config.rbac),
|
|
24
24
|
clusterRoleBinding(name),
|
|
25
25
|
serviceAccount(name),
|
|
26
|
-
|
|
26
|
+
apiPathSecret(name, apiPath),
|
|
27
27
|
tlsSecret(name, tls),
|
|
28
28
|
deployments.default,
|
|
29
29
|
service(name),
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { genEnv } from "../pods";
|
|
2
|
-
import { ModuleConfig } from "../../
|
|
2
|
+
import { ModuleConfig } from "../../types";
|
|
3
3
|
import { CapabilityExport } from "../../types";
|
|
4
4
|
import { dumpYaml } from "@kubernetes/client-node";
|
|
5
5
|
import { clusterRole } from "../rbac";
|
|
6
6
|
import { promises as fs } from "fs";
|
|
7
7
|
|
|
8
8
|
type ChartOverrides = {
|
|
9
|
-
|
|
9
|
+
apiPath: string;
|
|
10
10
|
capabilities: CapabilityExport[];
|
|
11
11
|
config: ModuleConfig;
|
|
12
12
|
hash: string;
|
|
@@ -16,7 +16,7 @@ type ChartOverrides = {
|
|
|
16
16
|
|
|
17
17
|
// Helm Chart overrides file (values.yaml) generated from assets
|
|
18
18
|
export async function overridesFile(
|
|
19
|
-
{ hash, name, image, config,
|
|
19
|
+
{ hash, name, image, config, apiPath, capabilities }: ChartOverrides,
|
|
20
20
|
path: string,
|
|
21
21
|
imagePullSecrets: string[],
|
|
22
22
|
): Promise<void> {
|
|
@@ -27,7 +27,7 @@ export async function overridesFile(
|
|
|
27
27
|
additionalIgnoredNamespaces: [],
|
|
28
28
|
rbac: rbacOverrides,
|
|
29
29
|
secrets: {
|
|
30
|
-
|
|
30
|
+
apiPath: Buffer.from(apiPath).toString("base64"),
|
|
31
31
|
},
|
|
32
32
|
hash,
|
|
33
33
|
namespace: {
|
|
@@ -9,7 +9,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 {
|
|
12
|
+
import { isWatchMode } from "../core/envChecks";
|
|
13
|
+
import { ModuleConfig } from "../types";
|
|
13
14
|
import { mutateProcessor } from "../processors/mutate-processor";
|
|
14
15
|
import { validateProcessor } from "../processors/validate-processor";
|
|
15
16
|
import { StoreController } from "./store";
|
|
@@ -33,8 +34,8 @@ export class Controller {
|
|
|
33
34
|
// Metrics collector
|
|
34
35
|
#metricsCollector = metricsCollector;
|
|
35
36
|
|
|
36
|
-
// The
|
|
37
|
-
#
|
|
37
|
+
// The path used to authenticate requests
|
|
38
|
+
#path = "";
|
|
38
39
|
|
|
39
40
|
// The express app instance
|
|
40
41
|
readonly #app = express();
|
|
@@ -92,14 +93,14 @@ export class Controller {
|
|
|
92
93
|
cert: fs.readFileSync(process.env.SSL_CERT_PATH || "/etc/certs/tls.crt"),
|
|
93
94
|
};
|
|
94
95
|
|
|
95
|
-
// Get the API
|
|
96
|
+
// Get the API path if not in watch mode
|
|
96
97
|
if (!isWatchMode()) {
|
|
97
|
-
// Get the API
|
|
98
|
-
this.#
|
|
99
|
-
Log.info(`Using API
|
|
98
|
+
// Get the API path from the environment variable or the mounted secret
|
|
99
|
+
this.#path = process.env.PEPR_API_PATH || fs.readFileSync("/app/api-path/value").toString().trim();
|
|
100
|
+
Log.info(`Using API path: ${this.#path}`);
|
|
100
101
|
|
|
101
|
-
if (!this.#
|
|
102
|
-
throw new Error("API
|
|
102
|
+
if (!this.#path) {
|
|
103
|
+
throw new Error("API path not found");
|
|
103
104
|
}
|
|
104
105
|
}
|
|
105
106
|
|
|
@@ -148,35 +149,35 @@ export class Controller {
|
|
|
148
149
|
}
|
|
149
150
|
|
|
150
151
|
// Require auth for webhook endpoints
|
|
151
|
-
this.#app.use(["/mutate/:
|
|
152
|
+
this.#app.use(["/mutate/:path", "/validate/:path"], this.#validatepath);
|
|
152
153
|
|
|
153
154
|
// Mutate endpoint
|
|
154
|
-
this.#app.post("/mutate/:
|
|
155
|
+
this.#app.post("/mutate/:path", this.#admissionReq("Mutate"));
|
|
155
156
|
|
|
156
157
|
// Validate endpoint
|
|
157
|
-
this.#app.post("/validate/:
|
|
158
|
+
this.#app.post("/validate/:path", this.#admissionReq("Validate"));
|
|
158
159
|
};
|
|
159
160
|
|
|
160
161
|
/**
|
|
161
|
-
* Validate the
|
|
162
|
+
* Validate the path in the request path
|
|
162
163
|
*
|
|
163
164
|
* @param req The incoming request
|
|
164
165
|
* @param res The outgoing response
|
|
165
166
|
* @param next The next middleware function
|
|
166
167
|
* @returns
|
|
167
168
|
*/
|
|
168
|
-
#
|
|
169
|
-
// Validate the
|
|
170
|
-
const {
|
|
171
|
-
if (
|
|
172
|
-
const err = `Unauthorized: invalid
|
|
169
|
+
#validatepath = (req: express.Request, res: express.Response, next: NextFunction): void => {
|
|
170
|
+
// Validate the path
|
|
171
|
+
const { path } = req.params;
|
|
172
|
+
if (path !== this.#path) {
|
|
173
|
+
const err = `Unauthorized: invalid path '${path.replace(/[^\w]/g, "_")}'`;
|
|
173
174
|
Log.info(err);
|
|
174
175
|
res.status(401).send(err);
|
|
175
176
|
this.#metricsCollector.alert();
|
|
176
177
|
return;
|
|
177
178
|
}
|
|
178
179
|
|
|
179
|
-
//
|
|
180
|
+
// path is valid, continue
|
|
180
181
|
next();
|
|
181
182
|
};
|
|
182
183
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { GenericClass, GroupVersionKind, modelToGroupVersionKind } from "kubernetes-fluent-client";
|
|
5
5
|
import { pickBy } from "ramda";
|
|
6
6
|
import Log from "../telemetry/logger";
|
|
7
|
-
import { isBuildMode, isDevMode, isWatchMode } from "./
|
|
7
|
+
import { isBuildMode, isDevMode, isWatchMode } from "./envChecks";
|
|
8
8
|
import { PeprStore, Storage } from "./storage";
|
|
9
9
|
import { OnSchedule, Schedule } from "./schedule";
|
|
10
10
|
import { Event } from "../enums";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export const isWatchMode = (): boolean => process.env.PEPR_WATCH_MODE === "true";
|
|
2
|
+
// Track if Pepr is running in build mode
|
|
3
|
+
|
|
4
|
+
export const isBuildMode = (): boolean => process.env.PEPR_MODE === "build";
|
|
5
|
+
|
|
6
|
+
export const isDevMode = (): boolean => process.env.PEPR_MODE === "dev";
|
package/src/lib/core/module.ts
CHANGED
|
@@ -4,71 +4,12 @@ import { clone } from "ramda";
|
|
|
4
4
|
import { Capability } from "./capability";
|
|
5
5
|
import { Controller, ControllerHooks } from "../controller";
|
|
6
6
|
import { ValidateError } from "../errors";
|
|
7
|
-
import {
|
|
8
|
-
import { CapabilityExport, AdmissionRequest } from "../types";
|
|
7
|
+
import { CapabilityExport } from "../types";
|
|
9
8
|
import { setupWatch } from "../processors/watch-processor";
|
|
10
9
|
import { Log } from "../../lib";
|
|
11
|
-
import { V1PolicyRule as PolicyRule } from "@kubernetes/client-node";
|
|
12
10
|
import { resolveIgnoreNamespaces } from "../assets/webhooks";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
export type CustomLabels = { namespace: Record<string, string> } | Record<string, never>;
|
|
17
|
-
|
|
18
|
-
/** Configuration that MAY be set a Pepr module's package.json. */
|
|
19
|
-
export type ModuleConfigOptions = {
|
|
20
|
-
/** The Pepr version this module uses */
|
|
21
|
-
peprVersion: string;
|
|
22
|
-
/** The user-defined version of the module */
|
|
23
|
-
appVersion: string;
|
|
24
|
-
/** A description of the Pepr module and what it does. */
|
|
25
|
-
description: string;
|
|
26
|
-
/** The webhookTimeout */
|
|
27
|
-
webhookTimeout: number;
|
|
28
|
-
/** Reject K8s resource AdmissionRequests on error. */
|
|
29
|
-
onError: string;
|
|
30
|
-
/** Define the log level for the in-cluster controllers */
|
|
31
|
-
logLevel: string;
|
|
32
|
-
/** Propagate env variables to in-cluster controllers */
|
|
33
|
-
env: Record<string, string>;
|
|
34
|
-
/** Custom RBAC rules */
|
|
35
|
-
rbac: PolicyRule[];
|
|
36
|
-
/** The RBAC mode; if "scoped", generates scoped rules, otherwise uses wildcard rules. */
|
|
37
|
-
rbacMode: string;
|
|
38
|
-
/** Custom Labels for Kubernetes Objects */
|
|
39
|
-
customLabels: CustomLabels;
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
/** Global configuration for the Pepr runtime. */
|
|
43
|
-
export type ModuleConfig = {
|
|
44
|
-
/** A unique identifier for this Pepr module. This is automatically generated by Pepr. */
|
|
45
|
-
uuid: string;
|
|
46
|
-
/** Configure global exclusions that will never be processed by Pepr. */
|
|
47
|
-
alwaysIgnore: WebhookIgnore;
|
|
48
|
-
} & Partial<ModuleConfigOptions>;
|
|
49
|
-
|
|
50
|
-
export type PackageJSON = {
|
|
51
|
-
description: string;
|
|
52
|
-
pepr: ModuleConfig;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
export type PeprModuleOptions = {
|
|
56
|
-
deferStart?: boolean;
|
|
57
|
-
|
|
58
|
-
/** A user-defined callback to pre-process or intercept a Pepr request from K8s immediately before it is processed */
|
|
59
|
-
beforeHook?: (req: AdmissionRequest) => void;
|
|
60
|
-
|
|
61
|
-
/** A user-defined callback to post-process or intercept a Pepr response just before it is returned to K8s */
|
|
62
|
-
afterHook?: (res: MutateResponse | ValidateResponse) => void;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
// Track if this is a watch mode controller
|
|
66
|
-
export const isWatchMode = (): boolean => process.env.PEPR_WATCH_MODE === "true";
|
|
67
|
-
|
|
68
|
-
// Track if Pepr is running in build mode
|
|
69
|
-
export const isBuildMode = (): boolean => process.env.PEPR_MODE === "build";
|
|
70
|
-
|
|
71
|
-
export const isDevMode = (): boolean => process.env.PEPR_MODE === "dev";
|
|
11
|
+
import { isBuildMode, isDevMode, isWatchMode } from "./envChecks";
|
|
12
|
+
import { PackageJSON, PeprModuleOptions, ModuleConfig } from "../types";
|
|
72
13
|
|
|
73
14
|
export class PeprModule {
|
|
74
15
|
#controller!: Controller;
|