pepr 0.42.1 → 0.42.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/dist/cli/deploy.d.ts +15 -0
  2. package/dist/cli/deploy.d.ts.map +1 -1
  3. package/dist/cli/dev.d.ts.map +1 -1
  4. package/dist/cli/format.d.ts.map +1 -1
  5. package/dist/cli/format.helpers.d.ts +3 -0
  6. package/dist/cli/format.helpers.d.ts.map +1 -0
  7. package/dist/cli/init/enums.d.ts +10 -0
  8. package/dist/cli/init/enums.d.ts.map +1 -0
  9. package/dist/cli/init/index.d.ts.map +1 -1
  10. package/dist/cli/init/templates.d.ts +15 -11
  11. package/dist/cli/init/templates.d.ts.map +1 -1
  12. package/dist/cli/init/utils.d.ts.map +1 -1
  13. package/dist/cli/init/walkthrough.d.ts +3 -2
  14. package/dist/cli/init/walkthrough.d.ts.map +1 -1
  15. package/dist/cli/kfc.d.ts.map +1 -1
  16. package/dist/cli/root.d.ts.map +1 -1
  17. package/dist/cli/update.d.ts.map +1 -1
  18. package/dist/cli/uuid.d.ts.map +1 -1
  19. package/dist/cli.js +145 -306
  20. package/dist/controller.js +1 -195
  21. package/dist/fixtures/loader.d.ts.map +1 -1
  22. package/dist/lib/assets/deploy.d.ts.map +1 -1
  23. package/dist/lib/assets/index.d.ts +1 -1
  24. package/dist/lib/assets/index.d.ts.map +1 -1
  25. package/dist/lib/assets/pods.d.ts +1 -3
  26. package/dist/lib/assets/pods.d.ts.map +1 -1
  27. package/dist/lib/assets/rbac.d.ts.map +1 -1
  28. package/dist/lib/assets/webhooks.d.ts.map +1 -1
  29. package/dist/lib/controller/index.d.ts +2 -2
  30. package/dist/lib/controller/index.d.ts.map +1 -1
  31. package/dist/lib/controller/store.d.ts +1 -1
  32. package/dist/lib/controller/store.d.ts.map +1 -1
  33. package/dist/lib/controller/storeCache.d.ts +1 -1
  34. package/dist/lib/controller/storeCache.d.ts.map +1 -1
  35. package/dist/lib/{capability.d.ts → core/capability.d.ts} +1 -1
  36. package/dist/lib/core/capability.d.ts.map +1 -0
  37. package/dist/lib/{module.d.ts → core/module.d.ts} +2 -2
  38. package/dist/lib/core/module.d.ts.map +1 -0
  39. package/dist/lib/core/queue.d.ts.map +1 -0
  40. package/dist/lib/{schedule.d.ts → core/schedule.d.ts} +0 -1
  41. package/dist/lib/core/schedule.d.ts.map +1 -0
  42. package/dist/lib/core/storage.d.ts.map +1 -0
  43. package/dist/lib/deploymentChecks.d.ts.map +1 -1
  44. package/dist/lib/errors.d.ts +0 -5
  45. package/dist/lib/errors.d.ts.map +1 -1
  46. package/dist/lib/filesystemService.d.ts.map +1 -1
  47. package/dist/lib/filter/adjudicators/adjudicators.d.ts +5 -4
  48. package/dist/lib/filter/adjudicators/adjudicators.d.ts.map +1 -1
  49. package/dist/lib/filter/filter.d.ts +33 -1
  50. package/dist/lib/filter/filter.d.ts.map +1 -1
  51. package/dist/lib/finalizer.d.ts.map +1 -1
  52. package/dist/lib/helpers.d.ts +4 -9
  53. package/dist/lib/helpers.d.ts.map +1 -1
  54. package/dist/lib/included-files.d.ts.map +1 -1
  55. package/dist/lib/mutate-request.d.ts.map +1 -1
  56. package/dist/lib/processors/mutate-processor.d.ts +28 -0
  57. package/dist/lib/processors/mutate-processor.d.ts.map +1 -0
  58. package/dist/lib/{validate-processor.d.ts → processors/validate-processor.d.ts} +5 -5
  59. package/dist/lib/processors/validate-processor.d.ts.map +1 -0
  60. package/dist/lib/{watch-processor.d.ts → processors/watch-processor.d.ts} +2 -2
  61. package/dist/lib/processors/watch-processor.d.ts.map +1 -0
  62. package/dist/lib/telemetry/logger.d.ts.map +1 -1
  63. package/dist/lib/telemetry/metrics.d.ts.map +1 -1
  64. package/dist/lib/validate-request.d.ts +2 -2
  65. package/dist/lib/validate-request.d.ts.map +1 -1
  66. package/dist/lib.d.ts +2 -2
  67. package/dist/lib.d.ts.map +1 -1
  68. package/dist/lib.js +383 -243
  69. package/dist/lib.js.map +4 -4
  70. package/dist/sdk/heredoc.d.ts.map +1 -1
  71. package/package.json +9 -9
  72. package/src/cli/deploy.ts +113 -74
  73. package/src/cli/dev.ts +2 -2
  74. package/src/cli/format.helpers.ts +27 -0
  75. package/src/cli/format.ts +4 -18
  76. package/src/cli/init/enums.ts +9 -0
  77. package/src/cli/init/index.ts +4 -3
  78. package/src/cli/init/templates.ts +30 -2
  79. package/src/cli/init/utils.ts +3 -3
  80. package/src/cli/init/walkthrough.ts +7 -8
  81. package/src/cli/kfc.ts +1 -1
  82. package/src/cli/root.ts +1 -1
  83. package/src/cli/update.ts +1 -1
  84. package/src/cli/uuid.ts +1 -1
  85. package/src/fixtures/loader.ts +2 -2
  86. package/src/lib/assets/deploy.ts +5 -5
  87. package/src/lib/assets/index.ts +1 -1
  88. package/src/lib/assets/pods.ts +1 -1
  89. package/src/lib/assets/webhooks.ts +30 -45
  90. package/src/lib/controller/index.ts +4 -4
  91. package/src/lib/controller/store.ts +2 -2
  92. package/src/lib/controller/storeCache.ts +6 -2
  93. package/src/lib/{capability.ts → core/capability.ts} +4 -4
  94. package/src/lib/{module.ts → core/module.ts} +10 -10
  95. package/src/lib/{queue.ts → core/queue.ts} +1 -1
  96. package/src/lib/deploymentChecks.ts +2 -2
  97. package/src/lib/errors.ts +3 -8
  98. package/src/lib/filesystemService.ts +1 -1
  99. package/src/lib/filter/adjudicators/adjudicators.ts +40 -9
  100. package/src/lib/filter/filter.ts +204 -111
  101. package/src/lib/finalizer.ts +2 -2
  102. package/src/lib/helpers.ts +20 -133
  103. package/src/lib/included-files.ts +1 -1
  104. package/src/lib/processors/mutate-processor.ts +225 -0
  105. package/src/lib/{validate-processor.ts → processors/validate-processor.ts} +8 -8
  106. package/src/lib/{watch-processor.ts → processors/watch-processor.ts} +8 -8
  107. package/src/lib/telemetry/logger.ts +3 -1
  108. package/src/lib/tls.ts +5 -1
  109. package/src/lib/validate-request.ts +4 -4
  110. package/src/lib.ts +2 -2
  111. package/src/runtime/controller.ts +2 -2
  112. package/src/sdk/heredoc.ts +1 -1
  113. package/dist/lib/capability.d.ts.map +0 -1
  114. package/dist/lib/module.d.ts.map +0 -1
  115. package/dist/lib/mutate-processor.d.ts +0 -6
  116. package/dist/lib/mutate-processor.d.ts.map +0 -1
  117. package/dist/lib/queue.d.ts.map +0 -1
  118. package/dist/lib/schedule.d.ts.map +0 -1
  119. package/dist/lib/storage.d.ts.map +0 -1
  120. package/dist/lib/validate-processor.d.ts.map +0 -1
  121. package/dist/lib/watch-processor.d.ts.map +0 -1
  122. package/src/lib/mutate-processor.ts +0 -165
  123. /package/dist/lib/{queue.d.ts → core/queue.d.ts} +0 -0
  124. /package/dist/lib/{storage.d.ts → core/storage.d.ts} +0 -0
  125. /package/src/lib/{schedule.ts → core/schedule.ts} +0 -0
  126. /package/src/lib/{storage.ts → core/storage.ts} +0 -0
