Skip to content

Commit

Permalink
frontend: support negative flow filter
Browse files Browse the repository at this point in the history
  • Loading branch information
paxnil authored and geakstr committed Feb 7, 2023
1 parent a1a3ba3 commit 25d6297
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 29 deletions.
79 changes: 77 additions & 2 deletions src/api/grpc/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,80 @@ export const buildBlacklistFlowFilters = (filters?: Filters): FlowFilter[] => {
blDstLocalDnsFilter.addDestinationFqdn('*.cluster.local*');
blFilters.push(blSrcLocalDnsFilter, blDstLocalDnsFilter);

const blSrcIps: string[] = [];
const blDstIps: string[] = [];
const blSrcIdentities: number[] = [];
const blDstIdentities: number[] = [];
const blSrcPods: string[] = [];
const blDstPods: string[] = [];
filters?.filters
?.filter(filter => filter.negative)
.forEach(filter => {
const { kind, query } = filter;
switch (kind) {
case FilterKind.Label: {
filter.fromRequired && blSrcLabelsFilter.addSourceLabel(query);
filter.toRequired && blDstLabelsFilter.addDestinationLabel(query);
break;
}
case FilterKind.Ip: {
filter.fromRequired && blSrcIps.push(filter.query);
filter.toRequired && blDstIps.push(filter.query);
break;
}
case FilterKind.Dns: {
filter.fromRequired && blSrcLocalDnsFilter.addSourceFqdn(query);
filter.toRequired && blDstLocalDnsFilter.addDestinationFqdn(query);
break;
}
case FilterKind.Identity: {
filter.fromRequired && blSrcIdentities.push(+query);
filter.toRequired && blDstIdentities.push(+query);
break;
}
case FilterKind.Pod: {
filter.fromRequired && blSrcPods.push(query);
filter.toRequired && blDstPods.push(query);
}
}
});

if (blSrcIps.length) {
const blSrcIpFilter: FlowFilter = new FlowFilter();
blSrcIps.forEach(e => blSrcIpFilter.addSourceIp(e));
blFilters.push(blSrcIpFilter);
}

if (blDstIps.length) {
const blDstIpFilter: FlowFilter = new FlowFilter();
blSrcIps.forEach(e => blDstIpFilter.addDestinationIp(e));
blFilters.push(blDstIpFilter);
}

if (blSrcIdentities.length) {
const blSrcIdentityFilter: FlowFilter = new FlowFilter();
blSrcIdentities.forEach(e => blSrcIdentityFilter.addSourceIdentity(e));
blFilters.push(blSrcIdentityFilter);
}

if (blDstIdentities.length) {
const blDstIdentityFilter: FlowFilter = new FlowFilter();
blDstIdentities.forEach(e => blDstIdentityFilter.addDestinationIdentity(e));
blFilters.push(blDstIdentityFilter);
}

if (blSrcPods.length) {
const blSrcPodFilter: FlowFilter = new FlowFilter();
blSrcPods.forEach(e => blSrcPodFilter.addSourcePod(e));
blFilters.push(blSrcPodFilter);
}

if (blDstPods.length) {
const blDstPodFilter: FlowFilter = new FlowFilter();
blDstPods.forEach(e => blDstPodFilter.addDestinationPod(e));
blFilters.push(blDstPodFilter);
}

return blFilters;
};

