pepr 0.45.1-nightly.0 → 0.45.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -8
- 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 +0 -4
- package/dist/cli/init/templates.d.ts.map +1 -1
- package/dist/cli.js +37 -31
- package/dist/controller.js +1 -1
- package/dist/lib/assets/assets.d.ts +1 -1
- package/dist/lib/assets/assets.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/yaml/overridesFile.d.ts +2 -2
- package/dist/lib/assets/yaml/overridesFile.d.ts.map +1 -1
- package/dist/lib.js +15 -15
- package/dist/lib.js.map +2 -2
- package/package.json +2 -6
- package/src/cli/build.helpers.ts +1 -1
- package/src/cli/build.ts +10 -2
- package/src/cli/dev.ts +1 -1
- package/src/lib/assets/assets.ts +6 -6
- 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 +1 -1
- package/src/lib/assets/networking.ts +3 -3
- package/src/lib/assets/pods.ts +4 -4
- package/src/lib/assets/webhooks.ts +5 -5
- package/src/lib/assets/yaml/generateAllYaml.ts +3 -3
- package/src/lib/assets/yaml/overridesFile.ts +3 -3
- package/src/lib/controller/index.ts +18 -18
- package/src/lib/telemetry/metrics.ts +1 -1
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.1
|
|
18
|
+
"version": "0.45.1",
|
|
19
19
|
"main": "dist/lib.js",
|
|
20
20
|
"types": "dist/lib.d.ts",
|
|
21
21
|
"scripts": {
|
|
@@ -24,7 +24,6 @@
|
|
|
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 .",
|
|
28
27
|
"set:version": "node scripts/set-version.js",
|
|
29
28
|
"test": "npm run test:unit && npm run test:journey && npm run test:journey-wasm",
|
|
30
29
|
"test:unit": "npm run gen-data-json && jest src --coverage --detectOpenHandles --coverageDirectory=./coverage --testPathIgnorePatterns='cosign.e2e.test.ts'",
|
|
@@ -32,12 +31,9 @@
|
|
|
32
31
|
"test:integration:prep": "./integration/prep.sh",
|
|
33
32
|
"test:integration:run": "jest --maxWorkers=4 integration",
|
|
34
33
|
"test:journey": "npm run test:journey:k3d && npm run build && npm run test:journey:image && npm run test:journey:run",
|
|
35
|
-
"test:journey:unicorn": "npm run test:journey:k3d && npm run build && npm run test:journey:image:unicorn && npm run test:journey:run",
|
|
36
34
|
"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",
|
|
38
35
|
"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",
|
|
39
36
|
"test:journey:image": "docker buildx build --output type=docker --tag pepr:dev . && k3d image import pepr:dev -c pepr-dev",
|
|
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
37
|
"test:journey:run": "jest --detectOpenHandles journey/entrypoint.test.ts && npm run test:journey:upgrade",
|
|
42
38
|
"test:journey:run-wasm": "jest --detectOpenHandles journey/entrypoint-wasm.test.ts",
|
|
43
39
|
"test:journey:upgrade": "npm run test:journey:k3d && npm run test:journey:image && jest --detectOpenHandles journey/pepr-upgrade.test.ts",
|
|
@@ -95,4 +91,4 @@
|
|
|
95
91
|
"typescript": "5.7.3",
|
|
96
92
|
"uuid": "11.0.5"
|
|
97
93
|
}
|
|
98
|
-
}
|
|
94
|
+
}
|
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
|
@@ -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(["registryInfo", "registry"]),
|
|
80
|
+
).conflicts(["version", "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", "registry"]),
|
|
86
|
+
).conflicts(["customImage", "version", "registry"]),
|
|
87
87
|
)
|
|
88
88
|
|
|
89
89
|
.option("-o, --output-dir <output directory>", "Define where to place build output")
|
|
@@ -92,6 +92,12 @@ 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
|
+
"DEPRECATED: The version of the Pepr image to use in the deployment manifests. Example: '0.27.3'.",
|
|
99
|
+
).conflicts(["customImage", "registryInfo"]),
|
|
100
|
+
)
|
|
95
101
|
.option(
|
|
96
102
|
"--withPullSecret <imagePullSecret>",
|
|
97
103
|
"Image Pull Secret: Use image pull secret for controller Deployment.",
|
|
@@ -158,6 +164,8 @@ export default function (program: RootCmd): void {
|
|
|
158
164
|
console.info(`✅ Module built successfully at ${path}`);
|
|
159
165
|
return;
|
|
160
166
|
}
|
|
167
|
+
// set the image version if provided -- DEPRECATED
|
|
168
|
+
if (opts.version) cfg.pepr.peprVersion = opts.version;
|
|
161
169
|
|
|
162
170
|
// Generate a secret for the module
|
|
163
171
|
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_TOKEN: webhook.apiToken,
|
|
81
81
|
PEPR_PRETTY_LOGS: "true",
|
|
82
82
|
SSL_KEY_PATH: "insecure-tls.key",
|
|
83
83
|
SSL_CERT_PATH: "insecure-tls.crt",
|
package/src/lib/assets/assets.ts
CHANGED
|
@@ -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, apiTokenSecret } 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 apiToken: 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 token for the controller / webhook
|
|
57
|
+
this.apiToken = crypto.randomBytes(32).toString("hex");
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
async deploy(
|
|
@@ -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.apiTokenSecretYaml, (): string => toYaml(apiTokenSecret(this.name, this.apiToken))],
|
|
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
|
+
apiToken: this.apiToken,
|
|
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 { apiTokenSecret, 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 token secret");
|
|
140
|
+
const apiToken = apiTokenSecret(name, assets.apiToken);
|
|
141
|
+
await K8s(kind.Secret).Apply(apiToken, { 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-token`),
|
|
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-token
|
|
225
|
+
mountPath: /app/api-token
|
|
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-token
|
|
238
238
|
secret:
|
|
239
|
-
secretName: {{ .Values.uuid }}-api-
|
|
239
|
+
secretName: {{ .Values.uuid }}-api-token
|
|
240
240
|
- name: module
|
|
241
241
|
secret:
|
|
242
242
|
secretName: {{ .Values.uuid }}-module
|
package/src/lib/assets/index.ts
CHANGED
|
@@ -80,7 +80,7 @@ export function helmLayout(basePath: string, unique: string): Record<string, Rec
|
|
|
80
80
|
watcherDeploymentYaml: `${helm.dirs.tmpls}/watcher-deployment.yaml`,
|
|
81
81
|
watcherServiceMonitorYaml: `${helm.dirs.tmpls}/watcher-service-monitor.yaml`,
|
|
82
82
|
tlsSecretYaml: `${helm.dirs.tmpls}/tls-secret.yaml`,
|
|
83
|
-
|
|
83
|
+
apiTokenSecretYaml: `${helm.dirs.tmpls}/api-token-secret.yaml`,
|
|
84
84
|
moduleSecretYaml: `${helm.dirs.tmpls}/module-secret.yaml`,
|
|
85
85
|
storeRoleYaml: `${helm.dirs.tmpls}/store-role.yaml`,
|
|
86
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 apiTokenSecret(name: string, apiToken: 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-token`,
|
|
14
14
|
namespace: "pepr-system",
|
|
15
15
|
},
|
|
16
16
|
type: "Opaque",
|
|
17
17
|
data: {
|
|
18
|
-
value: Buffer.from(
|
|
18
|
+
value: Buffer.from(apiToken).toString("base64"),
|
|
19
19
|
},
|
|
20
20
|
};
|
|
21
21
|
}
|
package/src/lib/assets/pods.ts
CHANGED
|
@@ -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-token",
|
|
301
|
+
mountPath: "/app/api-token",
|
|
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-token",
|
|
321
321
|
secret: {
|
|
322
|
-
secretName: `${name}-api-
|
|
322
|
+
secretName: `${name}-api-token`,
|
|
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, apiToken, 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 Token
|
|
95
|
+
const apiPath = `/${mutateOrValidate}/${apiToken}`;
|
|
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${apiPath}`;
|
|
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: apiPath,
|
|
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 { apiTokenSecret, 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, apiToken, 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
|
+
apiTokenSecret(name, apiToken),
|
|
27
27
|
tlsSecret(name, tls),
|
|
28
28
|
deployments.default,
|
|
29
29
|
service(name),
|
|
@@ -6,7 +6,7 @@ import { clusterRole } from "../rbac";
|
|
|
6
6
|
import { promises as fs } from "fs";
|
|
7
7
|
|
|
8
8
|
type ChartOverrides = {
|
|
9
|
-
|
|
9
|
+
apiToken: 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, apiToken, 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
|
+
apiToken: Buffer.from(apiToken).toString("base64"),
|
|
31
31
|
},
|
|
32
32
|
hash,
|
|
33
33
|
namespace: {
|
|
@@ -34,8 +34,8 @@ export class Controller {
|
|
|
34
34
|
// Metrics collector
|
|
35
35
|
#metricsCollector = metricsCollector;
|
|
36
36
|
|
|
37
|
-
// The
|
|
38
|
-
#
|
|
37
|
+
// The token used to authenticate requests
|
|
38
|
+
#token = "";
|
|
39
39
|
|
|
40
40
|
// The express app instance
|
|
41
41
|
readonly #app = express();
|
|
@@ -93,14 +93,14 @@ export class Controller {
|
|
|
93
93
|
cert: fs.readFileSync(process.env.SSL_CERT_PATH || "/etc/certs/tls.crt"),
|
|
94
94
|
};
|
|
95
95
|
|
|
96
|
-
// Get the API
|
|
96
|
+
// Get the API token if not in watch mode
|
|
97
97
|
if (!isWatchMode()) {
|
|
98
|
-
// Get the API
|
|
99
|
-
this.#
|
|
100
|
-
Log.info(`Using API
|
|
98
|
+
// Get the API token from the environment variable or the mounted secret
|
|
99
|
+
this.#token = process.env.PEPR_API_TOKEN || fs.readFileSync("/app/api-token/value").toString().trim();
|
|
100
|
+
Log.info(`Using API token: ${this.#token}`);
|
|
101
101
|
|
|
102
|
-
if (!this.#
|
|
103
|
-
throw new Error("API
|
|
102
|
+
if (!this.#token) {
|
|
103
|
+
throw new Error("API token not found");
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
|
|
@@ -149,35 +149,35 @@ export class Controller {
|
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
// Require auth for webhook endpoints
|
|
152
|
-
this.#app.use(["/mutate/:
|
|
152
|
+
this.#app.use(["/mutate/:token", "/validate/:token"], this.#validateToken);
|
|
153
153
|
|
|
154
154
|
// Mutate endpoint
|
|
155
|
-
this.#app.post("/mutate/:
|
|
155
|
+
this.#app.post("/mutate/:token", this.#admissionReq("Mutate"));
|
|
156
156
|
|
|
157
157
|
// Validate endpoint
|
|
158
|
-
this.#app.post("/validate/:
|
|
158
|
+
this.#app.post("/validate/:token", this.#admissionReq("Validate"));
|
|
159
159
|
};
|
|
160
160
|
|
|
161
161
|
/**
|
|
162
|
-
* Validate the
|
|
162
|
+
* Validate the token in the request path
|
|
163
163
|
*
|
|
164
164
|
* @param req The incoming request
|
|
165
165
|
* @param res The outgoing response
|
|
166
166
|
* @param next The next middleware function
|
|
167
167
|
* @returns
|
|
168
168
|
*/
|
|
169
|
-
#
|
|
170
|
-
// Validate the
|
|
171
|
-
const {
|
|
172
|
-
if (
|
|
173
|
-
const err = `Unauthorized: invalid
|
|
169
|
+
#validateToken = (req: express.Request, res: express.Response, next: NextFunction): void => {
|
|
170
|
+
// Validate the token
|
|
171
|
+
const { token } = req.params;
|
|
172
|
+
if (token !== this.#token) {
|
|
173
|
+
const err = `Unauthorized: invalid token '${token.replace(/[^\w]/g, "_")}'`;
|
|
174
174
|
Log.info(err);
|
|
175
175
|
res.status(401).send(err);
|
|
176
176
|
this.#metricsCollector.alert();
|
|
177
177
|
return;
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
-
//
|
|
180
|
+
// Token is valid, continue
|
|
181
181
|
next();
|
|
182
182
|
};
|
|
183
183
|
|
|
@@ -54,7 +54,7 @@ export class MetricsCollector {
|
|
|
54
54
|
this.#registry = new Registry();
|
|
55
55
|
this.#prefix = prefix;
|
|
56
56
|
this.addCounter(this.#metricNames.errors, "Mutation/Validate errors encountered");
|
|
57
|
-
this.addCounter(this.#metricNames.alerts, "Mutation/Validate bad api
|
|
57
|
+
this.addCounter(this.#metricNames.alerts, "Mutation/Validate bad api token received");
|
|
58
58
|
this.addSummary(this.#metricNames.mutate, "Mutation operation summary");
|
|
59
59
|
this.addSummary(this.#metricNames.validate, "Validation operation summary");
|
|
60
60
|
this.addGauge(this.#metricNames.cacheMiss, "Number of cache misses per window", ["window"]);
|