Skip to content

Commit 5e4599c

Browse files
committed
feat: PodSpec is now read from Pods instead of the workloads
This is a workaround for cases where the workload is a Custom Resource, which snyk-monitor today does not support and cannot read them. There are situations where we will misreport the securityContext because we tried to read it from the wrong workload. The Pod's spec is an identical copy to the one defined in the workload, so we can use it for collecting the workload information that we need - this way we can track workload security configuration even if the Pods are managed by a Custom Resource.
1 parent a1ba9df commit 5e4599c

File tree

2 files changed

+26
-27
lines changed

2 files changed

+26
-27
lines changed

src/supervisor/metadata-extractor.ts

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { V1OwnerReference, V1Pod, V1Container, V1ContainerStatus } from '@kubernetes/client-node';
1+
import { V1OwnerReference, V1Pod, V1Container, V1ContainerStatus, V1PodSpec } from '@kubernetes/client-node';
22
import { IWorkload, ILocalWorkloadLocator } from '../transmitter/types';
33
import { currentClusterName } from './cluster';
44
import { IKubeObjectMetadata } from './types';
@@ -53,6 +53,7 @@ export function buildImageMetadata(
5353
}
5454

5555
async function findParentWorkload(
56+
podSpec: V1PodSpec,
5657
ownerRefs: V1OwnerReference[] | undefined,
5758
namespace: string,
5859
): Promise<IKubeObjectMetadata | undefined> {
@@ -69,9 +70,14 @@ async function findParentWorkload(
6970
}
7071

7172
const workloadReader = getWorkloadReader(supportedWorkload.kind);
72-
let nextParentMetadata: IKubeObjectMetadata | undefined;
7373
try {
74-
nextParentMetadata = await workloadReader(supportedWorkload.name, namespace);
74+
const workloadMetadata = await workloadReader(supportedWorkload.name, namespace);
75+
if (workloadMetadata === undefined) {
76+
// Could not extract data for the next parent, so return whatever we have so far.
77+
return parentMetadata;
78+
}
79+
parentMetadata = { ...workloadMetadata, podSpec };
80+
ownerReferences = parentMetadata.ownerRefs;
7581
} catch (err) {
7682
if (
7783
err &&
@@ -87,14 +93,6 @@ async function findParentWorkload(
8793
}
8894
throw err;
8995
}
90-
91-
if (nextParentMetadata === undefined) {
92-
// Could not extract data for the next parent, so return whatever we have so far.
93-
return parentMetadata;
94-
}
95-
96-
parentMetadata = nextParentMetadata;
97-
ownerReferences = parentMetadata.ownerRefs;
9896
}
9997

10098
return undefined;
@@ -151,7 +149,7 @@ export async function buildMetadataForWorkload(pod: V1Pod): Promise<IWorkload[]
151149
}
152150

153151
const podOwner: IKubeObjectMetadata | undefined = await findParentWorkload(
154-
pod.metadata.ownerReferences, pod.metadata.namespace);
152+
pod.spec, pod.metadata.ownerReferences, pod.metadata.namespace);
155153

156154
if (podOwner === undefined) {
157155
logger.info({pod}, 'pod associated with owner, but owner not found. not building metadata.');

src/supervisor/workload-reader.ts

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ import { k8sApi } from './cluster';
55
import { IKubeObjectMetadata, WorkloadKind } from './types';
66
import logger = require('../common/logger');
77

8+
type IKubeObjectMetadataWithoutPodSpec = Omit<IKubeObjectMetadata, 'podSpec'>;
89
type IWorkloadReaderFunc = (
910
workloadName: string,
1011
namespace: string,
11-
) => Promise<IKubeObjectMetadata | undefined>;
12+
) => Promise<IKubeObjectMetadataWithoutPodSpec | undefined>;
1213

