diff --git a/README.md b/README.md index c9a3df5..13f21a7 100644 --- a/README.md +++ b/README.md @@ -83,12 +83,12 @@ proxy: + sysdig: + endpoint: ${SYSDIG_SECURE_ENDPOINT} ++ backlink: https://... # Optional override base link for backlinks. Must end in '/'. ``` - Set the environment variable `SYSDIG_SECURE_ENDPOINT` to your Sysdig Secure Endpoint. - Likewise, set `SYSDIG_SECURE_TOKEN` to your Sysdig Secure API Token. - ## How to annotate services All added annotations are available and documented in the [source file](./src/lib/annotations.ts). diff --git a/config.d.ts b/config.d.ts index 8375870..9f81334 100644 --- a/config.d.ts +++ b/config.d.ts @@ -21,5 +21,11 @@ export interface Config { * @visibility frontend */ endpoint: string; + + /** + * Custom backlink to Sysdig Secure. + * @visibility frontend + */ + backlink: string; }; } \ No newline at end of file diff --git a/package.json b/package.json index 15d6b3a..79f4058 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@sysdig/backstage-plugin-sysdig", - "version": "1.1.1", + "version": "1.2.0", "main": "dist/index.esm.js", "types": "dist/index.d.ts", "license": "Apache-2.0", diff --git a/src/components/SysdigPostureFetchComponent/SysdigPostureFetchComponent.tsx b/src/components/SysdigPostureFetchComponent/SysdigPostureFetchComponent.tsx index 98877bb..c34409b 100644 --- a/src/components/SysdigPostureFetchComponent/SysdigPostureFetchComponent.tsx +++ b/src/components/SysdigPostureFetchComponent/SysdigPostureFetchComponent.tsx @@ -59,7 +59,7 @@ import { API_PROXY_BASE_PATH, API_INVENTORY, - BACKLINK_INVENTORY + getBacklink } from '../../lib' @@ -212,8 +212,10 @@ export const DenseTable = ({ postureScans, title }: DenseTableProps) => { export const SysdigPostureFetchComponent = () => { const { entity } = useEntity(); const backendUrl = useApi(configApiRef).getString('backend.baseUrl'); - var backlink = useApi(configApiRef).getString('sysdig.endpoint') + BACKLINK_INVENTORY; + let endpoint: string | undefined = useApi(configApiRef).getOptionalString("sysdig.endpoint"); + let backlink_config: string | undefined = useApi(configApiRef).getOptionalString("sysdig.backlink"); + var backlink = getBacklink(endpoint, backlink_config, "inventory"); const annotations = entity.metadata.annotations; let uri = backendUrl + API_PROXY_BASE_PATH + API_INVENTORY; diff --git a/src/components/SysdigVMPipelineFetchComponent/SysdigVMPipelineFetchComponent.tsx b/src/components/SysdigVMPipelineFetchComponent/SysdigVMPipelineFetchComponent.tsx index d07e6dd..ce5c668 100644 --- a/src/components/SysdigVMPipelineFetchComponent/SysdigVMPipelineFetchComponent.tsx +++ b/src/components/SysdigVMPipelineFetchComponent/SysdigVMPipelineFetchComponent.tsx @@ -31,7 +31,7 @@ import { API_PROXY_BASE_PATH, API_VULN_PIPELINE, - BACKLINK_VULN_PIPELINE + getBacklink } from '../../lib' type PipelineScan = { @@ -114,7 +114,10 @@ export const DenseTable = ({ pipelineScans, title }: DenseTableProps) => { export const SysdigVMPipelineFetchComponent = () => { const { entity } = useEntity(); const backendUrl = useApi(configApiRef).getString('backend.baseUrl'); - var backlink = useApi(configApiRef).getString('sysdig.endpoint') + BACKLINK_VULN_PIPELINE; + let endpoint: string | undefined = useApi(configApiRef).getOptionalString("sysdig.endpoint"); + let backlink_config: string | undefined = useApi(configApiRef).getOptionalString("sysdig.backlink"); + + var backlink = getBacklink(endpoint, backlink_config, "vm-pipeline"); let uri = backendUrl + API_PROXY_BASE_PATH + API_VULN_PIPELINE; let filter = '?filter='; diff --git a/src/components/SysdigVMRegistryFetchComponent/SysdigVMRegistryFetchComponent.tsx b/src/components/SysdigVMRegistryFetchComponent/SysdigVMRegistryFetchComponent.tsx index 44acfe3..1b16e91 100644 --- a/src/components/SysdigVMRegistryFetchComponent/SysdigVMRegistryFetchComponent.tsx +++ b/src/components/SysdigVMRegistryFetchComponent/SysdigVMRegistryFetchComponent.tsx @@ -31,7 +31,7 @@ import { API_PROXY_BASE_PATH, API_VULN_REGISTRY, - BACKLINK_VULN_REGISTRY + getBacklink } from '../../lib' @@ -103,7 +103,10 @@ export const DenseTable = ({ registryScans, title }: DenseTableProps) => { export const SysdigVMRegistryFetchComponent = () => { const { entity } = useEntity(); const backendUrl = useApi(configApiRef).getString('backend.baseUrl'); - var backlink = useApi(configApiRef).getString('sysdig.endpoint') + BACKLINK_VULN_REGISTRY; + let endpoint: string | undefined = useApi(configApiRef).getOptionalString("sysdig.endpoint"); + let backlink_config: string | undefined = useApi(configApiRef).getOptionalString("sysdig.backlink"); + + var backlink = getBacklink(endpoint, backlink_config, "vm-registry"); let uri = backendUrl + API_PROXY_BASE_PATH + API_VULN_REGISTRY; let filter = '?filter='; diff --git a/src/components/SysdigVMRuntimeFetchComponent/SysdigVMRuntimeFetchComponent.tsx b/src/components/SysdigVMRuntimeFetchComponent/SysdigVMRuntimeFetchComponent.tsx index f343ac0..48ae70e 100644 --- a/src/components/SysdigVMRuntimeFetchComponent/SysdigVMRuntimeFetchComponent.tsx +++ b/src/components/SysdigVMRuntimeFetchComponent/SysdigVMRuntimeFetchComponent.tsx @@ -37,7 +37,7 @@ import { API_PROXY_BASE_PATH, API_VULN_RUNTIME, - BACKLINK_VULN_RUNTIME + getBacklink } from '../../lib' @@ -154,11 +154,14 @@ export const DenseTable = ({ runtimeScans, title }: DenseTableProps) => { export const SysdigVMRuntimeFetchComponent = () => { const { entity } = useEntity(); const backendUrl = useApi(configApiRef).getString('backend.baseUrl'); - var backlink = useApi(configApiRef).getString('sysdig.endpoint') + BACKLINK_VULN_RUNTIME; + let endpoint: string | undefined = useApi(configApiRef).getOptionalString("sysdig.endpoint"); + let backlink_config: string | undefined = useApi(configApiRef).getOptionalString("sysdig.backlink"); + + var backlink = getBacklink(endpoint, backlink_config, "vm-runtime"); let uri = backendUrl + API_PROXY_BASE_PATH + API_VULN_RUNTIME; let filter = '?filter='; - var name; + var names; const annotations = entity.metadata.annotations; if (annotations) { @@ -170,28 +173,28 @@ export const SysdigVMRuntimeFetchComponent = () => { var filters = [] if (SYSDIG_CLUSTER_NAME_ANNOTATION in annotations) { - name = annotations[SYSDIG_CLUSTER_NAME_ANNOTATION] - filters.push('kubernetes.cluster.name="' + name + '"'); + names = annotations[SYSDIG_CLUSTER_NAME_ANNOTATION].split(',').map(w => `"${w.trim()}"`).join(', '); + filters.push(`kubernetes.cluster.name in (${names})`); } if (SYSDIG_NAMESPACE_ANNOTATION in annotations) { - name = annotations[SYSDIG_NAMESPACE_ANNOTATION] - filters.push('kubernetes.namespace.name="' + name + '"'); + names = annotations[SYSDIG_NAMESPACE_ANNOTATION].split(',').map(w => `"${w.trim()}"`).join(', '); + filters.push(`kubernetes.namespace.name in (${names})`); } if (SYSDIG_WORKLOAD_ANNOTATION in annotations) { - name = annotations[SYSDIG_WORKLOAD_ANNOTATION] - filters.push('kubernetes.workload.name="' + name + '"'); + names = annotations[SYSDIG_WORKLOAD_ANNOTATION].split(',').map(w => `"${w.trim()}"`).join(', '); + filters.push(`kubernetes.workload.name in (${names})`); } if (SYSDIG_WORKLOAD_TYPE_ANNOTATION in annotations) { - name = annotations[SYSDIG_WORKLOAD_TYPE_ANNOTATION] - filters.push('kubernetes.workload.type="' + name + '"'); + names = annotations[SYSDIG_WORKLOAD_TYPE_ANNOTATION].split(',').map(w => `"${w.trim()}"`).join(', '); + filters.push(`kubernetes.workload.type in (${names})`); } if (SYSDIG_CONTAINER_ANNOTATION in annotations) { - name = annotations[SYSDIG_CONTAINER_ANNOTATION] - filters.push('kubernetes.pod.container.name="' + name + '"'); + names = annotations[SYSDIG_CONTAINER_ANNOTATION].split(',').map(w => `"${w.trim()}"`).join(', '); + filters.push(`kubernetes.pod.container.name in (${names})`); } if (filters.length == 0) { diff --git a/src/lib/annotations.ts b/src/lib/annotations.ts index fcaf595..8812b37 100644 --- a/src/lib/annotations.ts +++ b/src/lib/annotations.ts @@ -83,6 +83,8 @@ export const SYSDIG_SOURCE_TYPE_ANNOTATION = "sysdigcloud.com/source-type"; * Runtime */ +// Runtime annotation values also support comma separated values. Example "prod-gke,prod-eks" + // The cluster that will be included in the results. Example: "prod-gke" export const SYSDIG_CLUSTER_NAME_ANNOTATION = "sysdigcloud.com/kubernetes-cluster-name"; diff --git a/src/lib/endpoints.ts b/src/lib/endpoints.ts index 0b94701..5af273c 100644 --- a/src/lib/endpoints.ts +++ b/src/lib/endpoints.ts @@ -22,15 +22,36 @@ export const API_INVENTORY = "/api/cspm/v1/inventory/resources"; /* * Backlink paths to product */ +let DEFAULT_BACKLINK_BASE: string = "https://secure.sysdig.com/" -// Backlink path to Vulnerability Management at Runtime -export const BACKLINK_VULN_RUNTIME = "#/vulnerabilities/runtime/"; +const BACKLINKS: Record = { + // Backlink path to Vulnerability Management at Runtime + "vm-runtime": "#/vulnerabilities/runtime/", -// Backlink path to Vulnerability Management at Registry -export const BACKLINK_VULN_REGISTRY = "#/vulnerabilities/registry/"; + // Backlink path to Vulnerability Management at Registry + "vm-registry": "#/vulnerabilities/registry/", -// Backlink path to Vulnerability Management at Pipeline -export const BACKLINK_VULN_PIPELINE = "#/vulnerabilities/pipeline/"; + // Backlink path to Vulnerability Management at Pipeline + "vm-pipeline": "#/vulnerabilities/pipeline/", -// Backlink path to Inventory -export const BACKLINK_INVENTORY = "#/inventory"; \ No newline at end of file + // Backlink path to Inventory + "inventory": "#/inventory" +} + +export function getBacklink(endpoint: string | undefined, backlink: string | undefined, section: string) : string { + var backlink_base : string = DEFAULT_BACKLINK_BASE; + + if (backlink != undefined) { + backlink_base = backlink + } else if (endpoint != undefined) { + backlink_base = endpoint + } + + let backlink_section : string = BACKLINKS[section]; + + if (backlink_section === undefined) { + return ""; + } + + return backlink_base + backlink_section; +} \ No newline at end of file diff --git a/src/lib/index.ts b/src/lib/index.ts index 2887b07..4d800bd 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -53,8 +53,5 @@ export { API_VULN_REGISTRY, API_VULN_PIPELINE, API_INVENTORY, - BACKLINK_VULN_RUNTIME, - BACKLINK_VULN_REGISTRY, - BACKLINK_VULN_PIPELINE, - BACKLINK_INVENTORY + getBacklink } from './endpoints' \ No newline at end of file