@@ -0,0 +1,225 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
+
4
+ import jsonPatch from "fast-json-patch";
5
+ import { kind, KubernetesObject } from "kubernetes-fluent-client";
6
+ import { clone } from "ramda";
7
+
8
+ import { Capability } from "../core/capability";
9
+ import { shouldSkipRequest } from "../filter/filter";
10
+ import { MutateResponse } from "../k8s";
11
+ import { AdmissionRequest, Binding } from "../types";
12
+ import Log from "../telemetry/logger";
13
+ import { ModuleConfig } from "../core/module";
14
+ import { PeprMutateRequest } from "../mutate-request";
15
+ import { base64Encode, convertFromBase64Map, convertToBase64Map } from "../utils";
16
+ import { OnError } from "../../cli/init/enums";
17
+
18
+ export interface Bindable {
19
+ req: AdmissionRequest;
20
+ config: ModuleConfig;
21
+ name: string;
22
+ namespaces: string[];
23
+ binding: Binding;
24
+ actMeta: Record<string, string>;
25
+ }
26
+
27
+ export interface Result {
28
+ wrapped: PeprMutateRequest<KubernetesObject>;
29
+ response: MutateResponse;
30
+ }
31
+
32
+ // Add annotations to the request to indicate that the capability started processing
33
+ // this will allow tracking of failed mutations that were permitted to continue
34
+ export function updateStatus(
35
+ config: ModuleConfig,
36
+ name: string,
37
+ wrapped: PeprMutateRequest<KubernetesObject>,
38
+ status: string,
39
+ ): PeprMutateRequest<KubernetesObject> {
40
+ // Only update the status if the request is a CREATE or UPDATE (we don't use CONNECT)
41
+ if (wrapped.Request.operation === "DELETE") {
42
+ return wrapped;
43
+ }
44
+ wrapped.SetAnnotation(`${config.uuid}.pepr.dev/${name}`, status);
45
+
46
+ return wrapped;
47
+ }
48
+
49
+ export function logMutateErrorMessage(e: Error): string {
50
+ try {
51
+ if (e.message && e.message !== "[object Object]") {
52
+ return e.message;
53
+ } else {
54
+ throw new Error("An error occurred in the mutate action.");
55
+ }
56
+ } catch (e) {
57
+ return "An error occurred with the mutate action.";
58
+ }
59
+ }
60
+
61
+ export function decodeData(wrapped: PeprMutateRequest<KubernetesObject>): {
62
+ skipped: string[];
63
+ wrapped: PeprMutateRequest<KubernetesObject>;
64
+ } {
65
+ let skipped: string[] = [];
66
+
67
+ const isSecret = wrapped.Request.kind.version === "v1" && wrapped.Request.kind.kind === "Secret";
68
+ if (isSecret) {
69
+ // convertFromBase64Map modifies it's arg rather than returing a mod'ed copy (ye olde side-effect special, blerg)
70
+ skipped = convertFromBase64Map(wrapped.Raw as unknown as kind.Secret);
71
+ }
72
+
73
+ return { skipped, wrapped };
74
+ }
75
+
76
+ export function reencodeData(wrapped: PeprMutateRequest<KubernetesObject>, skipped: string[]): KubernetesObject {
77
+ const transformed = clone(wrapped.Raw);
78
+
79
+ const isSecret = wrapped.Request.kind.version === "v1" && wrapped.Request.kind.kind === "Secret";
80
+ if (isSecret) {
81
+ // convertToBase64Map modifies it's arg rather than returing a mod'ed copy (ye olde side-effect special, blerg)
82
+ convertToBase64Map(transformed as unknown as kind.Secret, skipped);
83
+ }
84
+
85
+ return transformed;
86
+ }
87
+
88
+ export async function processRequest(
89
+ bindable: Bindable,
90
+ wrapped: PeprMutateRequest<KubernetesObject>,
91
+ response: MutateResponse,
92
+ ): Promise<Result> {
93
+ const { binding, actMeta, name, config } = bindable;
94
+
95
+ const label = binding.mutateCallback!.name;
96
+ Log.info(actMeta, `Processing mutation action (${label})`);
97
+
98
+ wrapped = updateStatus(config, name, wrapped, "started");
99
+
100
+ try {
101
+ // Run the action
102
+ await binding.mutateCallback!(wrapped);
103
+
104
+ // Log on success
105
+ Log.info(actMeta, `Mutation action succeeded (${label})`);
106
+
107
+ // Add annotations to the request to indicate that the capability succeeded
108
+ wrapped = updateStatus(config, name, wrapped, "succeeded");
109
+ } catch (e) {
110
+ wrapped = updateStatus(config, name, wrapped, "warning");
111
+ response.warnings = response.warnings || [];
112
+
113
+ const errorMessage = logMutateErrorMessage(e);
114
+
115
+ // Log on failure
116
+ Log.error(actMeta, `Action failed: ${errorMessage}`);
117
+ response.warnings.push(`Action failed: ${errorMessage}`);
118
+
119
+ switch (config.onError) {
120
+ case OnError.REJECT:
121
+ response.result = "Pepr module configured to reject on error";
122
+ break;
123
+
124
+ case OnError.AUDIT:
125
+ response.auditAnnotations = response.auditAnnotations || {};
126
+ response.auditAnnotations[Date.now()] = `Action failed: ${errorMessage}`;
127
+ break;
128
+ }
129
+ }
130
+
131
+ return { wrapped, response };
132
+ }
133
+
134
+ /* eslint max-statements: ["warn", 25] */
135
+ export async function mutateProcessor(
136
+ config: ModuleConfig,
137
+ capabilities: Capability[],
138
+ req: AdmissionRequest,
139
+ reqMetadata: Record<string, string>,
140
+ ): Promise<MutateResponse> {
141
+ let response: MutateResponse = {
142
+ uid: req.uid,
143
+ warnings: [],
144
+ allowed: false,
145
+ };
146
+
147
+ const decoded = decodeData(new PeprMutateRequest(req));
148
+ let wrapped = decoded.wrapped;
149
+
150
+ Log.info(reqMetadata, `Processing request`);
151
+
152
+ let bindables: Bindable[] = capabilities.flatMap(capa =>
153
+ capa.bindings.map(bind => ({
154
+ req,
155
+ config,
156
+ name: capa.name,
157
+ namespaces: capa.namespaces,
158
+ binding: bind,
159
+ actMeta: { ...reqMetadata, name: capa.name },
160
+ })),
161
+ );
162
+
163
+ bindables = bindables.filter(bind => {
164
+ if (!bind.binding.mutateCallback) {
165
+ return false;
166
+ }
167
+
168
+ const shouldSkip = shouldSkipRequest(
169
+ bind.binding,
170
+ bind.req,
171
+ bind.namespaces,
172
+ bind.config?.alwaysIgnore?.namespaces,
173
+ );
174
+ if (shouldSkip !== "") {
175
+ Log.debug(shouldSkip);
176
+ return false;
177
+ }
178
+
179
+ return true;
180
+ });
181
+
182
+ for (const bindable of bindables) {
183
+ ({ wrapped, response } = await processRequest(bindable, wrapped, response));
184
+ if (config.onError === OnError.REJECT && response?.warnings!.length > 0) {
185
+ return response;
186
+ }
187
+ }
188
+
189
+ // If we've made it this far, the request is allowed
190
+ response.allowed = true;
191
+
192
+ // If no capability matched the request, exit early
193
+ if (bindables.length === 0) {
194
+ Log.info(reqMetadata, `No matching actions found`);
195
+ return response;
196
+ }
197
+
198
+ // delete operations can't be mutate, just return before the transformation
199
+ if (req.operation === "DELETE") {
200
+ return response;
201
+ }
202
+
203
+ // unskip base64-encoded data fields that were skipDecode'd
204
+ const transformed = reencodeData(wrapped, decoded.skipped);
205
+
206
+ // Compare the original request to the modified request to get the patches
207
+ const patches = jsonPatch.compare(req.object, transformed);
208
+
209
+ // Only add the patch if there are patches to apply
210
+ if (patches.length > 0) {
211
+ response.patchType = "JSONPatch";
212
+ // Webhook must be base64-encoded
213
+ // https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#response
214
+ response.patch = base64Encode(JSON.stringify(patches));
215
+ }
216
+
217
+ // Remove the warnings array if it's empty
218
+ if (response.warnings && response.warnings.length < 1) {
219
+ delete response.warnings;
220
+ }
221
+
222
+ Log.debug({ ...reqMetadata, patches }, `Patches generated`);
223
+
224
+ return response;
225
+ }
@@ -2,14 +2,14 @@
2
2
  // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
