pepr 0.1.21 → 0.1.22
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/pepr-cli.js +145 -24
- package/package.json +6 -2
- package/src/lib/k8s/tls.ts +18 -6
- package/src/lib/k8s/webhook.ts +96 -13
package/dist/pepr-cli.js
CHANGED
|
@@ -21,7 +21,7 @@ var uuid = require('uuid');
|
|
|
21
21
|
var commander = require('commander');
|
|
22
22
|
var chokidar = require('chokidar');
|
|
23
23
|
|
|
24
|
-
var version = "0.1.
|
|
24
|
+
var version = "0.1.22";
|
|
25
25
|
|
|
26
26
|
// SPDX-License-Identifier: Apache-2.0
|
|
27
27
|
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
@@ -118,15 +118,21 @@ function genTLS(name) {
|
|
|
118
118
|
]);
|
|
119
119
|
// Generate a new server key pair and create a server certificate signed by the CA
|
|
120
120
|
const serverKeys = forge.pki.rsa.generateKeyPair(2048);
|
|
121
|
-
const serverCert = genCert(serverKeys,
|
|
121
|
+
const serverCert = genCert(serverKeys, name, caCert.subject.attributes);
|
|
122
122
|
// Sign both certificates with the CA private key
|
|
123
123
|
caCert.sign(caKeys.privateKey, forge.md.sha256.create());
|
|
124
124
|
serverCert.sign(caKeys.privateKey, forge.md.sha256.create());
|
|
125
|
-
// Convert the keys and certificates to PEM format
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
125
|
+
// Convert the keys and certificates to PEM format
|
|
126
|
+
const pem = {
|
|
127
|
+
ca: forge.pki.certificateToPem(caCert),
|
|
128
|
+
crt: forge.pki.certificateToPem(serverCert),
|
|
129
|
+
key: forge.pki.privateKeyToPem(serverKeys.privateKey),
|
|
130
|
+
};
|
|
131
|
+
// Base64-encode the PEM strings
|
|
132
|
+
const ca = Buffer.from(pem.ca).toString("base64");
|
|
133
|
+
const key = Buffer.from(pem.key).toString("base64");
|
|
134
|
+
const crt = Buffer.from(pem.crt).toString("base64");
|
|
135
|
+
return { ca, key, crt, pem };
|
|
130
136
|
}
|
|
131
137
|
function genCert(key, name, issuer) {
|
|
132
138
|
const crt = forge.pki.createCertificate();
|
|
@@ -159,12 +165,16 @@ const peprIgnore = {
|
|
|
159
165
|
values: ["ignore"],
|
|
160
166
|
};
|
|
161
167
|
class Webhook {
|
|
162
|
-
|
|
168
|
+
get tls() {
|
|
169
|
+
return this._tls;
|
|
170
|
+
}
|
|
171
|
+
constructor(config, host) {
|
|
163
172
|
this.config = config;
|
|
173
|
+
this.host = host;
|
|
164
174
|
this.name = `pepr-${config.uuid}`;
|
|
165
175
|
this.image = `ghcr.io/defenseunicorns/pepr/controller:${config.version}`;
|
|
166
176
|
// Generate the ephemeral tls things
|
|
167
|
-
this.
|
|
177
|
+
this._tls = genTLS(this.host || `${this.name}.pepr-system.svc`);
|
|
168
178
|
}
|
|
169
179
|
/** Generate the pepr-system namespace */
|
|
170
180
|
namespace() {
|
|
@@ -235,8 +245,8 @@ class Webhook {
|
|
|
235
245
|
},
|
|
236
246
|
type: "kubernetes.io/tls",
|
|
237
247
|
data: {
|
|
238
|
-
"tls.crt": this.
|
|
239
|
-
"tls.key": this.
|
|
248
|
+
"tls.crt": this._tls.crt,
|
|
249
|
+
"tls.key": this._tls.key,
|
|
240
250
|
},
|
|
241
251
|
};
|
|
242
252
|
}
|
|
@@ -251,6 +261,21 @@ class Webhook {
|
|
|
251
261
|
values: this.config.alwaysIgnore.namespaces,
|
|
252
262
|
});
|
|
253
263
|
}
|
|
264
|
+
const clientConfig = {
|
|
265
|
+
caBundle: this._tls.ca,
|
|
266
|
+
};
|
|
267
|
+
// If a host is specified, use that with a port of 3000
|
|
268
|
+
if (this.host) {
|
|
269
|
+
clientConfig.url = `https://${this.host}:3000/mutate`;
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
// Otherwise, use the service
|
|
273
|
+
clientConfig.service = {
|
|
274
|
+
name: this.name,
|
|
275
|
+
namespace: "pepr-system",
|
|
276
|
+
path: "/mutate",
|
|
277
|
+
};
|
|
278
|
+
}
|
|
254
279
|
return {
|
|
255
280
|
apiVersion: "admissionregistration.k8s.io/v1",
|
|
256
281
|
kind: "MutatingWebhookConfiguration",
|
|
@@ -259,14 +284,7 @@ class Webhook {
|
|
|
259
284
|
{
|
|
260
285
|
name: `${name}.pepr.dev`,
|
|
261
286
|
admissionReviewVersions: ["v1", "v1beta1"],
|
|
262
|
-
clientConfig
|
|
263
|
-
caBundle: this.tls.ca,
|
|
264
|
-
service: {
|
|
265
|
-
name: this.name,
|
|
266
|
-
namespace: "pepr-system",
|
|
267
|
-
path: "/mutate",
|
|
268
|
-
},
|
|
269
|
-
},
|
|
287
|
+
clientConfig,
|
|
270
288
|
failurePolicy: "Ignore",
|
|
271
289
|
matchPolicy: "Equivalent",
|
|
272
290
|
timeoutSeconds: 15,
|
|
@@ -351,6 +369,11 @@ class Webhook {
|
|
|
351
369
|
mountPath: "/etc/certs",
|
|
352
370
|
readOnly: true,
|
|
353
371
|
},
|
|
372
|
+
{
|
|
373
|
+
name: "module",
|
|
374
|
+
mountPath: "/app/module.js.gz",
|
|
375
|
+
readOnly: true,
|
|
376
|
+
},
|
|
354
377
|
],
|
|
355
378
|
},
|
|
356
379
|
],
|
|
@@ -361,12 +384,56 @@ class Webhook {
|
|
|
361
384
|
secretName: `${this.name}-tls`,
|
|
362
385
|
},
|
|
363
386
|
},
|
|
387
|
+
{
|
|
388
|
+
name: "module",
|
|
389
|
+
secret: {
|
|
390
|
+
secretName: `${this.name}-module`,
|
|
391
|
+
},
|
|
392
|
+
},
|
|
364
393
|
],
|
|
365
394
|
},
|
|
366
395
|
},
|
|
367
396
|
},
|
|
368
397
|
};
|
|
369
398
|
}
|
|
399
|
+
/** Only permit the */
|
|
400
|
+
networkPolicy() {
|
|
401
|
+
return {
|
|
402
|
+
apiVersion: "networking.k8s.io/v1",
|
|
403
|
+
kind: "NetworkPolicy",
|
|
404
|
+
metadata: {
|
|
405
|
+
name: this.name,
|
|
406
|
+
namespace: "pepr-system",
|
|
407
|
+
},
|
|
408
|
+
spec: {
|
|
409
|
+
podSelector: {
|
|
410
|
+
matchLabels: {
|
|
411
|
+
app: this.name,
|
|
412
|
+
},
|
|
413
|
+
},
|
|
414
|
+
policyTypes: ["Ingress"],
|
|
415
|
+
ingress: [
|
|
416
|
+
{
|
|
417
|
+
from: [
|
|
418
|
+
{
|
|
419
|
+
namespaceSelector: {
|
|
420
|
+
matchLabels: {
|
|
421
|
+
"kubernetes.io/metadata.name": "kube-system",
|
|
422
|
+
},
|
|
423
|
+
},
|
|
424
|
+
},
|
|
425
|
+
],
|
|
426
|
+
ports: [
|
|
427
|
+
{
|
|
428
|
+
protocol: "TCP",
|
|
429
|
+
port: 443,
|
|
430
|
+
},
|
|
431
|
+
],
|
|
432
|
+
},
|
|
433
|
+
],
|
|
434
|
+
},
|
|
435
|
+
};
|
|
436
|
+
}
|
|
370
437
|
service() {
|
|
371
438
|
return {
|
|
372
439
|
apiVersion: "v1",
|
|
@@ -433,6 +500,7 @@ class Webhook {
|
|
|
433
500
|
allYaml(code) {
|
|
434
501
|
const resources = [
|
|
435
502
|
this.namespace(),
|
|
503
|
+
this.networkPolicy(),
|
|
436
504
|
this.clusterRole(),
|
|
437
505
|
this.clusterRoleBinding(),
|
|
438
506
|
this.serviceAccount(),
|
|
@@ -455,6 +523,7 @@ class Webhook {
|
|
|
455
523
|
const rbacApi = kubeConfig.makeApiClient(clientNode.RbacAuthorizationV1Api);
|
|
456
524
|
const appsApi = kubeConfig.makeApiClient(clientNode.AppsV1Api);
|
|
457
525
|
const admissionApi = kubeConfig.makeApiClient(clientNode.AdmissionregistrationV1Api);
|
|
526
|
+
const networkApi = kubeConfig.makeApiClient(clientNode.NetworkingV1Api);
|
|
458
527
|
const ns = this.namespace();
|
|
459
528
|
try {
|
|
460
529
|
types.Log.info("Checking for namespace");
|
|
@@ -465,6 +534,16 @@ class Webhook {
|
|
|
465
534
|
types.Log.info("Creating namespace");
|
|
466
535
|
await coreV1Api.createNamespace(ns);
|
|
467
536
|
}
|
|
537
|
+
const netpol = this.networkPolicy();
|
|
538
|
+
try {
|
|
539
|
+
types.Log.info("Checking for network policy");
|
|
540
|
+
await networkApi.readNamespacedNetworkPolicy(netpol.metadata.name, namespace);
|
|
541
|
+
}
|
|
542
|
+
catch (e) {
|
|
543
|
+
types.Log.debug(e.body);
|
|
544
|
+
types.Log.info("Creating network policy");
|
|
545
|
+
await networkApi.createNamespacedNetworkPolicy(namespace, netpol);
|
|
546
|
+
}
|
|
468
547
|
const wh = this.mutatingWebhook();
|
|
469
548
|
try {
|
|
470
549
|
types.Log.info("Creating mutating webhook");
|
|
@@ -514,6 +593,10 @@ class Webhook {
|
|
|
514
593
|
await coreV1Api.deleteNamespacedServiceAccount(sa.metadata.name, namespace);
|
|
515
594
|
await coreV1Api.createNamespacedServiceAccount(namespace, sa);
|
|
516
595
|
}
|
|
596
|
+
// If a host is specified, we don't need to deploy the rest of the resources
|
|
597
|
+
if (this.host) {
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
517
600
|
const mod = this.moduleSecret(code);
|
|
518
601
|
try {
|
|
519
602
|
types.Log.info("Creating module secret");
|
|
@@ -707,6 +790,47 @@ function deploy (program) {
|
|
|
707
790
|
});
|
|
708
791
|
}
|
|
709
792
|
|
|
793
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
794
|
+
function dev (program) {
|
|
795
|
+
program
|
|
796
|
+
.command("dev")
|
|
797
|
+
.description("Setup a local webhook development environment")
|
|
798
|
+
.option("-d, --dir [directory]", "Pepr module directory", ".")
|
|
799
|
+
.option("-h, --host [host]", "Host to listen on", "host.docker.internal")
|
|
800
|
+
.action(async (opts) => {
|
|
801
|
+
// Prompt the user to confirm
|
|
802
|
+
const confirm = await prompt.prompt({
|
|
803
|
+
type: "confirm",
|
|
804
|
+
name: "confirm",
|
|
805
|
+
message: "This will remove and redeploy the module. Continue?",
|
|
806
|
+
});
|
|
807
|
+
// Exit if the user doesn't confirm
|
|
808
|
+
if (!confirm.confirm) {
|
|
809
|
+
process.exit(0);
|
|
810
|
+
}
|
|
811
|
+
// Build the module
|
|
812
|
+
const { cfg, path } = await buildModule(opts.dir);
|
|
813
|
+
// Read the compiled module code
|
|
814
|
+
const code = await fs.promises.readFile(path, { encoding: "utf-8" });
|
|
815
|
+
// Generate a secret for the module
|
|
816
|
+
const webhook = new Webhook({
|
|
817
|
+
...cfg.pepr,
|
|
818
|
+
description: cfg.description,
|
|
819
|
+
}, opts.host);
|
|
820
|
+
// Write the TLS cert and key to disk
|
|
821
|
+
await fs.promises.writeFile("insecure-tls.crt", webhook.tls.pem.crt);
|
|
822
|
+
await fs.promises.writeFile("insecure-tls.key", webhook.tls.pem.key);
|
|
823
|
+
try {
|
|
824
|
+
await webhook.deploy(code);
|
|
825
|
+
types.Log.info(`Module deployed successfully`);
|
|
826
|
+
}
|
|
827
|
+
catch (e) {
|
|
828
|
+
types.Log.error(`Error deploying module: ${e}`);
|
|
829
|
+
process.exit(1);
|
|
830
|
+
}
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
|
|
710
834
|
// SPDX-License-Identifier: Apache-2.0
|
|
711
835
|
/**
|
|
712
836
|
* Sanitize a user input name to be used as a pepr module directory name
|
|
@@ -1027,11 +1151,7 @@ function walkthrough() {
|
|
|
1027
1151
|
},
|
|
1028
1152
|
],
|
|
1029
1153
|
};
|
|
1030
|
-
return prompt([
|
|
1031
|
-
askName,
|
|
1032
|
-
askDescription,
|
|
1033
|
-
askErrorBehavior,
|
|
1034
|
-
]);
|
|
1154
|
+
return prompt([askName, askDescription, askErrorBehavior]);
|
|
1035
1155
|
}
|
|
1036
1156
|
async function confirm(dirName, packageJSON, peprTSPath) {
|
|
1037
1157
|
console.log(`
|
|
@@ -1165,4 +1285,5 @@ build(program);
|
|
|
1165
1285
|
capability(program);
|
|
1166
1286
|
test(program);
|
|
1167
1287
|
deploy(program);
|
|
1288
|
+
dev(program);
|
|
1168
1289
|
program.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pepr",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.22",
|
|
4
4
|
"description": "Kubernetes application engine",
|
|
5
5
|
"author": "Defense Unicorns",
|
|
6
6
|
"homepage": "https://github.com/defenseunicorns/pepr",
|
|
@@ -29,7 +29,10 @@
|
|
|
29
29
|
"prettier": "npx prettier src --check",
|
|
30
30
|
"prettier:fix": "npm run prettier -- --write",
|
|
31
31
|
"prepublishOnly": "rm -fr dist/* && npm run lint:fix && npm run prettier:fix && npm run test && npm run build",
|
|
32
|
-
"e2e-dev": "
|
|
32
|
+
"e2e-dev-setup": "k3d cluster delete pepr-dev && k3d cluster create pepr-dev",
|
|
33
|
+
"e2e-dev": "npm run build && docker buildx build --tag pepr:dev . && k3d image import pepr:dev -c pepr-dev && node dist/pepr-cli.js deploy -f -i pepr:dev",
|
|
34
|
+
"prestart": "ts-node src/cli dev",
|
|
35
|
+
"start": "chokidar 'src/**/*.ts' -c 'SSL_KEY_PATH=insecure-tls.key SSL_CERT_PATH=insecure-tls.crt ts-node src/controller/index.ts' --initial --silent"
|
|
33
36
|
},
|
|
34
37
|
"dependencies": {
|
|
35
38
|
"@kubernetes/client-node": "^0.18.1",
|
|
@@ -59,6 +62,7 @@
|
|
|
59
62
|
"@typescript-eslint/eslint-plugin": "^5.57.0",
|
|
60
63
|
"@typescript-eslint/parser": "^5.57.0",
|
|
61
64
|
"ava": "^5.2.0",
|
|
65
|
+
"chokidar-cli": "^3.0.0",
|
|
62
66
|
"eslint": "^8.37.0",
|
|
63
67
|
"ts-node": "^10.9.1",
|
|
64
68
|
"tsconfig-paths": "^4.1.2"
|
package/src/lib/k8s/tls.ts
CHANGED
|
@@ -6,6 +6,11 @@ export interface TLSOut {
|
|
|
6
6
|
ca: string;
|
|
7
7
|
crt: string;
|
|
8
8
|
key: string;
|
|
9
|
+
pem: {
|
|
10
|
+
ca: string;
|
|
11
|
+
crt: string;
|
|
12
|
+
key: string;
|
|
13
|
+
};
|
|
9
14
|
}
|
|
10
15
|
|
|
11
16
|
/**
|
|
@@ -36,18 +41,25 @@ export function genTLS(name: string): TLSOut {
|
|
|
36
41
|
|
|
37
42
|
// Generate a new server key pair and create a server certificate signed by the CA
|
|
38
43
|
const serverKeys = forge.pki.rsa.generateKeyPair(2048);
|
|
39
|
-
const serverCert = genCert(serverKeys,
|
|
44
|
+
const serverCert = genCert(serverKeys, name, caCert.subject.attributes);
|
|
40
45
|
|
|
41
46
|
// Sign both certificates with the CA private key
|
|
42
47
|
caCert.sign(caKeys.privateKey, forge.md.sha256.create());
|
|
43
48
|
serverCert.sign(caKeys.privateKey, forge.md.sha256.create());
|
|
44
49
|
|
|
45
|
-
// Convert the keys and certificates to PEM format
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
// Convert the keys and certificates to PEM format
|
|
51
|
+
const pem = {
|
|
52
|
+
ca: forge.pki.certificateToPem(caCert),
|
|
53
|
+
crt: forge.pki.certificateToPem(serverCert),
|
|
54
|
+
key: forge.pki.privateKeyToPem(serverKeys.privateKey),
|
|
55
|
+
};
|
|
49
56
|
|
|
50
|
-
|
|
57
|
+
// Base64-encode the PEM strings
|
|
58
|
+
const ca = Buffer.from(pem.ca).toString("base64");
|
|
59
|
+
const key = Buffer.from(pem.key).toString("base64");
|
|
60
|
+
const crt = Buffer.from(pem.crt).toString("base64");
|
|
61
|
+
|
|
62
|
+
return { ca, key, crt, pem };
|
|
51
63
|
}
|
|
52
64
|
|
|
53
65
|
function genCert(key: forge.pki.rsa.KeyPair, name: string, issuer: forge.pki.CertificateField[]) {
|
package/src/lib/k8s/webhook.ts
CHANGED
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
AdmissionregistrationV1Api,
|
|
6
|
+
AdmissionregistrationV1WebhookClientConfig,
|
|
6
7
|
AppsV1Api,
|
|
7
8
|
CoreV1Api,
|
|
8
9
|
KubeConfig,
|
|
10
|
+
NetworkingV1Api,
|
|
9
11
|
RbacAuthorizationV1Api,
|
|
10
12
|
V1ClusterRole,
|
|
11
13
|
V1ClusterRoleBinding,
|
|
@@ -13,6 +15,7 @@ import {
|
|
|
13
15
|
V1LabelSelectorRequirement,
|
|
14
16
|
V1MutatingWebhookConfiguration,
|
|
15
17
|
V1Namespace,
|
|
18
|
+
V1NetworkPolicy,
|
|
16
19
|
V1Secret,
|
|
17
20
|
V1Service,
|
|
18
21
|
V1ServiceAccount,
|
|
@@ -31,17 +34,21 @@ const peprIgnore: V1LabelSelectorRequirement = {
|
|
|
31
34
|
|
|
32
35
|
export class Webhook {
|
|
33
36
|
private name: string;
|
|
34
|
-
private
|
|
37
|
+
private _tls: TLSOut;
|
|
35
38
|
|
|
36
39
|
public image: string;
|
|
37
40
|
|
|
38
|
-
|
|
41
|
+
public get tls(): TLSOut {
|
|
42
|
+
return this._tls;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
constructor(private readonly config: ModuleConfig, private readonly host?: string) {
|
|
39
46
|
this.name = `pepr-${config.uuid}`;
|
|
40
47
|
|
|
41
48
|
this.image = `ghcr.io/defenseunicorns/pepr/controller:${config.version}`;
|
|
42
49
|
|
|
43
50
|
// Generate the ephemeral tls things
|
|
44
|
-
this.
|
|
51
|
+
this._tls = genTLS(this.host || `${this.name}.pepr-system.svc`);
|
|
45
52
|
}
|
|
46
53
|
|
|
47
54
|
/** Generate the pepr-system namespace */
|
|
@@ -117,8 +124,8 @@ export class Webhook {
|
|
|
117
124
|
},
|
|
118
125
|
type: "kubernetes.io/tls",
|
|
119
126
|
data: {
|
|
120
|
-
"tls.crt": this.
|
|
121
|
-
"tls.key": this.
|
|
127
|
+
"tls.crt": this._tls.crt,
|
|
128
|
+
"tls.key": this._tls.key,
|
|
122
129
|
},
|
|
123
130
|
};
|
|
124
131
|
}
|
|
@@ -136,6 +143,22 @@ export class Webhook {
|
|
|
136
143
|
});
|
|
137
144
|
}
|
|
138
145
|
|
|
146
|
+
const clientConfig: AdmissionregistrationV1WebhookClientConfig = {
|
|
147
|
+
caBundle: this._tls.ca,
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
// If a host is specified, use that with a port of 3000
|
|
151
|
+
if (this.host) {
|
|
152
|
+
clientConfig.url = `https://${this.host}:3000/mutate`;
|
|
153
|
+
} else {
|
|
154
|
+
// Otherwise, use the service
|
|
155
|
+
clientConfig.service = {
|
|
156
|
+
name: this.name,
|
|
157
|
+
namespace: "pepr-system",
|
|
158
|
+
path: "/mutate",
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
139
162
|
return {
|
|
140
163
|
apiVersion: "admissionregistration.k8s.io/v1",
|
|
141
164
|
kind: "MutatingWebhookConfiguration",
|
|
@@ -144,14 +167,7 @@ export class Webhook {
|
|
|
144
167
|
{
|
|
145
168
|
name: `${name}.pepr.dev`,
|
|
146
169
|
admissionReviewVersions: ["v1", "v1beta1"],
|
|
147
|
-
clientConfig
|
|
148
|
-
caBundle: this.tls.ca,
|
|
149
|
-
service: {
|
|
150
|
-
name: this.name,
|
|
151
|
-
namespace: "pepr-system",
|
|
152
|
-
path: "/mutate",
|
|
153
|
-
},
|
|
154
|
-
},
|
|
170
|
+
clientConfig,
|
|
155
171
|
failurePolicy: "Ignore",
|
|
156
172
|
matchPolicy: "Equivalent",
|
|
157
173
|
timeoutSeconds: 15,
|
|
@@ -237,6 +253,11 @@ export class Webhook {
|
|
|
237
253
|
mountPath: "/etc/certs",
|
|
238
254
|
readOnly: true,
|
|
239
255
|
},
|
|
256
|
+
{
|
|
257
|
+
name: "module",
|
|
258
|
+
mountPath: "/app/module.js.gz",
|
|
259
|
+
readOnly: true,
|
|
260
|
+
},
|
|
240
261
|
],
|
|
241
262
|
},
|
|
242
263
|
],
|
|
@@ -247,6 +268,12 @@ export class Webhook {
|
|
|
247
268
|
secretName: `${this.name}-tls`,
|
|
248
269
|
},
|
|
249
270
|
},
|
|
271
|
+
{
|
|
272
|
+
name: "module",
|
|
273
|
+
secret: {
|
|
274
|
+
secretName: `${this.name}-module`,
|
|
275
|
+
},
|
|
276
|
+
},
|
|
250
277
|
],
|
|
251
278
|
},
|
|
252
279
|
},
|
|
@@ -254,6 +281,45 @@ export class Webhook {
|
|
|
254
281
|
};
|
|
255
282
|
}
|
|
256
283
|
|
|
284
|
+
/** Only permit the */
|
|
285
|
+
networkPolicy(): V1NetworkPolicy {
|
|
286
|
+
return {
|
|
287
|
+
apiVersion: "networking.k8s.io/v1",
|
|
288
|
+
kind: "NetworkPolicy",
|
|
289
|
+
metadata: {
|
|
290
|
+
name: this.name,
|
|
291
|
+
namespace: "pepr-system",
|
|
292
|
+
},
|
|
293
|
+
spec: {
|
|
294
|
+
podSelector: {
|
|
295
|
+
matchLabels: {
|
|
296
|
+
app: this.name,
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
policyTypes: ["Ingress"],
|
|
300
|
+
ingress: [
|
|
301
|
+
{
|
|
302
|
+
from: [
|
|
303
|
+
{
|
|
304
|
+
namespaceSelector: {
|
|
305
|
+
matchLabels: {
|
|
306
|
+
"kubernetes.io/metadata.name": "kube-system",
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
],
|
|
311
|
+
ports: [
|
|
312
|
+
{
|
|
313
|
+
protocol: "TCP",
|
|
314
|
+
port: 443,
|
|
315
|
+
},
|
|
316
|
+
],
|
|
317
|
+
},
|
|
318
|
+
],
|
|
319
|
+
},
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
|
|
257
323
|
service(): V1Service {
|
|
258
324
|
return {
|
|
259
325
|
apiVersion: "v1",
|
|
@@ -324,6 +390,7 @@ export class Webhook {
|
|
|
324
390
|
allYaml(code: string) {
|
|
325
391
|
const resources = [
|
|
326
392
|
this.namespace(),
|
|
393
|
+
this.networkPolicy(),
|
|
327
394
|
this.clusterRole(),
|
|
328
395
|
this.clusterRoleBinding(),
|
|
329
396
|
this.serviceAccount(),
|
|
@@ -351,6 +418,7 @@ export class Webhook {
|
|
|
351
418
|
const rbacApi = kubeConfig.makeApiClient(RbacAuthorizationV1Api);
|
|
352
419
|
const appsApi = kubeConfig.makeApiClient(AppsV1Api);
|
|
353
420
|
const admissionApi = kubeConfig.makeApiClient(AdmissionregistrationV1Api);
|
|
421
|
+
const networkApi = kubeConfig.makeApiClient(NetworkingV1Api);
|
|
354
422
|
|
|
355
423
|
const ns = this.namespace();
|
|
356
424
|
try {
|
|
@@ -362,6 +430,16 @@ export class Webhook {
|
|
|
362
430
|
await coreV1Api.createNamespace(ns);
|
|
363
431
|
}
|
|
364
432
|
|
|
433
|
+
const netpol = this.networkPolicy();
|
|
434
|
+
try {
|
|
435
|
+
logger.info("Checking for network policy");
|
|
436
|
+
await networkApi.readNamespacedNetworkPolicy(netpol.metadata.name, namespace);
|
|
437
|
+
} catch (e) {
|
|
438
|
+
logger.debug(e.body);
|
|
439
|
+
logger.info("Creating network policy");
|
|
440
|
+
await networkApi.createNamespacedNetworkPolicy(namespace, netpol);
|
|
441
|
+
}
|
|
442
|
+
|
|
365
443
|
const wh = this.mutatingWebhook();
|
|
366
444
|
try {
|
|
367
445
|
logger.info("Creating mutating webhook");
|
|
@@ -410,6 +488,11 @@ export class Webhook {
|
|
|
410
488
|
await coreV1Api.createNamespacedServiceAccount(namespace, sa);
|
|
411
489
|
}
|
|
412
490
|
|
|
491
|
+
// If a host is specified, we don't need to deploy the rest of the resources
|
|
492
|
+
if (this.host) {
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
|
|
413
496
|
const mod = this.moduleSecret(code);
|
|
414
497
|
try {
|
|
415
498
|
logger.info("Creating module secret");
|