Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Fix admission filters wip #1395

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 24 additions & 24 deletions src/lib/filter/adjudicators.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,9 @@
[{ metadata: { name: null } }, ""],
[{ metadata: { name: "name" } }, "name"],
])("given %j, returns '%s'", (given, expected) => {
const binding = given as DeepPartial<Binding>;
const kubernetesObject = given as DeepPartial<KubernetesObject>;

const result = sut.carriedName(binding);
const result = sut.carriedName(kubernetesObject);

expect(result).toBe(expected);
});
Expand All @@ -194,9 +194,9 @@
[{ metadata: { name: null } }, false],
[{ metadata: { name: "name" } }, true],
])("given %j, returns %s", (given, expected) => {
const binding = given as DeepPartial<Binding>;
const kubernetesObject = given as DeepPartial<KubernetesObject>;

const result = sut.carriesName(binding);
const result = sut.carriesName(kubernetesObject);

expect(result).toBe(expected);
});
Expand All @@ -210,9 +210,9 @@
[{ metadata: { name: null } }, true],
[{ metadata: { name: "name" } }, false],
])("given %j, returns %s", (given, expected) => {
const binding = given as DeepPartial<Binding>;
const kubernetesObject = given as DeepPartial<KubernetesObject>;

const result = sut.missingName(binding);
const result = sut.missingName(kubernetesObject);

expect(result).toBe(expected);
});
Expand Down Expand Up @@ -377,9 +377,9 @@
[{ metadata: { namespace: "" } }, ""],
[{ metadata: { namespace: "namespace" } }, "namespace"],
])("given %j, returns %j", (given, expected) => {
const binding = given as DeepPartial<Binding>;
const object = given as DeepPartial<KubernetesObject>;

const result = sut.carriedNamespace(binding);
const result = sut.carriedNamespace(object);

expect(result).toEqual(expected);
});
Expand All @@ -394,9 +394,9 @@
[{ metadata: { namespace: "" } }, false],
[{ metadata: { namespace: "namespace" } }, true],
])("given %j, returns %s", (given, expected) => {
const binding = given as DeepPartial<Binding>;
const object = given as DeepPartial<KubernetesObject>;

const result = sut.carriesNamespace(binding);
const result = sut.carriesNamespace(object);

expect(result).toBe(expected);
});
Expand All @@ -412,7 +412,7 @@
[{ filters: { namespaces: ["namespace"] } }, { metadata: { namespace: "namespace" } }, false],
])("given binding %j and object %j, returns %s", (bnd, obj, expected) => {
const binding = bnd as DeepPartial<Binding>;
const object = obj as DeepPartial<Binding>;
const object = obj as DeepPartial<KubernetesObject>;

const result = sut.mismatchedNamespace(binding, object);

Expand Down Expand Up @@ -443,7 +443,7 @@
],
])("given binding %j and object %j, returns %s", (bnd, obj, expected) => {
const binding = bnd as DeepPartial<Binding>;
const object = obj as DeepPartial<Binding>;
const object = obj as DeepPartial<KubernetesObject>;

const result = sut.mismatchedNamespaceRegex(binding, object);

Expand Down Expand Up @@ -513,9 +513,9 @@
[{ metadata: { annotations: { annotation: "" } } }, { annotation: "" }],
[{ metadata: { annotations: { anno: "tation" } } }, { anno: "tation" }],
])("given %j, returns %j", (given, expected) => {
const binding = given as DeepPartial<KubernetesObject>;
const object = given as DeepPartial<KubernetesObject>;

const result = sut.carriedAnnotations(binding);
const result = sut.carriedAnnotations(object);

expect(result).toEqual(expected);
});
Expand All @@ -531,9 +531,9 @@
[{ metadata: { annotations: { annotation: "" } } }, true],
[{ metadata: { annotations: { anno: "tation" } } }, true],
])("given %j, returns %s", (given, expected) => {
const binding = given as DeepPartial<KubernetesObject>;
const object = given as DeepPartial<KubernetesObject>;

const result = sut.carriesAnnotations(binding);
const result = sut.carriesAnnotations(object);

expect(result).toBe(expected);
});
Expand Down Expand Up @@ -591,7 +591,7 @@
],
])("given binding %j and object %j, returns %s", (bnd, obj, expected) => {
const binding = bnd as DeepPartial<Binding>;
const object = obj as DeepPartial<Binding>;
const object = obj as DeepPartial<KubernetesObject>;

const result = sut.mismatchedAnnotations(binding, object);

Expand Down Expand Up @@ -645,9 +645,9 @@
[{ metadata: { labels: { label: "" } } }, { label: "" }],
[{ metadata: { labels: { lab: "el" } } }, { lab: "el" }],
])("given %j, returns %j", (given, expected) => {
const binding = given as DeepPartial<KubernetesObject>;
const obj = given as DeepPartial<KubernetesObject>;

const result = sut.carriedLabels(binding);
const result = sut.carriedLabels(obj);

expect(result).toEqual(expected);
});
Expand All @@ -663,9 +663,9 @@
[{ metadata: { labels: { label: "" } } }, true],
[{ metadata: { labels: { lab: "el" } } }, true],
])("given %j, returns %s", (given, expected) => {
const binding = given as DeepPartial<KubernetesObject>;
const obj = given as DeepPartial<KubernetesObject>;

const result = sut.carriesLabels(binding);
const result = sut.carriesLabels(obj);

expect(result).toBe(expected);
});
Expand All @@ -691,7 +691,7 @@
[{ filters: { labels: { l: "a", b: "le" } } }, { metadata: { labels: { l: "a", b: "le" } } }, false],
])("given binding %j and object %j, returns %s", (bnd, obj, expected) => {
const binding = bnd as DeepPartial<Binding>;
const object = obj as DeepPartial<Binding>;
const object = obj as DeepPartial<KubernetesObject>;

const result = sut.mismatchedLabels(binding, object);

Expand Down Expand Up @@ -720,7 +720,7 @@
[["name", "space"], { metadata: { namespace: "name" } }, false],
[["name", "space"], { metadata: { namespace: "space" } }, false],
])("given capabilityNamespaces %j and object %j, returns %s", (nss, obj, expected) => {
const object = obj as DeepPartial<Binding>;
const object = obj as DeepPartial<KubernetesObject>;

const result = sut.uncarryableNamespace(nss, object);

Expand Down Expand Up @@ -749,7 +749,7 @@
[["ign", "ored"], { metadata: { namespace: "ored" } }, true],
[["ign", "ored"], { metadata: { namespace: "namespace" } }, false],
])("given capabilityNamespaces %j and object %j, returns %s", (nss, obj, expected) => {
const object = obj as DeepPartial<Binding>;
const object = obj as DeepPartial<KubernetesObject>;

const result = sut.carriesIgnoredNamespace(nss, object);

Expand Down Expand Up @@ -898,7 +898,7 @@
])("given %j, returns '%s'", (given, expected) => {
const request = given as DeepPartial<AdmissionRequest>;

const result = sut.declaredOperation(request);

Check failure on line 901 in src/lib/filter/adjudicators.test.ts

View workflow job for this annotation

GitHub Actions / container-scans

Argument of type 'DeepPartial<AdmissionRequest<KubernetesObject>>' is not assignable to parameter of type 'AdmissionRequest<KubernetesObject>'.

Check failure on line 901 in src/lib/filter/adjudicators.test.ts

View workflow job for this annotation

GitHub Actions / journey

Argument of type 'DeepPartial<AdmissionRequest<KubernetesObject>>' is not assignable to parameter of type 'AdmissionRequest<KubernetesObject>'.

expect(result).toEqual(expected);
});
Expand Down Expand Up @@ -992,7 +992,7 @@
])("given %j, returns '%s'", (given, expected) => {
const request = given as DeepPartial<AdmissionRequest>;

const result = sut.declaredGroup(request);

Check failure on line 995 in src/lib/filter/adjudicators.test.ts

View workflow job for this annotation

GitHub Actions / container-scans

Argument of type 'DeepPartial<AdmissionRequest<KubernetesObject>>' is not assignable to parameter of type 'AdmissionRequest<KubernetesObject>'.

Check failure on line 995 in src/lib/filter/adjudicators.test.ts

View workflow job for this annotation

GitHub Actions / journey

Argument of type 'DeepPartial<AdmissionRequest<KubernetesObject>>' is not assignable to parameter of type 'AdmissionRequest<KubernetesObject>'.

expect(result).toEqual(expected);
});
Expand Down Expand Up @@ -1064,7 +1064,7 @@
])("given %j, returns '%s'", (given, expected) => {
const request = given as DeepPartial<AdmissionRequest>;

const result = sut.declaredVersion(request);

Check failure on line 1067 in src/lib/filter/adjudicators.test.ts

View workflow job for this annotation

GitHub Actions / container-scans

Argument of type 'DeepPartial<AdmissionRequest<KubernetesObject>>' is not assignable to parameter of type 'AdmissionRequest<KubernetesObject>'.

Check failure on line 1067 in src/lib/filter/adjudicators.test.ts

View workflow job for this annotation

GitHub Actions / journey

Argument of type 'DeepPartial<AdmissionRequest<KubernetesObject>>' is not assignable to parameter of type 'AdmissionRequest<KubernetesObject>'.

expect(result).toEqual(expected);
});
Expand Down Expand Up @@ -1136,7 +1136,7 @@
])("given %j, returns '%s'", (given, expected) => {
const request = given as DeepPartial<AdmissionRequest>;

const result = sut.declaredKind(request);

Check failure on line 1139 in src/lib/filter/adjudicators.test.ts

View workflow job for this annotation

GitHub Actions / container-scans

Argument of type 'DeepPartial<AdmissionRequest<KubernetesObject>>' is not assignable to parameter of type 'AdmissionRequest<KubernetesObject>'.

Check failure on line 1139 in src/lib/filter/adjudicators.test.ts

View workflow job for this annotation

GitHub Actions / journey

Argument of type 'DeepPartial<AdmissionRequest<KubernetesObject>>' is not assignable to parameter of type 'AdmissionRequest<KubernetesObject>'.

expect(result).toEqual(expected);
});
Expand Down Expand Up @@ -1230,7 +1230,7 @@
])("given %j, returns '%s'", (given, expected) => {
const request = given as DeepPartial<AdmissionRequest>;

const result = sut.declaredUid(request);

Check failure on line 1233 in src/lib/filter/adjudicators.test.ts

View workflow job for this annotation

GitHub Actions / container-scans

Argument of type 'DeepPartial<AdmissionRequest<KubernetesObject>>' is not assignable to parameter of type 'AdmissionRequest<KubernetesObject>'.

Check failure on line 1233 in src/lib/filter/adjudicators.test.ts

View workflow job for this annotation

GitHub Actions / journey

Argument of type 'DeepPartial<AdmissionRequest<KubernetesObject>>' is not assignable to parameter of type 'AdmissionRequest<KubernetesObject>'.

expect(result).toEqual(expected);
});
Expand Down
27 changes: 14 additions & 13 deletions src/lib/filter/adjudicators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import {
nthArg,
pipe,
} from "ramda";