3
 
4
4
  import { kind, KubernetesObject } from "kubernetes-fluent-client";
5
- import { Capability } from "./capability";
6
- import { shouldSkipRequest } from "./filter/filter";
7
- import { ValidateResponse } from "./k8s";
8
- import { AdmissionRequest, Binding } from "./types";
9
- import Log from "./telemetry/logger";
10
- import { convertFromBase64Map } from "./utils";
11
- import { PeprValidateRequest } from "./validate-request";
12
- import { ModuleConfig } from "./module";
5
+ import { Capability } from "../core/capability";
6
+ import { shouldSkipRequest } from "../filter/filter";
7
+ import { ValidateResponse } from "../k8s";
8
+ import { AdmissionRequest, Binding } from "../types";
9
+ import Log from "../telemetry/logger";
10
+ import { convertFromBase64Map } from "../utils";
11
+ import { PeprValidateRequest } from "../validate-request";
12
+ import { ModuleConfig } from "../core/module";
13
13
 
14
14
  export async function processRequest(
15
15
  binding: Binding,
@@ -1,15 +1,15 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
+ import Log from "../telemetry/logger";
4
+ import { Binding } from "../types";
5
+ import { Capability } from "../core/capability";
6
+ import { Event } from "../enums";
3
7
  import { K8s, KubernetesObject, WatchCfg, WatchEvent } from "kubernetes-fluent-client";
8
+ import { Queue } from "../core/queue";
4
9
  import { WatchPhase } from "kubernetes-fluent-client/dist/fluent/types";
5
- import { Capability } from "./capability";
6
- import { filterNoMatchReason } from "./helpers";
7
- import { removeFinalizer } from "./finalizer";
8
- import Log from "./telemetry/logger";
9
- import { Queue } from "./queue";
10
- import { Binding } from "./types";
11
- import { Event } from "./enums";
12
- import { metricsCollector } from "./telemetry/metrics";
10
+ import { filterNoMatchReason } from "../filter/filter";
11
+ import { metricsCollector } from "../telemetry/metrics";
12
+ import { removeFinalizer } from "../finalizer";
13
13
 
14
14
  // stores Queue instances
15
15
  const queues: Record<string, Queue<KubernetesObject>> = {};
@@ -18,7 +18,9 @@ const pretty = {
18
18
  const transport = isPrettyLog ? pretty : undefined;
19
19
  // epochTime is the pino default
20
20
  const pinoTimeFunction =
21
- process.env.PINO_TIME_STAMP === "iso" ? () => stdTimeFunctions.isoTime() : () => stdTimeFunctions.epochTime();
21
+ process.env.PINO_TIME_STAMP === "iso"
22
+ ? (): string => stdTimeFunctions.isoTime()
23
+ : (): string => stdTimeFunctions.epochTime();
22
24
  const Log = pino({
23
25
  transport,
24
26
  timestamp: pinoTimeFunction,
package/src/lib/tls.ts CHANGED
@@ -62,7 +62,11 @@ export function genTLS(name: string): TLSOut {
62
62
  return { ca, key, crt, pem };
63
63
  }
64
64
 
65
- function genCert(key: forge.pki.rsa.KeyPair, name: string, issuer: forge.pki.CertificateField[]) {
65
+ function genCert(
66
+ key: forge.pki.rsa.KeyPair,
67
+ name: string,
68
+ issuer: forge.pki.CertificateField[],
69
+ ): forge.pki.Certificate {
66
70
  const crt = forge.pki.createCertificate();
67
71
  crt.publicKey = key.publicKey;
68
72
  crt.serialNumber = "01";
@@ -23,7 +23,7 @@ export class PeprValidateRequest<T extends KubernetesObject> {
23
23
  * Provides access to the old resource in the request if available.
24
24
  * @returns The old Kubernetes resource object or null if not available.
25
25
  */
26
- get OldResource() {
26
+ get OldResource(): KubernetesObject | undefined {
27
27
  return this.#input.oldObject;
28
28
  }
29
29
 
@@ -31,7 +31,7 @@ export class PeprValidateRequest<T extends KubernetesObject> {
31
31
  * Provides access to the request object.
32
32
  * @returns The request object containing the Kubernetes resource.
33
33
  */
34
- get Request() {
34
+ get Request(): AdmissionRequest<KubernetesObject> {
35
35
  return this.#input;
36
36
  }
37
37
 
@@ -61,7 +61,7 @@ export class PeprValidateRequest<T extends KubernetesObject> {
61
61
  * @param key the label key to check
62
62
  * @returns
63
63
  */
64
- HasLabel = (key: string) => {
64
+ HasLabel = (key: string): boolean => {
65
65
  return this.Raw.metadata?.labels?.[key] !== undefined;
66
66
  };
67
67
 
@@ -71,7 +71,7 @@ export class PeprValidateRequest<T extends KubernetesObject> {
71
71
  * @param key the annotation key to check
72
72
  * @returns
73
73
  */
74
- HasAnnotation = (key: string) => {
74
+ HasAnnotation = (key: string): boolean => {
75
75
  return this.Raw.metadata?.annotations?.[key] !== undefined;
76
76
  };
77
77
 
package/src/lib.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { K8s, RegisterKind, kind as a, fetch, fetchStatus, kind } from "kubernetes-fluent-client";
2
2
  import * as R from "ramda";
3
3
 
4
- import { Capability } from "./lib/capability";
4
+ import { Capability } from "./lib/core/capability";
5
5
  import Log from "./lib/telemetry/logger";
6
- import { PeprModule } from "./lib/module";
6
+ import { PeprModule } from "./lib/core/module";
7
7
  import { PeprMutateRequest } from "./lib/mutate-request";
8
8
  import * as PeprUtils from "./lib/utils";
9
9
  import { PeprValidateRequest } from "./lib/validate-request";
@@ -14,7 +14,7 @@ import { peprStoreCRD } from "../lib/assets/store";
14
14
  import { validateHash } from "../lib/helpers";
15
15
  const { version } = packageJSON;
16
16
 
17
- function runModule(expectedHash: string) {
17
+ function runModule(expectedHash: string): void {
18
18
  const gzPath = `/app/load/module-${expectedHash}.js.gz`;
19
19
  const jsPath = `/app/module-${expectedHash}.js`;
20
20
 
@@ -59,7 +59,7 @@ Log.info(`Pepr Controller (v${version})`);
59
59
 
60
60
  const hash = process.argv[2];
61
61
 
62
- const startup = async () => {
62
+ const startup = async (): Promise<void> => {
63
63
  try {
64
64
  Log.info("Applying the Pepr Store CRD if it doesn't exist");
65
65
  await K8s(kind.CustomResourceDefinition).Apply(peprStoreCRD, { force: true });
@@ -1,7 +1,7 @@
1
1
  // Refs:
2
2
  // - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates
3
3
 
4
- export function heredoc(strings: TemplateStringsArray, ...values: string[]) {
4
+ export function heredoc(strings: TemplateStringsArray, ...values: string[]): string {
5
5
  // shuffle strings & expression values back together
6
6
  const zipped = strings
7
7
  .reduce((acc: string[], cur, idx) => {
@@ -1 +0,0 @@
1
- {"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../../src/lib/capability.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAA2B,MAAM,0BAA0B,CAAC;AAInG,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAc,QAAQ,EAAE,MAAM,YAAY,CAAC;AAElD,OAAO,EACL,OAAO,EAGP,aAAa,EACb,gBAAgB,EAQhB,YAAY,EACb,MAAM,SAAS,CAAC;AAMjB;;GAEG;AACH,qBAAa,UAAW,YAAW,gBAAgB;;IASjD,WAAW,EAAE,OAAO,CAAC;IAErB;;;;;OAKG;IACH,UAAU,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAqBtC;IAEK,gBAAgB,IAAI,OAAO;IAIlC;;;;;;OAMG;IACH,KAAK,EAAE,SAAS,CASd;IAEF;;;;;;OAMG;IACH,aAAa,EAAE,SAAS,CAStB;IAEF,IAAI,QAAQ,IAAI,OAAO,EAAE,CAExB;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,UAAU,IAAI,MAAM,EAAE,CAEzB;gBAEW,GAAG,EAAE,aAAa;IAU9B;;OAEG;IACH,qBAAqB,QAAO,OAAO,CAWjC;IAEF;;;;OAIG;IACH,aAAa,QAAO,OAAO,CAWzB;IAEF;;;;;;;;OAQG;IACH,IAAI,4CAA6C,gBAAgB,qBA4O/D;CACH"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../src/lib/module.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACxE,OAAO,EAAoB,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAG7D,OAAO,EAAE,YAAY,IAAI,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErE,0CAA0C;AAC1C,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AACD,iDAAiD;AACjD,MAAM,MAAM,YAAY,GAAG;IACzB,wCAAwC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yFAAyF;IACzF,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yBAAyB;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sDAAsD;IACtD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,YAAY,EAAE,aAAa,CAAC;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,2CAA2C;IAC3C,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,wBAAwB;IACxB,IAAI,CAAC,EAAE,UAAU,EAAE,CAAC;IACpB,yFAAyF;IACzF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,YAAY,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,qHAAqH;IACrH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAE7C,6GAA6G;IAC7G,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,cAAc,GAAG,gBAAgB,KAAK,IAAI,CAAC;CAC9D,CAAC;AAGF,eAAO,MAAM,WAAW,eAA+C,CAAC;AAGxE,eAAO,MAAM,WAAW,eAA0C,CAAC;AAEnE,eAAO,MAAM,SAAS,eAAwC,CAAC;AAE/D,qBAAa,UAAU;;IAGrB;;;;;;OAMG;gBACS,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,WAAW,EAAE,YAAY,GAAE,UAAU,EAAO,EAAE,IAAI,GAAE,iBAAsB;IAsD7G;;;;;OAKG;IACH,KAAK,0BAEH;CACH"}
@@ -1,6 +0,0 @@
1
- import { Capability } from "./capability";
2
- import { MutateResponse } from "./k8s";
3
- import { AdmissionRequest } from "./types";
4
- import { ModuleConfig } from "./module";
5
- export declare function mutateProcessor(config: ModuleConfig, capabilities: Capability[], req: AdmissionRequest, reqMetadata: Record<string, string>): Promise<MutateResponse>;
6
- //# sourceMappingURL=mutate-processor.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"mutate-processor.d.ts","sourceRoot":"","sources":["../../src/lib/mutate-processor.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,OAAO,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE3C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAIxC,wBAAsB,eAAe,CACnC,MAAM,EAAE,YAAY,EACpB,YAAY,EAAE,UAAU,EAAE,EAC1B,GAAG,EAAE,gBAAgB,EACrB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAClC,OAAO,CAAC,cAAc,CAAC,CAmIzB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../src/lib/queue.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,4CAA4C,CAAC;AAIxE,KAAK,aAAa,GAAG,CAAC,GAAG,EAAE,gBAAgB,EAAE,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAUjF;;GAEG;AACH,qBAAa,KAAK,CAAC,CAAC,SAAS,gBAAgB;;gBAM/B,IAAI,EAAE,MAAM;IAKxB,KAAK,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE;IAItC,KAAK,IAAI;QACP,KAAK,EAAE;YACL,IAAI,EAAE,MAAM,CAAC;YACb,GAAG,EAAE,MAAM,CAAC;SACb,CAAC;QACF,KAAK,EAAE;YACL,MAAM,EAAE,MAAM,CAAC;SAChB,CAAC;KACH;IASD;;;;;;;;OAQG;IACH,OAAO,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;CAsE7E"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"schedule.d.ts","sourceRoot":"","sources":["../../src/lib/schedule.ts"],"names":[],"mappings":";AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,MAAM,IAAI,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAElF,MAAM,WAAW,QAAQ;IACvB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,EAAE,IAAI,CAAC;IACX;;OAEG;IACH,GAAG,EAAE,MAAM,IAAI,CAAC;IAChB;;OAEG;IACH,SAAS,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;IAE7B;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;CAC7B;AAED,qBAAa,UAAW,YAAW,QAAQ;IACzC,UAAU,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAQ;IACzC,KAAK,EAAE,SAAS,GAAG,SAAS,CAAC;IAC7B,IAAI,EAAG,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,IAAI,CAAC;IACX,GAAG,EAAG,MAAM,IAAI,CAAC;IACjB,SAAS,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;IAC7B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,aAAa,EAAE,IAAI,GAAG,SAAS,CAAC;gBAEpB,QAAQ,EAAE,QAAQ;IAQ9B,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAIhC,aAAa,IAAI,IAAI;IAKrB;;;OAGG;IACH,UAAU,IAAI,IAAI;IAUlB;;;OAGG;IACH,WAAW,IAAI,IAAI;IAUnB;;OAEG;IACH,WAAW,IAAI,IAAI;IAmBnB;;OAEG;IACH,aAAa,IAAI,IAAI;IAwBrB;;OAEG;IACH,KAAK,IAAI,IAAI;IAgBb;;OAEG;IACH,IAAI,IAAI,IAAI;CAOb"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/lib/storage.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;AACtC,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAC/C,MAAM,MAAM,UAAU,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;AAC9E,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;AACrD,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAUrC,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEjD;AACD,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACpC;;OAEG;IACH,KAAK,IAAI,IAAI,CAAC;IACd;;OAEG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAE1C;;;;;OAKG;IACH,SAAS,CAAC,QAAQ,EAAE,YAAY,GAAG,WAAW,CAAC;IAE/C;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IAEtC;;;OAGG;IACH,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE5D;;;OAGG;IACH,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACjD;AAED;;;;GAIG;AAEH,qBAAa,OAAQ,YAAW,SAAS;;IAOvC,cAAc,SAAU,UAAU,KAAG,IAAI,CAEvC;IAEF,OAAO,SAAU,SAAS,KAAG,IAAI,CAU/B;IAEF,OAAO,QAAS,MAAM,KAAG,MAAM,GAAG,IAAI,CAMpC;IAEF,KAAK,QAAO,IAAI,CAMd;IAEF,UAAU,QAAS,MAAM,KAAG,IAAI,CAE9B;IAEF,OAAO,QAAS,MAAM,SAAS,MAAM,KAAG,IAAI,CAE1C;IAEF;;;;;;;OAOG;IACH,cAAc,QAAS,MAAM,SAAS,MAAM,KAAG,QAAQ,MAAM,CAAC,CAmB5D;IAEF;;;;;;OAMG;IACH,iBAAiB,QAAS,MAAM,KAAG,QAAQ,MAAM,CAAC,CAkBhD;IAEF,SAAS,eAAgB,YAAY,KAAG,CAAC,MAAM,IAAI,CAAC,CAIlD;IAEF,OAAO,aAAc,YAAY,KAAG,IAAI,CAEtC;IAEF;;;OAGG;IACH,WAAW,QAAS,MAAM,KAAG,IAAI,CAE/B;CAqBH"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"validate-processor.d.ts","sourceRoot":"","sources":["../../src/lib/validate-processor.ts"],"names":[],"mappings":"AAGA,OAAO,EAAQ,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACtC,mBAAmB,EAAE,mBAAmB,CAAC,gBAAgB,CAAC,GACzD,OAAO,CAAC,gBAAgB,CAAC,CAkC3B;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,YAAY,EACpB,YAAY,EAAE,UAAU,EAAE,EAC1B,GAAG,EAAE,gBAAgB,EACrB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAClC,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAkC7B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"watch-processor.d.ts","sourceRoot":"","sources":["../../src/lib/watch-processor.ts"],"names":[],"mappings":"AAEA,OAAO,EAAO,gBAAgB,EAAY,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEvF,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAI1C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAQhC;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,gBAAgB,GAAG,MAAM,CAkBtD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,gBAAgB,GAAG,KAAK,CAAC,gBAAgB,CAAC,CAM/E;AAuBD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,YAAY,EAAE,UAAU,EAAE,EAAE,iBAAiB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAMzF;AAmHD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,GAAE,MAAW,EAAE,GAAG,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAO9F"}
@@ -1,165 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
-
4
- import jsonPatch from "fast-json-patch";
5
- import { kind } from "kubernetes-fluent-client";
6
-
7
- import { Capability } from "./capability";
8
- import { Errors } from "./errors";
9
- import { shouldSkipRequest } from "./filter/filter";
10
- import { MutateResponse } from "./k8s";
11
- import { AdmissionRequest } from "./types";
12
- import Log from "./telemetry/logger";
13
- import { ModuleConfig } from "./module";
14
- import { PeprMutateRequest } from "./mutate-request";
15
- import { base64Encode, convertFromBase64Map, convertToBase64Map } from "./utils";
16
-
17
- export async function mutateProcessor(
18
- config: ModuleConfig,
19
- capabilities: Capability[],
20
- req: AdmissionRequest,
21
- reqMetadata: Record<string, string>,
22
- ): Promise<MutateResponse> {
23
- const wrapped = new PeprMutateRequest(req);
24
- const response: MutateResponse = {
25
- uid: req.uid,
26
- warnings: [],
27
- allowed: false,
28
- };
29
-
30
- // Track whether any capability matched the request
31
- let matchedAction = false;
32
-
33
- // Track data fields that should be skipped during decoding
34
- let skipDecode: string[] = [];
35
-
36
- // If the resource is a secret, decode the data
37
- const isSecret = req.kind.version === "v1" && req.kind.kind === "Secret";
38
- if (isSecret) {
39
- skipDecode = convertFromBase64Map(wrapped.Raw as unknown as kind.Secret);
40
- }
41
-
42
- Log.info(reqMetadata, `Processing request`);
43
-
44
- for (const { name, bindings, namespaces } of capabilities) {
45
- const actionMetadata = { ...reqMetadata, name };
46
- for (const action of bindings) {
47
- // Skip this action if it's not a mutate action
48
- if (!action.mutateCallback) {
49
- continue;
50
- }
51
-
52
- // Continue to the next action without doing anything if this one should be skipped
53
- const shouldSkip = shouldSkipRequest(action, req, namespaces, config?.alwaysIgnore?.namespaces);
54
- if (shouldSkip !== "") {
55
- Log.debug(shouldSkip);
56
- continue;
57
- }
58
-
59
- const label = action.mutateCallback.name;
60
- Log.info(actionMetadata, `Processing mutation action (${label})`);
61
- matchedAction = true;
62
-
63
- // Add annotations to the request to indicate that the capability started processing
64
- // this will allow tracking of failed mutations that were permitted to continue
65
- const updateStatus = (status: string) => {
66
- // Only update the status if the request is a CREATE or UPDATE (we don't use CONNECT)
67
- if (req.operation === "DELETE") {
68
- return;
69
- }
70
-
71
- const identifier = `${config.uuid}.pepr.dev/${name}`;
72
- wrapped.Raw.metadata = wrapped.Raw.metadata || {};
73
- wrapped.Raw.metadata.annotations = wrapped.Raw.metadata.annotations || {};
74
- wrapped.Raw.metadata.annotations[identifier] = status;
75
- };
76
-
77
- updateStatus("started");
78
-
79
- try {
80
- // Run the action
81
- await action.mutateCallback(wrapped);
82
-
83
- // Log on success
84
- Log.info(actionMetadata, `Mutation action succeeded (${label})`);
85
-
86
- // Add annotations to the request to indicate that the capability succeeded
87
- updateStatus("succeeded");
88
- } catch (e) {
89
- updateStatus("warning");
90
- response.warnings = response.warnings || [];
91
-
92
- const errorMessage = logMutateErrorMessage(e);
93
-
94
- // Log on failure
95
- Log.error(actionMetadata, `Action failed: ${errorMessage}`);
96
- response.warnings.push(`Action failed: ${errorMessage}`);
97
-
98
- switch (config.onError) {
99
- case Errors.reject:
100
- Log.error(actionMetadata, `Action failed: ${errorMessage}`);
101
- response.result = "Pepr module configured to reject on error";
102
- return response;
103
-
104
- case Errors.audit:
105
- response.auditAnnotations = response.auditAnnotations || {};
106
- response.auditAnnotations[Date.now()] = `Action failed: ${errorMessage}`;
107
- break;
108
- }
109
- }
110
- }
111
- }
112
-
113
- // If we've made it this far, the request is allowed
114
- response.allowed = true;
115
-
116
- // If no capability matched the request, exit early
117
- if (!matchedAction) {
118
- Log.info(reqMetadata, `No matching actions found`);
119
- return response;
120
- }
121
-
122
- // delete operations can't be mutate, just return before the transformation
123
- if (req.operation === "DELETE") {
124
- return response;
125
- }
126
-
127
- const transformed = wrapped.Raw;
128
-
129
- // Post-process the Secret requests to convert it back to the original format
130
- if (isSecret) {
131
- convertToBase64Map(transformed as unknown as kind.Secret, skipDecode);
132
- }
133
-
134
- // Compare the original request to the modified request to get the patches
135
- const patches = jsonPatch.compare(req.object, transformed);
136
-
137
- // Only add the patch if there are patches to apply
138
- if (patches.length > 0) {
139
- response.patchType = "JSONPatch";
140
- // Webhook must be base64-encoded
141
- // https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#response
142
- response.patch = base64Encode(JSON.stringify(patches));
143
- }
144
-
145
- // Remove the warnings array if it's empty
146
- if (response.warnings && response.warnings.length < 1) {
147
- delete response.warnings;
148
- }
149
-
150
- Log.debug({ ...reqMetadata, patches }, `Patches generated`);
151
-
152
- return response;
153
- }
154
-
155
- const logMutateErrorMessage = (e: Error): string => {
156
- try {
157
- if (e.message && e.message !== "[object Object]") {
158
- return e.message;
159
- } else {
160
- throw new Error("An error occurred in the mutate action.");
161
- }
162
- } catch (e) {
163
- return "An error occurred with the mutate action.";
164
- }
165
- };
File without changes
File without changes
File without changes
File without changes