Skip to content

Commit f97dcb7

Browse files
authored
Merge pull request #669 from snyk/feat/load-rego-policy
feat: load user-defined Rego rules for workload auto-import
2 parents 5ed47de + 423d23d commit f97dcb7

File tree

11 files changed

+137
-3
lines changed

11 files changed

+137
-3
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"prepare": "npm run build",
2121
"build": "tsc",
2222
"dev": "tsc-watch --project tsconfig.json --onSuccess 'node --inspect .'",
23-
"debug": "tsc-watch --project tsconfig.json --onSuccess 'node --inspect --debug-brk .'",
23+
"debug": "tsc-watch --project tsconfig.json --onSuccess 'node --inspect-brk .'",
2424
"lint": "eslint \"src/**/*.ts\" && (cd test && eslint \"**/*.ts\")"
2525
},
2626
"author": "snyk.io",

snyk-monitor-deployment.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ spec:
3434
mountPath: "/srv/app/certs"
3535
- name: registries-conf
3636
mountPath: "/srv/app/.config/containers"
37+
- name: workload-policies
38+
mountPath: "/var/tmp/policies"
3739
env:
3840
- name: SNYK_INTEGRATION_ID
3941
valueFrom:
@@ -115,4 +117,8 @@ spec:
115117
configMap:
116118
name: snyk-monitor-registries-conf
117119
optional: true
120+
- name: workload-policies
121+
configMap:
122+
name: snyk-monitor-workload-policies
123+
optional: true
118124
serviceAccountName: snyk-monitor

snyk-monitor/templates/deployment.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ spec:
4949
mountPath: "/var/tmp"
5050
- name: ssl-certs
5151
mountPath: "/srv/app/certs"
52+
- name: workload-policies
53+
mountPath: "/var/tmp/policies"
54+
readOnly: true
5255
- name: registries-conf
5356
mountPath: "/srv/app/.config/containers"
5457
env:
@@ -114,6 +117,10 @@ spec:
114117
configMap:
115118
name: {{ .Values.certsConfigMap }}
116119
optional: true
120+
- name: workload-policies
121+
configMap:
122+
name: {{ .Values.workloadPoliciesMap }}
123+
optional: true
117124
- name: registries-conf
118125
configMap:
119126
name: {{ .Values.registriesConfConfigMap }}

snyk-monitor/values.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
monitorSecrets: snyk-monitor
88
certsConfigMap: snyk-monitor-certs
99
registriesConfConfigMap: snyk-monitor-registries-conf
10+
workloadPoliciesMap: snyk-monitor-workload-policies
1011

1112
# One of: Cluster, Namespaced
1213
# Cluster - creates a ClusterRole and ClusterRoleBinding with the ServiceAccount

src/common/policy.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { existsSync, readFile } from 'fs';
2+
import { resolve as resolvePath } from 'path';
3+
import { promisify } from 'util';
4+
5+
import { logger } from './logger';
6+
import { constructWorkloadAutoImportPolicy } from '../transmitter/payload';
7+
import { sendWorkloadAutoImportPolicy } from '../transmitter';
8+
import { config } from './config';
9+
10+
const readFileAsync = promisify(readFile);
11+
12+
export async function loadAndSendWorkloadAutoImportPolicy(): Promise<void> {
13+
try {
14+
/** This path is set in snyk-monitor during installation/deployment and is defined in the Helm chart. */
15+
const userProvidedRegoPolicyPath = resolvePath(
16+
config.IMAGE_STORAGE_ROOT,
17+
'policies',
18+
'workload-auto-import.rego',
19+
);
20+
if (!existsSync(userProvidedRegoPolicyPath)) {
21+
logger.info({}, 'Rego policy file does not exist, skipping loading');
22+
return;
23+
}
24+
25+
const regoPolicy = await readFileAsync(userProvidedRegoPolicyPath, 'utf8');
26+
const payload = constructWorkloadAutoImportPolicy(regoPolicy);
27+
await sendWorkloadAutoImportPolicy(payload);
28+
} catch (err) {
29+
logger.error({ err }, 'Unexpected error occurred while loading workload auto-import policy');
30+
}
31+
}