1314
const deploymentReader: IWorkloadReaderFunc = async (workloadName, namespace) => {
1415
const deploymentResult = await kubernetesApiWrappers.retryKubernetesApiRequest(
@@ -22,14 +23,14 @@ const deploymentReader: IWorkloadReaderFunc = async (workloadName, namespace) =>
2223
return undefined;
2324
}
2425

25-
return {
26+
const metadata: IKubeObjectMetadataWithoutPodSpec = {
2627
kind: WorkloadKind.Deployment,
2728
objectMeta: deployment.metadata,
2829
specMeta: deployment.spec.template.metadata,
2930
ownerRefs: deployment.metadata.ownerReferences,
3031
revision: deployment.status.observedGeneration,
31-
podSpec: deployment.spec.template.spec,
3232
};
33+
return metadata;
3334
};
3435

3536
const replicaSetReader: IWorkloadReaderFunc = async (workloadName, namespace) => {
@@ -44,14 +45,14 @@ const replicaSetReader: IWorkloadReaderFunc = async (workloadName, namespace) =>
4445
return undefined;
4546
}
4647

47-
return {
48+
const metadata: IKubeObjectMetadataWithoutPodSpec = {
4849
kind: WorkloadKind.ReplicaSet,
4950
objectMeta: replicaSet.metadata,
5051
specMeta: replicaSet.spec.template.metadata,
5152
ownerRefs: replicaSet.metadata.ownerReferences,
5253
revision: replicaSet.status.observedGeneration,
53-
podSpec: replicaSet.spec.template.spec,
5454
};
55+
return metadata;
5556
};
5657

5758
const statefulSetReader: IWorkloadReaderFunc = async (workloadName, namespace) => {
@@ -66,14 +67,14 @@ const statefulSetReader: IWorkloadReaderFunc = async (workloadName, namespace) =
6667
return undefined;
6768
}
6869

69-
return {
70+
const metadata: IKubeObjectMetadataWithoutPodSpec = {
7071
kind: WorkloadKind.StatefulSet,
7172
objectMeta: statefulSet.metadata,
7273
specMeta: statefulSet.spec.template.metadata,
7374
ownerRefs: statefulSet.metadata.ownerReferences,
7475
revision: statefulSet.status.observedGeneration,
75-
podSpec: statefulSet.spec.template.spec,
7676
};
77+
return metadata;
7778
};
7879

7980
const daemonSetReader: IWorkloadReaderFunc = async (workloadName, namespace) => {
@@ -88,14 +89,14 @@ const daemonSetReader: IWorkloadReaderFunc = async (workloadName, namespace) =>
8889
return undefined;
8990
}
9091

91-
return {
92+
const metadata: IKubeObjectMetadataWithoutPodSpec = {
9293
kind: WorkloadKind.DaemonSet,
9394
objectMeta: daemonSet.metadata,
9495
specMeta: daemonSet.spec.template.metadata,
9596
ownerRefs: daemonSet.metadata.ownerReferences,
9697
revision: daemonSet.status.observedGeneration,
97-
podSpec: daemonSet.spec.template.spec,
9898
};
99+
return metadata;
99100
};
100101

101102
const jobReader: IWorkloadReaderFunc = async (workloadName, namespace) => {
@@ -109,13 +110,13 @@ const jobReader: IWorkloadReaderFunc = async (workloadName, namespace) => {
109110
return undefined;
110111
}
111112

112-
return {
113+
const metadata: IKubeObjectMetadataWithoutPodSpec = {
113114
kind: WorkloadKind.Job,
114115
objectMeta: job.metadata,
115116
specMeta: job.spec.template.metadata,
116117
ownerRefs: job.metadata.ownerReferences,
117-
podSpec: job.spec.template.spec,
118118
};
119+
return metadata;
119120
};
120121

121122
// Keep an eye on this! We need v1beta1 API for CronJobs.
@@ -133,13 +134,13 @@ const cronJobReader: IWorkloadReaderFunc = async (workloadName, namespace) => {
133134
return undefined;
134135
}
135136

136-
return {
137+
const metadata: IKubeObjectMetadataWithoutPodSpec = {
137138
kind: WorkloadKind.CronJob,
138139
objectMeta: cronJob.metadata,
139140
specMeta: cronJob.spec.jobTemplate.metadata,
140141
ownerRefs: cronJob.metadata.ownerReferences,
141-
podSpec: cronJob.spec.jobTemplate.spec.template.spec,
142142
};
143+
return metadata;
143144
};
144145

145146
const replicationControllerReader: IWorkloadReaderFunc = async (workloadName, namespace) => {
@@ -155,14 +156,14 @@ const replicationControllerReader: IWorkloadReaderFunc = async (workloadName, na
155156
return undefined;
156157
}
157158

158-
return {
159+
const metadata: IKubeObjectMetadataWithoutPodSpec = {
159160
kind: WorkloadKind.ReplicationController,
160161
objectMeta: replicationController.metadata,
161162
specMeta: replicationController.spec.template.metadata,
162163
ownerRefs: replicationController.metadata.ownerReferences,
163164
revision: replicationController.status.observedGeneration,
164-
podSpec: replicationController.spec.template.spec,
165165
};
166+
return metadata;
166167
};
167168

168169
function logIncompleteWorkload(workloadName: string, namespace: string): void {

0 commit comments

Comments
 (0)