diff --git a/backend/proto/customprotocol/customprotocol_pb.ts b/backend/proto/customprotocol/customprotocol_pb.ts index b3ba84709..df036a958 100644 --- a/backend/proto/customprotocol/customprotocol_pb.ts +++ b/backend/proto/customprotocol/customprotocol_pb.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -// @generated by protobuf-ts 2.9.3 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number +// @generated by protobuf-ts 2.9.4 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number // @generated from protobuf file "customprotocol/customprotocol.proto" (package "customprotocol", syntax proto3) // tslint:disable // @ts-nocheck diff --git a/backend/proto/flow/flow_pb.ts b/backend/proto/flow/flow_pb.ts index 71ee32986..f38312607 100644 --- a/backend/proto/flow/flow_pb.ts +++ b/backend/proto/flow/flow_pb.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -// @generated by protobuf-ts 2.9.3 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number +// @generated by protobuf-ts 2.9.4 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number // @generated from protobuf file "flow/flow.proto" (package "flow", syntax proto3) // tslint:disable // @ts-nocheck diff --git a/backend/proto/google/protobuf/any_pb.ts b/backend/proto/google/protobuf/any_pb.ts index 20c5ffd61..6fc8b85c7 100644 --- a/backend/proto/google/protobuf/any_pb.ts +++ b/backend/proto/google/protobuf/any_pb.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -// @generated by protobuf-ts 2.9.3 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number +// @generated by protobuf-ts 2.9.4 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number // @generated from protobuf file "google/protobuf/any.proto" (package "google.protobuf", syntax proto3) // tslint:disable // @ts-nocheck diff --git a/backend/proto/google/protobuf/duration_pb.ts b/backend/proto/google/protobuf/duration_pb.ts index 11d7753df..1819a1dd5 100644 --- a/backend/proto/google/protobuf/duration_pb.ts +++ b/backend/proto/google/protobuf/duration_pb.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -// @generated by protobuf-ts 2.9.3 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number +// @generated by protobuf-ts 2.9.4 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number // @generated from protobuf file "google/protobuf/duration.proto" (package "google.protobuf", syntax proto3) // tslint:disable // @ts-nocheck diff --git a/backend/proto/google/protobuf/field_mask_pb.ts b/backend/proto/google/protobuf/field_mask_pb.ts index 5265ee494..92d6a8661 100644 --- a/backend/proto/google/protobuf/field_mask_pb.ts +++ b/backend/proto/google/protobuf/field_mask_pb.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -// @generated by protobuf-ts 2.9.3 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number +// @generated by protobuf-ts 2.9.4 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number // @generated from protobuf file "google/protobuf/field_mask.proto" (package "google.protobuf", syntax proto3) // tslint:disable // @ts-nocheck diff --git a/backend/proto/google/protobuf/timestamp_pb.ts b/backend/proto/google/protobuf/timestamp_pb.ts index 6f26c0898..a320c10cc 100644 --- a/backend/proto/google/protobuf/timestamp_pb.ts +++ b/backend/proto/google/protobuf/timestamp_pb.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -// @generated by protobuf-ts 2.9.3 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number +// @generated by protobuf-ts 2.9.4 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number // @generated from protobuf file "google/protobuf/timestamp.proto" (package "google.protobuf", syntax proto3) // tslint:disable // @ts-nocheck diff --git a/backend/proto/google/protobuf/wrappers_pb.ts b/backend/proto/google/protobuf/wrappers_pb.ts index b6ac30dc7..b7a3e6208 100644 --- a/backend/proto/google/protobuf/wrappers_pb.ts +++ b/backend/proto/google/protobuf/wrappers_pb.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -// @generated by protobuf-ts 2.9.3 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number +// @generated by protobuf-ts 2.9.4 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number // @generated from protobuf file "google/protobuf/wrappers.proto" (package "google.protobuf", syntax proto3) // tslint:disable // @ts-nocheck diff --git a/backend/proto/observer/observer_pb.client.ts b/backend/proto/observer/observer_pb.client.ts index 37523c2d9..d01cf889f 100644 --- a/backend/proto/observer/observer_pb.client.ts +++ b/backend/proto/observer/observer_pb.client.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -// @generated by protobuf-ts 2.9.3 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number +// @generated by protobuf-ts 2.9.4 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number // @generated from protobuf file "observer/observer.proto" (package "observer", syntax proto3) // tslint:disable // @ts-nocheck diff --git a/backend/proto/observer/observer_pb.ts b/backend/proto/observer/observer_pb.ts index 81d41a694..dc45adfd7 100644 --- a/backend/proto/observer/observer_pb.ts +++ b/backend/proto/observer/observer_pb.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -// @generated by protobuf-ts 2.9.3 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number +// @generated by protobuf-ts 2.9.4 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number // @generated from protobuf file "observer/observer.proto" (package "observer", syntax proto3) // tslint:disable // @ts-nocheck diff --git a/backend/proto/relay/relay_pb.ts b/backend/proto/relay/relay_pb.ts index 65298727d..7cb3105fb 100644 --- a/backend/proto/relay/relay_pb.ts +++ b/backend/proto/relay/relay_pb.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -// @generated by protobuf-ts 2.9.3 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number +// @generated by protobuf-ts 2.9.4 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number // @generated from protobuf file "relay/relay.proto" (package "relay", syntax proto3) // tslint:disable // @ts-nocheck diff --git a/backend/proto/ui/notifications_pb.ts b/backend/proto/ui/notifications_pb.ts index 31d375383..2748fd69c 100644 --- a/backend/proto/ui/notifications_pb.ts +++ b/backend/proto/ui/notifications_pb.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -// @generated by protobuf-ts 2.9.3 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number +// @generated by protobuf-ts 2.9.4 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number // @generated from protobuf file "ui/notifications.proto" (package "ui", syntax proto3) // tslint:disable // @ts-nocheck diff --git a/backend/proto/ui/status_pb.ts b/backend/proto/ui/status_pb.ts index 3a26992fd..0b20784f3 100644 --- a/backend/proto/ui/status_pb.ts +++ b/backend/proto/ui/status_pb.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -// @generated by protobuf-ts 2.9.3 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number +// @generated by protobuf-ts 2.9.4 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number // @generated from protobuf file "ui/status.proto" (package "ui", syntax proto3) // tslint:disable // @ts-nocheck diff --git a/backend/proto/ui/ui_pb.client.ts b/backend/proto/ui/ui_pb.client.ts index 401861680..6c6d5160d 100644 --- a/backend/proto/ui/ui_pb.client.ts +++ b/backend/proto/ui/ui_pb.client.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -// @generated by protobuf-ts 2.9.3 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number +// @generated by protobuf-ts 2.9.4 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number // @generated from protobuf file "ui/ui.proto" (package "ui", syntax proto3) // tslint:disable // @ts-nocheck diff --git a/backend/proto/ui/ui_pb.ts b/backend/proto/ui/ui_pb.ts index af72ff70f..73559f547 100644 --- a/backend/proto/ui/ui_pb.ts +++ b/backend/proto/ui/ui_pb.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -// @generated by protobuf-ts 2.9.3 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number +// @generated by protobuf-ts 2.9.4 with parameter add_pb_suffix,eslint_disable,ts_nocheck,generate_dependencies,long_type_number // @generated from protobuf file "ui/ui.proto" (package "ui", syntax proto3) // tslint:disable // @ts-nocheck diff --git a/src/api/__mocks__/data.ts b/src/api/__mocks__/data.ts index b25049ce6..8b6a9ded6 100644 --- a/src/api/__mocks__/data.ts +++ b/src/api/__mocks__/data.ts @@ -485,5 +485,7 @@ export const flows: HubbleFlow[] = range(1000).map((): HubbleFlow => { verdict: Math.random() <= 0.5 ? Verdict.Forwarded : Verdict.Dropped, trafficDirection: Math.random() <= 0.5 ? TrafficDirection.Egress : TrafficDirection.Ingress, authType: AuthType.Disbaled, + egressAllowedBy: [], + ingressAllowedBy: [], }; }); diff --git a/src/components/FlowsTable/Sidebar.tsx b/src/components/FlowsTable/Sidebar.tsx index e30bbd3af..ee7581332 100644 --- a/src/components/FlowsTable/Sidebar.tsx +++ b/src/components/FlowsTable/Sidebar.tsx @@ -14,6 +14,7 @@ import { DnsBodyItem, IdentityEntry, PodEntry, + PolicyEntry, } from './SidebarComponents'; import css from './styles.scss'; @@ -444,6 +445,23 @@ export const FlowsTableSidebar = memo(function FlowsTableSidebar(props) { )} +
+ {flow.hasEgressAllowedBy && ( +
+ Egress allowed by policies +
+ +
+
+ )} + {flow.hasIngressAllowedBy && ( +
+ Ingress allowed by policies +
+ +
+
+ )} ); }); diff --git a/src/components/FlowsTable/SidebarComponents.tsx b/src/components/FlowsTable/SidebarComponents.tsx index e1e15432c..8cb9be27b 100644 --- a/src/components/FlowsTable/SidebarComponents.tsx +++ b/src/components/FlowsTable/SidebarComponents.tsx @@ -242,3 +242,29 @@ export const PodEntry = memo(function FlowsTableSidebarPodEntry(pr ); }); + +export interface PolicyEntryProps { + allowedBy: string[]; +} + +export const PolicyEntry = memo( + function FlowsTableSidebarLabelsEntry(props) { + return ( +
+ {props.allowedBy.map(policyName => { + return ; + })} +
+ ); + }, +); + +export interface PolicyEntryItemProps { + name: string; +} + +export const PolicyEntryItem = memo( + function FlowsTableSidebarPolicyEntry(props) { + return {props.name}; + }, +); diff --git a/src/components/FlowsTable/styles.scss b/src/components/FlowsTable/styles.scss index d36cb6b60..bc4f8f93d 100644 --- a/src/components/FlowsTable/styles.scss +++ b/src/components/FlowsTable/styles.scss @@ -237,6 +237,12 @@ } } + .policies { + .policy { + display: block; + } + } + .tcpFlags { .tcpFlag { margin-right: 5px; diff --git a/src/domain/flows/index.ts b/src/domain/flows/index.ts index eee97c0d7..4a1febf97 100644 --- a/src/domain/flows/index.ts +++ b/src/domain/flows/index.ts @@ -614,4 +614,20 @@ export class Flow { public get authTypeLabel(): string { return authtypeHelpers.toString(this.ref.authType); } + + public get hasEgressAllowedBy(): boolean { + return this.ref.egressAllowedBy.length > 0; + } + + public get hasIngressAllowedBy(): boolean { + return this.ref.ingressAllowedBy.length > 0; + } + + public get egressAllowedBy(): string[] { + return this.ref.egressAllowedBy || []; + } + + public get ingressAllowedBy(): string[] { + return this.ref.ingressAllowedBy || []; + } } diff --git a/src/domain/helpers/flows.ts b/src/domain/helpers/flows.ts index 6a5a9ecb4..c9859bc83 100644 --- a/src/domain/helpers/flows.ts +++ b/src/domain/helpers/flows.ts @@ -30,6 +30,8 @@ import * as misc from '~/domain/misc'; import * as verdictHelpers from './verdict'; import { authTypeFromPb } from './auth-type'; +const derivedFrom = 'reserved:io.cilium.policy.derived-from'; + export const hubbleFlowFromLogEntry = (entry: string | object): HubbleFlow | null => { if (entry == null) return null; @@ -83,6 +85,9 @@ export const hubbleFlowFromObj = (obj: any): HubbleFlow | null => { const trafficDirection = trafficDirectionFromStr(obj.trafficDirection); const authType = authTypeFromStr(obj.authType); + const egressAllowedBy = getNameFromPolicy(obj.getEgressAllowedByList); + const ingressAllowedBy = getNameFromPolicy(obj.getIngressAllowedByList); + return { time, verdict, @@ -104,6 +109,8 @@ export const hubbleFlowFromObj = (obj: any): HubbleFlow | null => { summary: obj.summary, trafficDirection, authType, + egressAllowedBy, + ingressAllowedBy, }; }; @@ -146,6 +153,8 @@ export const hubbleFlowFromPb = (flow: flowpb.Flow): HubbleFlow => { const destinationService = flowServiceFromPb(flow.destinationService); const trafficDirection = trafficDirectionFromPb(flow.trafficDirection); const authType = authTypeFromPb(flow.authType); + const egressAllowedBy = getNameFromPolicy(flow.egressAllowedBy); + const ingressAllowedBy = getNameFromPolicy(flow.ingressAllowedBy); return { time, @@ -168,6 +177,8 @@ export const hubbleFlowFromPb = (flow: flowpb.Flow): HubbleFlow => { summary: flow.summary, trafficDirection, authType, + egressAllowedBy: egressAllowedBy, + ingressAllowedBy: ingressAllowedBy, }; }; @@ -504,3 +515,25 @@ export const icmpv4FromPb = (icmp: flowpb.ICMPv4): ICMPv4 => { export const icmpv6FromPb = (icmp: flowpb.ICMPv6): ICMPv6 => { return icmpv4FromPb(icmp); }; + +export const getNameFromPolicy = (policies: Array): Array => { + return policies.map(policy => { + if (policy.name === '') { + const labelMap = new Map(); + policy.labels.forEach(keyValueString => { + const [key, value] = keyValueString.split('='); + labelMap.set(key, value); + }); + + // Note: We try to automatically derive the policy name if it is set. + // This is set by the policy mapstate for certain known scenarios, like allowing localhost access. + // See: https://github.com/cilium/cilium/blob/614f2ddcc8fe93aeaf463b4535dcc0f1dcc373a3/pkg/policy/mapstate.go#L42-L49 + if (labelMap.has(derivedFrom)) { + return '/' + labelMap.get(derivedFrom); + } + return '/unknown'; + } + + return policy.namespace + '/' + policy.name; + }); +}; diff --git a/src/domain/hubble.ts b/src/domain/hubble.ts index 47630746e..6f5544dc7 100644 --- a/src/domain/hubble.ts +++ b/src/domain/hubble.ts @@ -26,6 +26,8 @@ export interface HubbleFlow { readonly summary: string; readonly trafficDirection: TrafficDirection; readonly authType: AuthType; + readonly egressAllowedBy: Array; + readonly ingressAllowedBy: Array; } export interface HubbleService { diff --git a/src/testing/data/flows.ts b/src/testing/data/flows.ts index 5c553320b..fdc2b4fb6 100644 --- a/src/testing/data/flows.ts +++ b/src/testing/data/flows.ts @@ -51,6 +51,8 @@ export const icmpv4Flow: HubbleFlow = { }, trafficDirection: TrafficDirection.Ingress, authType: AuthType.Disbaled, + egressAllowedBy: [], + ingressAllowedBy: [], }; export const icmpv6Flow: HubbleFlow = { @@ -100,6 +102,8 @@ export const hubbleOne: HubbleFlow = { }, trafficDirection: TrafficDirection.Ingress, authType: AuthType.Disbaled, + egressAllowedBy: [], + ingressAllowedBy: [], }; export const hubbleNoSourceName: HubbleFlow = { diff --git a/src/testing/helpers.ts b/src/testing/helpers.ts index f4cd5952b..6d8b93ca9 100644 --- a/src/testing/helpers.ts +++ b/src/testing/helpers.ts @@ -63,6 +63,8 @@ export const flowsBetweenPods = (senderPod: string, receiverPod: string): FlowsB time: nextFlowTimestamp(), trafficDirection: TrafficDirection.Ingress, authType: AuthType.Disbaled, + egressAllowedBy: [], + ingressAllowedBy: [], }; const fromBtoA: HubbleFlow = { @@ -99,6 +101,8 @@ export const flowsBetweenPods = (senderPod: string, receiverPod: string): FlowsB time: nextFlowTimestamp(), trafficDirection: TrafficDirection.Ingress, authType: AuthType.Disbaled, + egressAllowedBy: [], + ingressAllowedBy: [], }; return { fromAtoB, fromBtoA }; @@ -139,6 +143,8 @@ export const flowsBetweenServices = (a: HubbleService, b: HubbleService): FlowsB time: nextFlowTimestamp(), trafficDirection: TrafficDirection.Ingress, authType: AuthType.Disbaled, + egressAllowedBy: [], + ingressAllowedBy: [], }; const fromBtoA: HubbleFlow = { @@ -175,6 +181,8 @@ export const flowsBetweenServices = (a: HubbleService, b: HubbleService): FlowsB time: nextFlowTimestamp(), trafficDirection: TrafficDirection.Ingress, authType: AuthType.Disbaled, + egressAllowedBy: [], + ingressAllowedBy: [], }; return { fromAtoB, fromBtoA }; @@ -225,6 +233,8 @@ export const flowsFromToService = (from: HubbleService, to: HubbleService) => { time: nextFlowTimestamp(), trafficDirection: TrafficDirection.Ingress, authType: AuthType.Disbaled, + egressAllowedBy: [], + ingressAllowedBy: [], }; const fromBtoA: HubbleFlow = { @@ -259,6 +269,8 @@ export const flowsFromToService = (from: HubbleService, to: HubbleService) => { time: nextFlowTimestamp(), trafficDirection: TrafficDirection.Ingress, authType: AuthType.Disbaled, + egressAllowedBy: [], + ingressAllowedBy: [], }; return { fromAtoB, fromBtoA };