src/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { config } from './common/config';
77
import { logger } from './common/logger';
88
import { currentClusterName } from './supervisor/cluster';
99
import { beginWatchingWorkloads } from './supervisor/watchers';
10+
import { loadAndSendWorkloadAutoImportPolicy } from './common/policy';
1011

1112
process.on('uncaughtException', (err) => {
1213
if (state.shutdownInProgress) {
@@ -58,4 +59,9 @@ function monitor(): void {
5859

5960
SourceMapSupport.install();
6061
cleanUpTempStorage();
61-
monitor();
62+
63+
// Allow running in an async context
64+
setImmediate(async function setUpAndMonitor(): Promise<void> {
65+
await loadAndSendWorkloadAutoImportPolicy();
66+
monitor();
67+
});

src/transmitter/index.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
IRequestError,
1111
ScanResultsPayload,
1212
IDependencyGraphPayload,
13+
WorkloadAutoImportPolicyPayload,
1314
} from './types';
1415
import { getProxyAgent } from './proxy';
1516

@@ -69,6 +70,30 @@ export async function sendWorkloadMetadata(payload: IWorkloadMetadataPayload): P
6970
}
7071
}
7172

73+
export async function sendWorkloadAutoImportPolicy(payload: WorkloadAutoImportPolicyPayload): Promise<void> {
74+
try {
75+
logger.info(
76+
{ userLocator: payload.userLocator, cluster: payload.cluster, agentId: payload.agentId },
77+
'attempting to send workload auto-import policy',
78+
);
79+
80+
const { response, attempt } = await retryRequest('post', `${upstreamUrl}/api/v1/policy`, payload);
81+
if (!isSuccessStatusCode(response.statusCode)) {
82+
throw new Error(`${response.statusCode} ${response.statusMessage}`);
83+
}
84+
85+
logger.info(
86+
{ userLocator: payload.userLocator, cluster: payload.cluster, agentId: payload.agentId, attempt },
87+
'workload auto-import policy sent upstream successfully',
88+
);
89+
} catch (error) {
90+
logger.error(
91+
{ error, userLocator: payload.userLocator, cluster: payload.cluster, agentId: payload.agentId },
92+
'could not send workload auto-import policy',
93+
);
94+
}
95+
}
96+
7297
export async function deleteWorkload(payload: IDeleteWorkloadPayload): Promise<void> {
7398
try {
7499
const {response, attempt} = await retryRequest('delete', `${upstreamUrl}/api/v1/workload`, payload);

src/transmitter/payload.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
IKubernetesMonitorMetadata,
1313
ScanResultsPayload,
1414
IDependencyGraphPayload,
15+
WorkloadAutoImportPolicyPayload,
1516
} from './types';
1617

1718
export function constructDepGraph(
@@ -125,3 +126,14 @@ export function constructDeleteWorkload(
125126
agentId: config.AGENT_ID,
126127
};
127128
}
129+
130+
export function constructWorkloadAutoImportPolicy(
131+
policy: string,
132+
): WorkloadAutoImportPolicyPayload {
133+
return {
134+
policy,
135+
userLocator: config.INTEGRATION_ID,
136+
cluster: currentClusterName,
137+
agentId: config.AGENT_ID,
138+
};
139+
}

src/transmitter/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,13 @@ export interface IDeleteWorkloadPayload {
6161
agentId: string;
6262
}
6363

64+
export interface WorkloadAutoImportPolicyPayload {
65+
userLocator: string;
66+
cluster: string;
67+
agentId: string;
68+
policy: string;
69+
}
70+
6471
export interface IWorkload {
6572
type: string;
6673
name: string;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package snyk
2+
3+
default workload_auto_import = false

0 commit comments

Comments
 (0)