import { AdmissionRequest } from "../types";
import { KubernetesObject } from "kubernetes-fluent-client";
/*
Naming scheme:
- AdmissionRequest - "declares" / "neglects"
Expand All @@ -29,34 +30,34 @@ import {
/*
AdmissionRequest collectors
*/
export const declaredOperation = pipe(request => request?.operation, defaultTo(""));
export const declaredGroup = pipe(request => request?.kind?.group, defaultTo(""));
export const declaredVersion = pipe(request => request?.kind?.version, defaultTo(""));
export const declaredKind = pipe(request => request?.kind?.kind, defaultTo(""));
export const declaredUid = pipe(request => request?.uid, defaultTo(""));
export const declaredOperation = pipe((request: AdmissionRequest) => request?.operation, defaultTo(""));
export const declaredGroup = pipe((request: AdmissionRequest) => request?.kind?.group, defaultTo(""));
export const declaredVersion = pipe((request: AdmissionRequest) => request?.kind?.version, defaultTo(""));
export const declaredKind = pipe((request: AdmissionRequest) => request?.kind?.kind, defaultTo(""));
export const declaredUid = pipe((request: AdmissionRequest) => request?.uid, defaultTo(""));

/*
KuberneteskubernetesObjectect collectors
*/
export const carriesDeletionTimestamp = pipe(
kubernetesObject => !!kubernetesObject.metadata?.deletionTimestamp,
(kubernetesObject: KubernetesObject) => !!kubernetesObject.metadata?.deletionTimestamp,
defaultTo(false),
);
export const missingDeletionTimestamp = complement(carriesDeletionTimestamp);

