pepr 0.1.28 → 0.1.30
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/cli.ts +3 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +4 -0
- package/dist/index.js +14 -5
- package/dist/package.json +2 -2
- package/dist/src/cli/banner.js +4 -1
- package/dist/src/cli/build.js +41 -34
- package/dist/src/cli/capability.js +4 -1
- package/dist/src/cli/deploy.js +18 -12
- package/dist/src/cli/dev.js +32 -26
- package/dist/src/cli/index.js +24 -19
- package/dist/src/cli/init/index.js +32 -26
- package/dist/src/cli/init/templates.js +23 -18
- package/dist/src/cli/init/utils.js +12 -6
- package/dist/src/cli/init/walkthrough.js +27 -19
- package/dist/src/cli/root.js +12 -5
- package/dist/src/cli/test.js +23 -17
- package/dist/src/lib/capability.js +26 -19
- package/dist/src/lib/controller.js +18 -11
- package/dist/src/lib/filter.js +12 -5
- package/dist/src/lib/k8s/index.js +35 -4
- package/dist/src/lib/k8s/kinds.js +7 -3
- package/dist/src/lib/k8s/tls.js +17 -10
- package/dist/src/lib/k8s/types.js +5 -2
- package/dist/src/lib/k8s/upstream.js +45 -1
- package/dist/src/lib/k8s/webhook.js +54 -47
- package/dist/src/lib/logger.js +8 -4
- package/dist/src/lib/module.js +12 -5
- package/dist/src/lib/processor.js +21 -14
- package/dist/src/lib/request.js +29 -2
- package/dist/src/lib/types.js +9 -6
- package/package.json +2 -2
package/dist/src/lib/k8s/tls.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.genTLS = void 0;
|
|
7
|
+
const node_forge_1 = __importDefault(require("node-forge"));
|
|
2
8
|
const caName = "Pepr Ephemeral CA";
|
|
3
9
|
/**
|
|
4
10
|
* Generates a self-signed CA and server certificate with Subject Alternative Names (SANs) for the K8s webhook.
|
|
@@ -6,9 +12,9 @@ const caName = "Pepr Ephemeral CA";
|
|
|
6
12
|
* @param {string} name - The name to use for the server certificate's Common Name and SAN DNS entry.
|
|
7
13
|
* @returns {TLSOut} - An object containing the Base64-encoded CA, server certificate, and server private key.
|
|
8
14
|
*/
|
|
9
|
-
|
|
15
|
+
function genTLS(name) {
|
|
10
16
|
// Generate a new CA key pair and create a self-signed CA certificate
|
|
11
|
-
const caKeys =
|
|
17
|
+
const caKeys = node_forge_1.default.pki.rsa.generateKeyPair(2048);
|
|
12
18
|
const caCert = genCert(caKeys, caName, [{ name: "commonName", value: caName }]);
|
|
13
19
|
caCert.setExtensions([
|
|
14
20
|
{
|
|
@@ -25,16 +31,16 @@ export function genTLS(name) {
|
|
|
25
31
|
},
|
|
26
32
|
]);
|
|
27
33
|
// Generate a new server key pair and create a server certificate signed by the CA
|
|
28
|
-
const serverKeys =
|
|
34
|
+
const serverKeys = node_forge_1.default.pki.rsa.generateKeyPair(2048);
|
|
29
35
|
const serverCert = genCert(serverKeys, name, caCert.subject.attributes);
|
|
30
36
|
// Sign both certificates with the CA private key
|
|
31
|
-
caCert.sign(caKeys.privateKey,
|
|
32
|
-
serverCert.sign(caKeys.privateKey,
|
|
37
|
+
caCert.sign(caKeys.privateKey, node_forge_1.default.md.sha256.create());
|
|
38
|
+
serverCert.sign(caKeys.privateKey, node_forge_1.default.md.sha256.create());
|
|
33
39
|
// Convert the keys and certificates to PEM format
|
|
34
40
|
const pem = {
|
|
35
|
-
ca:
|
|
36
|
-
crt:
|
|
37
|
-
key:
|
|
41
|
+
ca: node_forge_1.default.pki.certificateToPem(caCert),
|
|
42
|
+
crt: node_forge_1.default.pki.certificateToPem(serverCert),
|
|
43
|
+
key: node_forge_1.default.pki.privateKeyToPem(serverKeys.privateKey),
|
|
38
44
|
};
|
|
39
45
|
// Base64-encode the PEM strings
|
|
40
46
|
const ca = Buffer.from(pem.ca).toString("base64");
|
|
@@ -42,8 +48,9 @@ export function genTLS(name) {
|
|
|
42
48
|
const crt = Buffer.from(pem.crt).toString("base64");
|
|
43
49
|
return { ca, key, crt, pem };
|
|
44
50
|
}
|
|
51
|
+
exports.genTLS = genTLS;
|
|
45
52
|
function genCert(key, name, issuer) {
|
|
46
|
-
const crt =
|
|
53
|
+
const crt = node_forge_1.default.pki.createCertificate();
|
|
47
54
|
crt.publicKey = key.publicKey;
|
|
48
55
|
crt.serialNumber = "01";
|
|
49
56
|
crt.validity.notBefore = new Date();
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
3
|
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
|
-
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.Operation = void 0;
|
|
6
|
+
var Operation;
|
|
4
7
|
(function (Operation) {
|
|
5
8
|
Operation["CREATE"] = "CREATE";
|
|
6
9
|
Operation["UPDATE"] = "UPDATE";
|
|
7
10
|
Operation["DELETE"] = "DELETE";
|
|
8
11
|
Operation["CONNECT"] = "CONNECT";
|
|
9
|
-
})(Operation || (Operation = {}));
|
|
12
|
+
})(Operation = exports.Operation || (exports.Operation = {}));
|
|
@@ -1,3 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
3
|
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
|
-
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.VolumeAttachment = exports.ValidatingWebhookConfiguration = exports.TokenReview = exports.SubjectAccessReview = exports.StorageClass = exports.StatefulSet = exports.ServiceAccount = exports.Service = exports.SelfSubjectRulesReview = exports.SelfSubjectAccessReview = exports.Secret = exports.RuntimeClass = exports.ResourceQuota = exports.ReplicationController = exports.ReplicaSet = exports.PodTemplate = exports.PodDisruptionBudget = exports.Pod = exports.PersistentVolumeClaim = exports.PersistentVolume = exports.Node = exports.NetworkPolicy = exports.Namespace = exports.MutatingWebhookConfiguration = exports.LocalSubjectAccessReview = exports.LimitRange = exports.Job = exports.IngressClass = exports.Ingress = exports.HorizontalPodAutoscaler = exports.EndpointSlice = exports.Deployment = exports.DaemonSet = exports.CustomResourceDefinition = exports.CSIStorageCapacity = exports.CSIDriver = exports.CronJob = exports.ControllerRevision = exports.ConfigMap = exports.CertificateSigningRequest = exports.APIService = void 0;
|
|
6
|
+
var dist_1 = require("@kubernetes/client-node/dist");
|
|
7
|
+
Object.defineProperty(exports, "APIService", { enumerable: true, get: function () { return dist_1.V1APIService; } });
|
|
8
|
+
Object.defineProperty(exports, "CertificateSigningRequest", { enumerable: true, get: function () { return dist_1.V1CertificateSigningRequest; } });
|
|
9
|
+
Object.defineProperty(exports, "ConfigMap", { enumerable: true, get: function () { return dist_1.V1ConfigMap; } });
|
|
10
|
+
Object.defineProperty(exports, "ControllerRevision", { enumerable: true, get: function () { return dist_1.V1ControllerRevision; } });
|
|
11
|
+
Object.defineProperty(exports, "CronJob", { enumerable: true, get: function () { return dist_1.V1CronJob; } });
|
|
12
|
+
Object.defineProperty(exports, "CSIDriver", { enumerable: true, get: function () { return dist_1.V1CSIDriver; } });
|
|
13
|
+
Object.defineProperty(exports, "CSIStorageCapacity", { enumerable: true, get: function () { return dist_1.V1CSIStorageCapacity; } });
|
|
14
|
+
Object.defineProperty(exports, "CustomResourceDefinition", { enumerable: true, get: function () { return dist_1.V1CustomResourceDefinition; } });
|
|
15
|
+
Object.defineProperty(exports, "DaemonSet", { enumerable: true, get: function () { return dist_1.V1DaemonSet; } });
|
|
16
|
+
Object.defineProperty(exports, "Deployment", { enumerable: true, get: function () { return dist_1.V1Deployment; } });
|
|
17
|
+
Object.defineProperty(exports, "EndpointSlice", { enumerable: true, get: function () { return dist_1.V1EndpointSlice; } });
|
|
18
|
+
Object.defineProperty(exports, "HorizontalPodAutoscaler", { enumerable: true, get: function () { return dist_1.V1HorizontalPodAutoscaler; } });
|
|
19
|
+
Object.defineProperty(exports, "Ingress", { enumerable: true, get: function () { return dist_1.V1Ingress; } });
|
|
20
|
+
Object.defineProperty(exports, "IngressClass", { enumerable: true, get: function () { return dist_1.V1IngressClass; } });
|
|
21
|
+
Object.defineProperty(exports, "Job", { enumerable: true, get: function () { return dist_1.V1Job; } });
|
|
22
|
+
Object.defineProperty(exports, "LimitRange", { enumerable: true, get: function () { return dist_1.V1LimitRange; } });
|
|
23
|
+
Object.defineProperty(exports, "LocalSubjectAccessReview", { enumerable: true, get: function () { return dist_1.V1LocalSubjectAccessReview; } });
|
|
24
|
+
Object.defineProperty(exports, "MutatingWebhookConfiguration", { enumerable: true, get: function () { return dist_1.V1MutatingWebhookConfiguration; } });
|
|
25
|
+
Object.defineProperty(exports, "Namespace", { enumerable: true, get: function () { return dist_1.V1Namespace; } });
|
|
26
|
+
Object.defineProperty(exports, "NetworkPolicy", { enumerable: true, get: function () { return dist_1.V1NetworkPolicy; } });
|
|
27
|
+
Object.defineProperty(exports, "Node", { enumerable: true, get: function () { return dist_1.V1Node; } });
|
|
28
|
+
Object.defineProperty(exports, "PersistentVolume", { enumerable: true, get: function () { return dist_1.V1PersistentVolume; } });
|
|
29
|
+
Object.defineProperty(exports, "PersistentVolumeClaim", { enumerable: true, get: function () { return dist_1.V1PersistentVolumeClaim; } });
|
|
30
|
+
Object.defineProperty(exports, "Pod", { enumerable: true, get: function () { return dist_1.V1Pod; } });
|
|
31
|
+
Object.defineProperty(exports, "PodDisruptionBudget", { enumerable: true, get: function () { return dist_1.V1PodDisruptionBudget; } });
|
|
32
|
+
Object.defineProperty(exports, "PodTemplate", { enumerable: true, get: function () { return dist_1.V1PodTemplate; } });
|
|
33
|
+
Object.defineProperty(exports, "ReplicaSet", { enumerable: true, get: function () { return dist_1.V1ReplicaSet; } });
|
|
34
|
+
Object.defineProperty(exports, "ReplicationController", { enumerable: true, get: function () { return dist_1.V1ReplicationController; } });
|
|
35
|
+
Object.defineProperty(exports, "ResourceQuota", { enumerable: true, get: function () { return dist_1.V1ResourceQuota; } });
|
|
36
|
+
Object.defineProperty(exports, "RuntimeClass", { enumerable: true, get: function () { return dist_1.V1RuntimeClass; } });
|
|
37
|
+
Object.defineProperty(exports, "Secret", { enumerable: true, get: function () { return dist_1.V1Secret; } });
|
|
38
|
+
Object.defineProperty(exports, "SelfSubjectAccessReview", { enumerable: true, get: function () { return dist_1.V1SelfSubjectAccessReview; } });
|
|
39
|
+
Object.defineProperty(exports, "SelfSubjectRulesReview", { enumerable: true, get: function () { return dist_1.V1SelfSubjectRulesReview; } });
|
|
40
|
+
Object.defineProperty(exports, "Service", { enumerable: true, get: function () { return dist_1.V1Service; } });
|
|
41
|
+
Object.defineProperty(exports, "ServiceAccount", { enumerable: true, get: function () { return dist_1.V1ServiceAccount; } });
|
|
42
|
+
Object.defineProperty(exports, "StatefulSet", { enumerable: true, get: function () { return dist_1.V1StatefulSet; } });
|
|
43
|
+
Object.defineProperty(exports, "StorageClass", { enumerable: true, get: function () { return dist_1.V1StorageClass; } });
|
|
44
|
+
Object.defineProperty(exports, "SubjectAccessReview", { enumerable: true, get: function () { return dist_1.V1SubjectAccessReview; } });
|
|
45
|
+
Object.defineProperty(exports, "TokenReview", { enumerable: true, get: function () { return dist_1.V1TokenReview; } });
|
|
46
|
+
Object.defineProperty(exports, "ValidatingWebhookConfiguration", { enumerable: true, get: function () { return dist_1.V1ValidatingWebhookConfiguration; } });
|
|
47
|
+
Object.defineProperty(exports, "VolumeAttachment", { enumerable: true, get: function () { return dist_1.V1VolumeAttachment; } });
|
|
@@ -1,15 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
3
|
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
5
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
6
|
+
};
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.Webhook = void 0;
|
|
9
|
+
const client_node_1 = require("@kubernetes/client-node");
|
|
10
|
+
const zlib_1 = require("zlib");
|
|
11
|
+
const logger_1 = __importDefault(require("../logger"));
|
|
12
|
+
const tls_1 = require("./tls");
|
|
7
13
|
const peprIgnore = {
|
|
8
14
|
key: "pepr.dev",
|
|
9
15
|
operator: "NotIn",
|
|
10
16
|
values: ["ignore"],
|
|
11
17
|
};
|
|
12
|
-
|
|
18
|
+
class Webhook {
|
|
13
19
|
get tls() {
|
|
14
20
|
return this._tls;
|
|
15
21
|
}
|
|
@@ -19,7 +25,7 @@ export class Webhook {
|
|
|
19
25
|
this.name = `pepr-${config.uuid}`;
|
|
20
26
|
this.image = `ghcr.io/defenseunicorns/pepr/controller:${config.version}`;
|
|
21
27
|
// Generate the ephemeral tls things
|
|
22
|
-
this._tls = genTLS(this.host || `${this.name}.pepr-system.svc`);
|
|
28
|
+
this._tls = (0, tls_1.genTLS)(this.host || `${this.name}.pepr-system.svc`);
|
|
23
29
|
}
|
|
24
30
|
/** Generate the pepr-system namespace */
|
|
25
31
|
namespace() {
|
|
@@ -302,7 +308,7 @@ export class Webhook {
|
|
|
302
308
|
}
|
|
303
309
|
moduleSecret(data) {
|
|
304
310
|
// Compress the data
|
|
305
|
-
const compressed = gzipSync(data);
|
|
311
|
+
const compressed = (0, zlib_1.gzipSync)(data);
|
|
306
312
|
return {
|
|
307
313
|
apiVersion: "v1",
|
|
308
314
|
kind: "Secret",
|
|
@@ -340,7 +346,7 @@ export class Webhook {
|
|
|
340
346
|
},
|
|
341
347
|
],
|
|
342
348
|
};
|
|
343
|
-
return dumpYaml(zarfCfg, { noRefs: true });
|
|
349
|
+
return (0, client_node_1.dumpYaml)(zarfCfg, { noRefs: true });
|
|
344
350
|
}
|
|
345
351
|
allYaml(code) {
|
|
346
352
|
const resources = [
|
|
@@ -356,85 +362,85 @@ export class Webhook {
|
|
|
356
362
|
this.moduleSecret(code),
|
|
357
363
|
];
|
|
358
364
|
// Convert the resources to a single YAML string
|
|
359
|
-
return resources.map(r => dumpYaml(r, { noRefs: true })).join("---\n");
|
|
365
|
+
return resources.map(r => (0, client_node_1.dumpYaml)(r, { noRefs: true })).join("---\n");
|
|
360
366
|
}
|
|
361
367
|
async deploy(code) {
|
|
362
|
-
|
|
368
|
+
logger_1.default.info("Establishing connection to Kubernetes");
|
|
363
369
|
const namespace = "pepr-system";
|
|
364
370
|
// Deploy the resources using the k8s API
|
|
365
|
-
const kubeConfig = new KubeConfig();
|
|
371
|
+
const kubeConfig = new client_node_1.KubeConfig();
|
|
366
372
|
kubeConfig.loadFromDefault();
|
|
367
|
-
const coreV1Api = kubeConfig.makeApiClient(CoreV1Api);
|
|
368
|
-
const rbacApi = kubeConfig.makeApiClient(RbacAuthorizationV1Api);
|
|
369
|
-
const appsApi = kubeConfig.makeApiClient(AppsV1Api);
|
|
370
|
-
const admissionApi = kubeConfig.makeApiClient(AdmissionregistrationV1Api);
|
|
371
|
-
const networkApi = kubeConfig.makeApiClient(NetworkingV1Api);
|
|
373
|
+
const coreV1Api = kubeConfig.makeApiClient(client_node_1.CoreV1Api);
|
|
374
|
+
const rbacApi = kubeConfig.makeApiClient(client_node_1.RbacAuthorizationV1Api);
|
|
375
|
+
const appsApi = kubeConfig.makeApiClient(client_node_1.AppsV1Api);
|
|
376
|
+
const admissionApi = kubeConfig.makeApiClient(client_node_1.AdmissionregistrationV1Api);
|
|
377
|
+
const networkApi = kubeConfig.makeApiClient(client_node_1.NetworkingV1Api);
|
|
372
378
|
const ns = this.namespace();
|
|
373
379
|
try {
|
|
374
|
-
|
|
380
|
+
logger_1.default.info("Checking for namespace");
|
|
375
381
|
await coreV1Api.readNamespace(namespace);
|
|
376
382
|
}
|
|
377
383
|
catch (e) {
|
|
378
|
-
|
|
379
|
-
|
|
384
|
+
logger_1.default.debug(e.body);
|
|
385
|
+
logger_1.default.info("Creating namespace");
|
|
380
386
|
await coreV1Api.createNamespace(ns);
|
|
381
387
|
}
|
|
382
388
|
const netpol = this.networkPolicy();
|
|
383
389
|
try {
|
|
384
|
-
|
|
390
|
+
logger_1.default.info("Checking for network policy");
|
|
385
391
|
await networkApi.readNamespacedNetworkPolicy(netpol.metadata.name, namespace);
|
|
386
392
|
}
|
|
387
393
|
catch (e) {
|
|
388
|
-
|
|
389
|
-
|
|
394
|
+
logger_1.default.debug(e.body);
|
|
395
|
+
logger_1.default.info("Creating network policy");
|
|
390
396
|
await networkApi.createNamespacedNetworkPolicy(namespace, netpol);
|
|
391
397
|
}
|
|
392
398
|
const wh = this.mutatingWebhook();
|
|
393
399
|
try {
|
|
394
|
-
|
|
400
|
+
logger_1.default.info("Creating mutating webhook");
|
|
395
401
|
await admissionApi.createMutatingWebhookConfiguration(wh);
|
|
396
402
|
}
|
|
397
403
|
catch (e) {
|
|
398
|
-
|
|
399
|
-
|
|
404
|
+
logger_1.default.debug(e.body);
|
|
405
|
+
logger_1.default.info("Removing and re-creating mutating webhook");
|
|
400
406
|
await admissionApi.deleteMutatingWebhookConfiguration(wh.metadata.name);
|
|
401
407
|
await admissionApi.createMutatingWebhookConfiguration(wh);
|
|
402
408
|
}
|
|
403
409
|
const crb = this.clusterRoleBinding();
|
|
404
410
|
try {
|
|
405
|
-
|
|
411
|
+
logger_1.default.info("Creating cluster role binding");
|
|
406
412
|
await rbacApi.createClusterRoleBinding(crb);
|
|
407
413
|
}
|
|
408
414
|
catch (e) {
|
|
409
|
-
|
|
410
|
-
|
|
415
|
+
logger_1.default.debug(e.body);
|
|
416
|
+
logger_1.default.info("Removing and re-creating cluster role binding");
|
|
411
417
|
await rbacApi.deleteClusterRoleBinding(crb.metadata.name);
|
|
412
418
|
await rbacApi.createClusterRoleBinding(crb);
|
|
413
419
|
}
|
|
414
420
|
const cr = this.clusterRole();
|
|
415
421
|
try {
|
|
416
|
-
|
|
422
|
+
logger_1.default.info("Creating cluster role");
|
|
417
423
|
await rbacApi.createClusterRole(cr);
|
|
418
424
|
}
|
|
419
425
|
catch (e) {
|
|
420
|
-
|
|
421
|
-
|
|
426
|
+
logger_1.default.debug(e.body);
|
|
427
|
+
logger_1.default.info("Removing and re-creating the cluster role");
|
|
422
428
|
try {
|
|
423
429
|
await rbacApi.deleteClusterRole(cr.metadata.name);
|
|
424
430
|
await rbacApi.createClusterRole(cr);
|
|
425
431
|
}
|
|
426
432
|
catch (e) {
|
|
427
|
-
|
|
433
|
+
logger_1.default.debug(e.body);
|
|
428
434
|
}
|
|
429
435
|
}
|
|
430
436
|
const sa = this.serviceAccount();
|
|
431
437
|
try {
|
|
432
|
-
|
|
438
|
+
logger_1.default.info("Creating service account");
|
|
433
439
|
await coreV1Api.createNamespacedServiceAccount(namespace, sa);
|
|
434
440
|
}
|
|
435
441
|
catch (e) {
|
|
436
|
-
|
|
437
|
-
|
|
442
|
+
logger_1.default.debug(e.body);
|
|
443
|
+
logger_1.default.info("Removing and re-creating service account");
|
|
438
444
|
await coreV1Api.deleteNamespacedServiceAccount(sa.metadata.name, namespace);
|
|
439
445
|
await coreV1Api.createNamespacedServiceAccount(namespace, sa);
|
|
440
446
|
}
|
|
@@ -444,47 +450,48 @@ export class Webhook {
|
|
|
444
450
|
}
|
|
445
451
|
const mod = this.moduleSecret(code);
|
|
446
452
|
try {
|
|
447
|
-
|
|
453
|
+
logger_1.default.info("Creating module secret");
|
|
448
454
|
await coreV1Api.createNamespacedSecret(namespace, mod);
|
|
449
455
|
}
|
|
450
456
|
catch (e) {
|
|
451
|
-
|
|
452
|
-
|
|
457
|
+
logger_1.default.debug(e.body);
|
|
458
|
+
logger_1.default.info("Removing and re-creating module secret");
|
|
453
459
|
await coreV1Api.deleteNamespacedSecret(mod.metadata.name, namespace);
|
|
454
460
|
await coreV1Api.createNamespacedSecret(namespace, mod);
|
|
455
461
|
}
|
|
456
462
|
const svc = this.service();
|
|
457
463
|
try {
|
|
458
|
-
|
|
464
|
+
logger_1.default.info("Creating service");
|
|
459
465
|
await coreV1Api.createNamespacedService(namespace, svc);
|
|
460
466
|
}
|
|
461
467
|
catch (e) {
|
|
462
|
-
|
|
463
|
-
|
|
468
|
+
logger_1.default.debug(e.body);
|
|
469
|
+
logger_1.default.info("Removing and re-creating service");
|
|
464
470
|
await coreV1Api.deleteNamespacedService(svc.metadata.name, namespace);
|
|
465
471
|
await coreV1Api.createNamespacedService(namespace, svc);
|
|
466
472
|
}
|
|
467
473
|
const tls = this.tlsSecret();
|
|
468
474
|
try {
|
|
469
|
-
|
|
475
|
+
logger_1.default.info("Creating TLS secret");
|
|
470
476
|
await coreV1Api.createNamespacedSecret(namespace, tls);
|
|
471
477
|
}
|
|
472
478
|
catch (e) {
|
|
473
|
-
|
|
474
|
-
|
|
479
|
+
logger_1.default.debug(e.body);
|
|
480
|
+
logger_1.default.info("Removing and re-creating TLS secret");
|
|
475
481
|
await coreV1Api.deleteNamespacedSecret(tls.metadata.name, namespace);
|
|
476
482
|
await coreV1Api.createNamespacedSecret(namespace, tls);
|
|
477
483
|
}
|
|
478
484
|
const dep = this.deployment();
|
|
479
485
|
try {
|
|
480
|
-
|
|
486
|
+
logger_1.default.info("Creating deployment");
|
|
481
487
|
await appsApi.createNamespacedDeployment(namespace, dep);
|
|
482
488
|
}
|
|
483
489
|
catch (e) {
|
|
484
|
-
|
|
485
|
-
|
|
490
|
+
logger_1.default.debug(e.body);
|
|
491
|
+
logger_1.default.info("Removing and re-creating deployment");
|
|
486
492
|
await appsApi.deleteNamespacedDeployment(dep.metadata.name, namespace);
|
|
487
493
|
await appsApi.createNamespacedDeployment(namespace, dep);
|
|
488
494
|
}
|
|
489
495
|
}
|
|
490
496
|
}
|
|
497
|
+
exports.Webhook = Webhook;
|
package/dist/src/lib/logger.js
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
3
|
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.Logger = exports.LogLevel = void 0;
|
|
3
6
|
/**
|
|
4
7
|
* Enumeration representing different logging levels.
|
|
5
8
|
*/
|
|
6
|
-
|
|
9
|
+
var LogLevel;
|
|
7
10
|
(function (LogLevel) {
|
|
8
11
|
LogLevel[LogLevel["debug"] = 0] = "debug";
|
|
9
12
|
LogLevel[LogLevel["info"] = 1] = "info";
|
|
10
13
|
LogLevel[LogLevel["warn"] = 2] = "warn";
|
|
11
14
|
LogLevel[LogLevel["error"] = 3] = "error";
|
|
12
|
-
})(LogLevel || (LogLevel = {}));
|
|
15
|
+
})(LogLevel = exports.LogLevel || (exports.LogLevel = {}));
|
|
13
16
|
var ConsoleColors;
|
|
14
17
|
(function (ConsoleColors) {
|
|
15
18
|
ConsoleColors["Reset"] = "\u001B[0m";
|
|
@@ -39,7 +42,7 @@ var ConsoleColors;
|
|
|
39
42
|
/**
|
|
40
43
|
* Simple logger class that logs messages at different log levels.
|
|
41
44
|
*/
|
|
42
|
-
|
|
45
|
+
class Logger {
|
|
43
46
|
/**
|
|
44
47
|
* Create a new logger instance.
|
|
45
48
|
* @param logLevel - The minimum log level to log messages for.
|
|
@@ -113,4 +116,5 @@ export class Logger {
|
|
|
113
116
|
return color + text + ConsoleColors.Reset;
|
|
114
117
|
}
|
|
115
118
|
}
|
|
116
|
-
|
|
119
|
+
exports.Logger = Logger;
|
|
120
|
+
exports.default = new Logger(LogLevel.info);
|
package/dist/src/lib/module.js
CHANGED
|
@@ -1,21 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
3
|
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
5
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
6
|
+
};
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.PeprModule = void 0;
|
|
9
|
+
const ramda_1 = __importDefault(require("ramda"));
|
|
10
|
+
const controller_1 = require("./controller");
|
|
5
11
|
const alwaysIgnore = {
|
|
6
12
|
namespaces: ["kube-system", "pepr-system"],
|
|
7
13
|
labels: [{ "pepr.dev": "ignore" }],
|
|
8
14
|
};
|
|
9
|
-
|
|
15
|
+
class PeprModule {
|
|
10
16
|
/**
|
|
11
17
|
* Create a new Pepr runtime
|
|
12
18
|
*
|
|
13
19
|
* @param config The configuration for the Pepr runtime
|
|
14
20
|
*/
|
|
15
21
|
constructor({ description, pepr }, capabilities = [], deferStart = false) {
|
|
16
|
-
const config =
|
|
22
|
+
const config = ramda_1.default.mergeDeepWith(ramda_1.default.concat, pepr, alwaysIgnore);
|
|
17
23
|
config.description = description;
|
|
18
|
-
this._controller = new Controller(config, capabilities);
|
|
24
|
+
this._controller = new controller_1.Controller(config, capabilities);
|
|
19
25
|
if (!deferStart) {
|
|
20
26
|
this.start();
|
|
21
27
|
}
|
|
@@ -30,3 +36,4 @@ export class PeprModule {
|
|
|
30
36
|
this._controller.startServer(port);
|
|
31
37
|
}
|
|
32
38
|
}
|
|
39
|
+
exports.PeprModule = PeprModule;
|
|
@@ -1,27 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
3
|
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
5
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
6
|
+
};
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.processor = void 0;
|
|
9
|
+
const fast_json_patch_1 = require("fast-json-patch");
|
|
10
|
+
const filter_1 = require("./filter");
|
|
11
|
+
const logger_1 = __importDefault(require("./logger"));
|
|
12
|
+
const request_1 = require("./request");
|
|
13
|
+
function processor(config, capabilities, req) {
|
|
14
|
+
const wrapped = new request_1.RequestWrapper(req);
|
|
9
15
|
const response = {
|
|
10
16
|
uid: req.uid,
|
|
11
17
|
patchType: "JSONPatch",
|
|
12
18
|
warnings: [],
|
|
13
19
|
allowed: false,
|
|
14
20
|
};
|
|
15
|
-
|
|
21
|
+
logger_1.default.info(`Processing '${req.uid}' for '${req.kind.kind}' '${req.name}'`);
|
|
16
22
|
for (const { name, bindings } of capabilities) {
|
|
17
23
|
const prefix = `${req.uid} ${req.name}: ${name}`;
|
|
18
|
-
|
|
24
|
+
logger_1.default.info(`Processing capability ${name}`, prefix);
|
|
19
25
|
for (const action of bindings) {
|
|
20
26
|
// Continue to the next action without doing anything if this one should be skipped
|
|
21
|
-
if (shouldSkipRequest(action, req)) {
|
|
27
|
+
if ((0, filter_1.shouldSkipRequest)(action, req)) {
|
|
22
28
|
continue;
|
|
23
29
|
}
|
|
24
|
-
|
|
30
|
+
logger_1.default.info(`Processing matched action ${action.kind.kind}`, prefix);
|
|
25
31
|
// Add annotations to the request to indicate that the capability started processing
|
|
26
32
|
// this will allow tracking of failed mutations that were permitted to continue
|
|
27
33
|
const { metadata } = wrapped.Raw;
|
|
@@ -38,12 +44,12 @@ export function processor(config, capabilities, req) {
|
|
|
38
44
|
response.warnings.push(`Action failed: ${e}`);
|
|
39
45
|
// If errors are not allowed, note the failure in the Reponse
|
|
40
46
|
if (config.onError) {
|
|
41
|
-
|
|
47
|
+
logger_1.default.error(`Action failed: ${e}`, prefix);
|
|
42
48
|
response.result = "Pepr module configured to reject on error";
|
|
43
49
|
return response;
|
|
44
50
|
}
|
|
45
51
|
else {
|
|
46
|
-
|
|
52
|
+
logger_1.default.warn(`Action failed: ${e}`, prefix);
|
|
47
53
|
metadata.annotations[identifier] = "warning";
|
|
48
54
|
}
|
|
49
55
|
}
|
|
@@ -52,7 +58,7 @@ export function processor(config, capabilities, req) {
|
|
|
52
58
|
// If we've made it this far, the request is allowed
|
|
53
59
|
response.allowed = true;
|
|
54
60
|
// Compare the original request to the modified request to get the patches
|
|
55
|
-
const patches = compare(req.object, wrapped.Raw);
|
|
61
|
+
const patches = (0, fast_json_patch_1.compare)(req.object, wrapped.Raw);
|
|
56
62
|
// Only add the patch if there are patches to apply
|
|
57
63
|
if (patches.length > 0) {
|
|
58
64
|
response.patch = JSON.stringify(patches);
|
|
@@ -61,6 +67,7 @@ export function processor(config, capabilities, req) {
|
|
|
61
67
|
if (response.warnings.length < 1) {
|
|
62
68
|
delete response.warnings;
|
|
63
69
|
}
|
|
64
|
-
|
|
70
|
+
logger_1.default.debug(patches);
|
|
65
71
|
return response;
|
|
66
72
|
}
|
|
73
|
+
exports.processor = processor;
|
package/dist/src/lib/request.js
CHANGED
|
@@ -1,11 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
3
|
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
|
-
|
|
4
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
5
|
+
if (k2 === undefined) k2 = k;
|
|
6
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
7
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
8
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
9
|
+
}
|
|
10
|
+
Object.defineProperty(o, k2, desc);
|
|
11
|
+
}) : (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
o[k2] = m[k];
|
|
14
|
+
}));
|
|
15
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
16
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
17
|
+
}) : function(o, v) {
|
|
18
|
+
o["default"] = v;
|
|
19
|
+
});
|
|
20
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
21
|
+
if (mod && mod.__esModule) return mod;
|
|
22
|
+
var result = {};
|
|
23
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
24
|
+
__setModuleDefault(result, mod);
|
|
25
|
+
return result;
|
|
26
|
+
};
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.RequestWrapper = void 0;
|
|
29
|
+
const R = __importStar(require("ramda"));
|
|
4
30
|
/**
|
|
5
31
|
* The RequestWrapper class provides methods to modify Kubernetes objects in the context
|
|
6
32
|
* of a mutating webhook request.
|
|
7
33
|
*/
|
|
8
|
-
|
|
34
|
+
class RequestWrapper {
|
|
9
35
|
get PermitSideEffects() {
|
|
10
36
|
return !this._input.dryRun;
|
|
11
37
|
}
|
|
@@ -115,3 +141,4 @@ export class RequestWrapper {
|
|
|
115
141
|
return this.Raw?.metadata?.annotations?.[key] !== undefined;
|
|
116
142
|
}
|
|
117
143
|
}
|
|
144
|
+
exports.RequestWrapper = RequestWrapper;
|
package/dist/src/lib/types.js
CHANGED
|
@@ -1,31 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
3
|
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.Event = exports.HookPhase = exports.ErrorBehavior = void 0;
|
|
3
6
|
/**
|
|
4
7
|
* The behavior of this module when an error occurs.
|
|
5
8
|
*/
|
|
6
|
-
|
|
9
|
+
var ErrorBehavior;
|
|
7
10
|
(function (ErrorBehavior) {
|
|
8
11
|
ErrorBehavior["ignore"] = "ignore";
|
|
9
12
|
ErrorBehavior["audit"] = "audit";
|
|
10
13
|
ErrorBehavior["reject"] = "reject";
|
|
11
|
-
})(ErrorBehavior || (ErrorBehavior = {}));
|
|
14
|
+
})(ErrorBehavior = exports.ErrorBehavior || (exports.ErrorBehavior = {}));
|
|
12
15
|
/**
|
|
13
16
|
* The phase of the Kubernetes admission webhook that the capability is registered for.
|
|
14
17
|
*
|
|
15
18
|
* Currently only `mutate` is supported.
|
|
16
19
|
*/
|
|
17
|
-
|
|
20
|
+
var HookPhase;
|
|
18
21
|
(function (HookPhase) {
|
|
19
22
|
HookPhase["mutate"] = "mutate";
|
|
20
23
|
HookPhase["valdiate"] = "validate";
|
|
21
|
-
})(HookPhase || (HookPhase = {}));
|
|
24
|
+
})(HookPhase = exports.HookPhase || (exports.HookPhase = {}));
|
|
22
25
|
/**
|
|
23
26
|
* The type of Kubernetes mutating webhook event ethat the capability action is registered for.
|
|
24
27
|
*/
|
|
25
|
-
|
|
28
|
+
var Event;
|
|
26
29
|
(function (Event) {
|
|
27
30
|
Event["Create"] = "create";
|
|
28
31
|
Event["Update"] = "update";
|
|
29
32
|
Event["Delete"] = "delete";
|
|
30
33
|
Event["CreateOrUpdate"] = "createOrUpdate";
|
|
31
|
-
})(Event || (Event = {}));
|
|
34
|
+
})(Event = exports.Event || (exports.Event = {}));
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pepr",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.30",
|
|
4
4
|
"description": "Kubernetes application engine",
|
|
5
5
|
"author": "Defense Unicorns",
|
|
6
6
|
"homepage": "https://github.com/defenseunicorns/pepr",
|
|
7
7
|
"license": "Apache-2.0",
|
|
8
|
-
"bin": "dist/
|
|
8
|
+
"bin": "dist/cli.js",
|
|
9
9
|
"repository": "defenseunicorns/pepr",
|
|
10
10
|
"engines": {
|
|
11
11
|
"node": ">=18.0.0"
|