Expand Down Expand Up @@ -206,7 +280,8 @@ export const buildFlowFilters = (filters: Filters): FlowFilters => {
const wlFilters: FlowFilter[] = [];
const blFilters = buildBlacklistFlowFilters(filters);

if (!filters.filters?.length) {
const postiveEntries = filters.filters?.filter(filter => !filter.negative);
if (!postiveEntries?.length) {
const namespace = filters?.namespace;
if (namespace) {
const wlSrcFilter = baseWhitelistFilter(filters);
Expand All @@ -220,7 +295,7 @@ export const buildFlowFilters = (filters: Filters): FlowFilters => {
return [wlFilters, blFilters];
}

filters.filters.forEach(filter => {
postiveEntries.forEach(filter => {
wlFilters.push(...filterEntryWhitelistFilters(filters, filter));
});

Expand Down
5 changes: 5 additions & 0 deletions src/components/TopBar/FlowsFilterInput.scss
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@
display: block;
}

.negative {
color: #d00;
margin: 0 2px;
}

.kind {
color: #3b3c42;
}
Expand Down
1 change: 1 addition & 0 deletions src/components/TopBar/FlowsFilterInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ function tagRenderer(item: FilterEntry | null) {
<div className={css.tag}>
<TagDirection direction={item.direction} />
<span className={css.body}>
{item.negative && <span className={css.negative}>!</span>}
<span className={css.kind}>{item.kind}</span>
<span className={css.separator}>=</span>
<span className={css.query}>{query}</span>
Expand Down
12 changes: 12 additions & 0 deletions src/domain/filtering/__tests__/filter-entry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const parse = (
dir: FilterDirection,
kind: FilterKind,
query: string,
negative = false,
) => {
test(testName, () => {
const e = FilterEntry.parse(s);
Expand All @@ -17,6 +18,7 @@ const parse = (
expect(e!.kind).toBe(kind);
expect(e!.direction).toBe(dir);
expect(e!.query).toBe(query);
expect(e!.negative).toBe(negative);
});
};

Expand Down Expand Up @@ -182,4 +184,14 @@ describe('correct strings parsing', () => {
FilterKind.Pod,
'random',
);

parse(
'correct 20',
'!pod=random',
true,
FilterDirection.Both,
FilterKind.Pod,
'random',
true,
);
});
28 changes: 22 additions & 6 deletions src/domain/filtering/filter-entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export interface Params {
kind: Kind;
direction: Direction;
query: string;
negative?: boolean;
meta?: string;
}

Expand All @@ -28,9 +29,13 @@ export class FilterEntry {
public kind: Kind;
public direction: Direction;
public query: string;
public negative: boolean;
public meta?: string;

public static parseFull(userInput: string): FilterEntry | null {
const negative: boolean = userInput[0] === '!';
if (negative) userInput = userInput.substring(1);

let [rawDirection] = userInput.split(':');
rawDirection = rawDirection || '';

Expand All @@ -48,10 +53,12 @@ export class FilterEntry {
const query = FilterEntry.parseQuery(kind, rawQuery);
if (!query) return null;

return new FilterEntry({ kind, direction, query });
return new FilterEntry({ kind, direction, query, negative });
}

public static parse(userInput: string): FilterEntry | null {
const negative: boolean = userInput[0] === '!';
if (negative) userInput = userInput.substring(1);
if (userInput.length === 0) return null;

let kind: Kind = Kind.Label;
Expand All @@ -73,7 +80,7 @@ export class FilterEntry {
parts = kindWithQuery.split('=');
if (parts.length < 2) {
query = FilterEntry.parseQuery(kind, parts[0] || '');
return new FilterEntry({ kind, direction, query });
return new FilterEntry({ kind, direction, query, negative });
}

const [rawKind, ...secondRest] = parts;
Expand All @@ -86,7 +93,7 @@ export class FilterEntry {
}

query = FilterEntry.parseQuery(kind, rest.join('='));
return new FilterEntry({ kind, direction, query });
return new FilterEntry({ kind, direction, query, negative });
}

public static parseDirection(s: string): Direction | null {
Expand Down Expand Up @@ -187,10 +194,11 @@ export class FilterEntry {
});
}

constructor({ kind, direction, query, meta }: Params) {
constructor({ kind, direction, query, negative, meta }: Params) {
this.kind = kind;
this.query = query;
this.direction = direction;
this.negative = negative || false;
this.meta = meta;
}

Expand Down Expand Up @@ -225,14 +233,17 @@ export class FilterEntry {
}

public toString(): string {
return `${this.direction}:${this.kind}=${this.query}`;
return `${this.negative ? '!' : ''}${this.direction}:${this.kind}=${
this.query
}`;
}

public clone(): FilterEntry {
return new FilterEntry({
kind: this.kind,
direction: this.direction,
query: this.query,
negative: this.negative,
meta: this.meta,
});
}
Expand All @@ -241,7 +252,8 @@ export class FilterEntry {
return (
this.kind === rhs.kind &&
this.direction === rhs.direction &&
this.query === rhs.query
this.query === rhs.query &&
this.negative == rhs.negative
);
}

Expand Down Expand Up @@ -293,6 +305,10 @@ export class FilterEntry {
return this.bothRequired;
}

public get isNegative(): boolean {
return this.negative;
}

public get labelKeyValue(): [string, string] {
const [key, ...rest] = this.query.split('=');

Expand Down
18 changes: 9 additions & 9 deletions src/domain/filtering/filter-flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,14 @@ export const filterFlow = (flow: Flow, filters: Filters): boolean => {
if (rangeSign === '-' && flow.httpStatus > httpStatus) return false;
}

let ok = !filters.filters?.length;
filters.filters?.forEach((ff: FilterEntry) => {
const passed = filterFlowByEntry(flow, ff);

ok = ok || passed;
});

return ok;
const filtered = filters.filters?.some(
ff => ff.negative && !filterFlowByEntry(flow, ff),
);
return filtered
? false
: !!filters.filters?.some(
ff => !ff.negative && filterFlowByEntry(flow, ff),
);
};

export const filterFlowByEntry = (flow: Flow, filter: FilterEntry): boolean => {
Expand Down Expand Up @@ -108,5 +108,5 @@ export const filterFlowByEntry = (flow: Flow, filter: FilterEntry): boolean => {
}
}

return fromOk || toOk;
return filter.negative !== (fromOk || toOk);
};
25 changes: 13 additions & 12 deletions src/domain/filtering/filter-link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ export const filterLink = (link: Link, filters: Filters): boolean => {

if (link.isDNSRequest && filters.skipKubeDns) return false;

let ok = !filters.filters?.length;
filters.filters?.forEach((ff: FilterEntry) => {
const passed = filterLinkByEntry(link, ff);

ok = ok || passed;
});

return ok;
const filtered = filters.filters?.some(
ff => ff.negative && !filterLinkByEntry(link, ff),
);
return filtered
? false
: !!filters.filters?.some(
ff => !ff.negative && filterLinkByEntry(link, ff),
);
};

export const filterLinkByEntry = (l: Link, e: FilterEntry): boolean => {
Expand All @@ -32,7 +32,8 @@ export const filterLinkByEntry = (l: Link, e: FilterEntry): boolean => {
case FilterDirection.Both: {
switch (e.kind) {
case FilterKind.Identity: {
if (!sourceIdentityMatch && !destIdentityMatch) return false;
if (!sourceIdentityMatch && !destIdentityMatch)
return e.negative !== false;
break;
}
}
Expand All @@ -41,7 +42,7 @@ export const filterLinkByEntry = (l: Link, e: FilterEntry): boolean => {
case FilterDirection.To: {
switch (e.kind) {
case FilterKind.Identity: {
if (!destIdentityMatch) return false;
if (!destIdentityMatch) return e.negative !== false;
break;
}
}
Expand All @@ -50,13 +51,13 @@ export const filterLinkByEntry = (l: Link, e: FilterEntry): boolean => {
case FilterDirection.From: {
switch (e.kind) {
case FilterKind.Identity: {
if (!sourceIdentityMatch) return false;
if (!sourceIdentityMatch) return e.negative !== false;
break;
}
}
break;
}
}

return true;
return !e.negative;
};

0 comments on commit 25d6297

Please sign in to comment.