export const carriedKind = pipe(kubernetesObject => kubernetesObject?.metadata?.kind, defaultTo("not set"));
export const carriedVersion = pipe(kubernetesObject => kubernetesObject?.metadata?.version, defaultTo("not set"));
export const carriedName = pipe(kubernetesObject => kubernetesObject?.metadata?.name, defaultTo(""));
export const carriedKind = pipe((kubernetesObject: KubernetesObject) => kubernetesObject?.kind, defaultTo("not set"));
export const carriedAPIVersion = pipe((kubernetesObject: KubernetesObject) => kubernetesObject?.apiVersion, defaultTo("not set"));
export const carriedName = pipe((kubernetesObject: KubernetesObject) => kubernetesObject?.metadata?.name, defaultTo(""));
export const carriesName = pipe(carriedName, equals(""), not);
export const missingName = complement(carriesName);

export const carriedNamespace = pipe(kubernetesObject => kubernetesObject?.metadata?.namespace, defaultTo(""));
export const carriedNamespace = pipe((kubernetesObject: KubernetesObject) => kubernetesObject?.metadata?.namespace, defaultTo(""));
export const carriesNamespace = pipe(carriedNamespace, equals(""), not);

export const carriedAnnotations = pipe(kubernetesObject => kubernetesObject?.metadata?.annotations, defaultTo({}));
export const carriedAnnotations = pipe((kubernetesObject: KubernetesObject) => kubernetesObject?.metadata?.annotations, defaultTo({}));
export const carriesAnnotations = pipe(carriedAnnotations, equals({}), not);

export const carriedLabels = pipe(kubernetesObject => kubernetesObject?.metadata?.labels, defaultTo({}));
export const carriedLabels = pipe((kubernetesObject: KubernetesObject) => kubernetesObject?.metadata?.labels, defaultTo({}));
export const carriesLabels = pipe(carriedLabels, equals({}), not);

/*
Expand Down
4 changes: 2 additions & 2 deletions src/lib/filter/filtersWithLogs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export const carriesIgnoredNamespaceFilter = createFilter(
data => data.ignoredNamespaces,
data => getAdmissionRequest(data),
(ignoreArray, kubernetesObject) => carriesIgnoredNamespace(ignoreArray, kubernetesObject),
(ignoreArray, kubernetesObject) => commonLogMessage("ignored namespaces", kubernetesObject, ignoreArray),
(ignoreArray, kubernetesObject) => commonLogMessage("ignored namespaces", ignoreArray, kubernetesObject),
);

export const unbindableNamespacesFilter = createFilter(
Expand Down Expand Up @@ -142,5 +142,5 @@ export const uncarryableNamespaceFilter = createFilter(
data => getAdmissionRequest(data),
(capabilityNamespaces, kubernetesObject) => uncarryableNamespace(capabilityNamespaces, kubernetesObject),
(capabilityNamespaces, kubernetesObject) =>
commonLogMessage("namespace array", kubernetesObject, capabilityNamespaces),
commonLogMessage("uncarryable namespace", capabilityNamespaces, kubernetesObject ),
);
61 changes: 46 additions & 15 deletions src/lib/filter/logMessages.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { FilterInput } from "../types";
import { KubernetesObject } from "kubernetes-fluent-client";
import { AdmissionRequest, FilterInput } from "../types";
import {
carriedKind,

Check failure on line 4 in src/lib/filter/logMessages.ts

View workflow job for this annotation

GitHub Actions / format

'carriedKind' is defined but never used
carriedName,
carriedNamespace,
carriedVersion,
carriedAPIVersion,

Check failure on line 7 in src/lib/filter/logMessages.ts

View workflow job for this annotation

GitHub Actions / format

'carriedAPIVersion' is defined but never used
declaredGroup,
declaredVersion,
definedAnnotations,
declaredKind,
definedGroup,
definedKind,
definedLabels,
Expand All @@ -16,13 +20,14 @@

const prefix = "Ignoring Admission Callback:";

const ignoredNamespacesKubernetesObjectCases = ["ignored namespaces"];
const capabilityNamespacesKubernetesObjectCases = ["uncarryable namespace"];
const bindingKubernetesObjectCases = [
"annotations",
"deletionTimestamp",
"labels",
"name regex",
"name",
"namespace array",
"namespace regexes",
"namespaces",
];
Expand All @@ -33,44 +38,70 @@
return getBindingKubernetesObjectMessage(subject, filterInput, filterCriteria);
} else if (bindingAdmissionRequestCases.includes(subject)) {
return getBindingAdmissionRequestMessage(subject, filterInput, filterCriteria);
} else if (subject === "ignored namespaces") {
return `${prefix} Object carries namespace '${carriedNamespace(filterInput)}' but ${subject} include '${JSON.stringify(filterCriteria)}'.`;
} else if (capabilityNamespacesKubernetesObjectCases.includes(subject)){
return getCapabilityNamespacesKubernetesObjectMessage(subject, filterInput, filterCriteria);
} else if (ignoredNamespacesKubernetesObjectCases.includes(subject)) {
return getIgnoredNamespacesKubernetesObjectMessage(subject, filterInput, filterCriteria);
} else {
return getUndefinedLoggingConditionMessage(subject, filterInput, filterCriteria);
}
};

const getBindingAdmissionRequestMessage = (subject: string, filterInput: FilterInput, filterCriteria?: FilterInput) => {
const admissionFilterCriteria = filterCriteria as AdmissionRequest;
switch (subject) {
case "group":
return `${prefix} Binding defines ${subject} '${definedGroup(filterInput)}' but Request declares '${carriedName(filterCriteria)}'.`;
return `${prefix} Binding defines ${subject} '${definedGroup(filterInput)}' but Request declares '${declaredGroup(admissionFilterCriteria)}'.`;
case "event":
return `${prefix} Binding defines ${subject} '${definedKind(filterInput)}' but Request does not declare it.`;
case "version":
return `${prefix} Binding defines ${subject} '${definedVersion(filterInput)}' but Request declares '${carriedVersion(filterCriteria)}'.`;
return `${prefix} Binding defines ${subject} '${definedVersion(filterInput)}' but Request declares '${declaredVersion(admissionFilterCriteria)}'.`;
case "kind":
return `${prefix} Binding defines ${subject} '${definedKind(filterInput)}' but Request declares '${carriedKind(filterCriteria)}'.`;
return `${prefix} Binding defines ${subject} '${definedKind(filterInput)}' but Request declares '${declaredKind(admissionFilterCriteria)}'.`;
default:
return getUndefinedLoggingConditionMessage(subject, filterInput, filterCriteria);
}
};

const getCapabilityNamespacesKubernetesObjectMessage = (subject: string, filterInput: FilterInput, filterCriteria?: FilterInput) => {
const capabilityNamespacesFilterInput = filterInput as string[];
const kubernetesObjectFilterCriteria = filterCriteria as KubernetesObject;
switch(subject){
case "uncarryable namespace":
return `${prefix} Object carries namespace '${carriedNamespace(kubernetesObjectFilterCriteria)}' but namespaces allowed by Capability are '${JSON.stringify(capabilityNamespacesFilterInput)}'.`;
default:
return getUndefinedLoggingConditionMessage(subject, filterInput, filterCriteria);
}
}
const getIgnoredNamespacesKubernetesObjectMessage = (subject: string, filterInput: FilterInput, filterCriteria?: FilterInput) => {
const ingoredNSFilterInput = filterInput as string[];
const kubernetesObjectFilterCriteria = filterCriteria as KubernetesObject;
switch(subject){
case "ignored namespaces":
return `${prefix} Object carries namespace '${carriedNamespace(kubernetesObjectFilterCriteria)}' but ${subject} include '${JSON.stringify(ingoredNSFilterInput)}'.`;
default:
return getUndefinedLoggingConditionMessage(subject, filterInput, filterCriteria);
}
}

const getBindingKubernetesObjectMessage = (subject: string, filterInput: FilterInput, filterCriteria?: FilterInput) => {
const kubernetesObjectFilterCriteria = filterCriteria as KubernetesObject;

switch (subject) {
case "namespaces":
return `${prefix} Binding defines ${subject} '${definedNamespaces(filterInput)}' but Object carries '${carriedNamespace(filterCriteria)}'.`;
return `${prefix} Binding defines ${subject} '${definedNamespaces(filterInput)}' but Object carries '${carriedNamespace(kubernetesObjectFilterCriteria)}'.`;
case "annotations":
return `${prefix} Binding defines ${subject} '${definedAnnotations(filterInput)}' but Object carries '${carriedName(filterCriteria)}'.`;
return `${prefix} Binding defines ${subject} '${definedAnnotations(filterInput)}' but Object carries '${carriedName(kubernetesObjectFilterCriteria)}'.`;
case "labels":
return `${prefix} Binding defines ${subject} '${definedLabels(filterInput)}' but Object carries '${carriedName(filterCriteria)}'.`;
return `${prefix} Binding defines ${subject} '${definedLabels(filterInput)}' but Object carries '${carriedName(kubernetesObjectFilterCriteria)}'.`;
case "name":
return `${prefix} Binding defines ${subject} '${definedName(filterInput)}' but Object carries '${carriedName(filterCriteria)}'.`;
return `${prefix} Binding defines ${subject} '${definedName(filterInput)}' but Object carries '${carriedName(kubernetesObjectFilterCriteria)}'.`;
case "namespace array":
return `${prefix} Object carries namespace '${carriedNamespace(filterInput)}' but namespaces allowed by Capability are '${JSON.stringify(filterCriteria)}'.`;
return `${prefix} Object carries namespace '${carriedNamespace(kubernetesObjectFilterCriteria)}' but namespaces allowed by Capability are '${JSON.stringify(definedNamespaces(filterInput))}'.`;
case "name regex":
return `${prefix} Binding defines ${subject} '${definedNameRegex(filterInput)}' but Object carries '${carriedName(filterCriteria)}'.`;
return `${prefix} Binding defines ${subject} '${definedNameRegex(filterInput)}' but Object carries '${carriedName(kubernetesObjectFilterCriteria)}'.`;
case "namespace regexes":
return `${prefix} Binding defines ${subject} '${definedNameRegex(filterInput)}' but Object carries '${carriedName(filterCriteria)}'.`;
return `${prefix} Binding defines ${subject} '${definedNameRegex(filterInput)}' but Object carries '${carriedName(kubernetesObjectFilterCriteria)}'.`;
case "deletionTimestamp":
return getDeletionTimestampLogMessage(filterInput, filterCriteria);
default:
Expand Down
7 changes: 4 additions & 3 deletions src/lib/filter/shouldSkipRequest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,9 +269,10 @@ it("should reject when kind does not match", () => {
callback,
};
const pod = CreatePod();

const actualOutput = shouldSkipRequest(binding, pod, [])
console.log(actualOutput)
expect(shouldSkipRequest(binding, pod, [])).toMatch(
/Ignoring Admission Callback: Binding defines kind '.+' but Request declares 'not set'./,
/Ignoring Admission Callback: Binding defines kind '.+' but Request declares '.+'./,
);
});

Expand All @@ -290,7 +291,7 @@ it("should reject when group does not match", () => {
const pod = CreatePod();

expect(shouldSkipRequest(binding, pod, [])).toMatch(
/Ignoring Admission Callback: Binding defines group '.+' but Request declares '.+'./,
/Ignoring Admission Callback: Binding defines group '.+' but Request declares ''./,
);
});

Expand Down
Loading