Skip to content
This repository was archived by the owner on Oct 14, 2020. It is now read-only.

Commit 3de41bb

Browse files
committed
Cascading Rules Integration Tests
1 parent c6fddbf commit 3de41bb

File tree

3 files changed

+100
-84
lines changed

3 files changed

+100
-84
lines changed

.github/workflows/ci.yaml

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,8 +440,29 @@ jobs:
440440
helm -n integration-tests install zap ./scanners/zap/ --set="parserImage.tag=sha-$(git rev-parse --short HEAD)"
441441
cd tests/integration/
442442
npx jest --ci --color zap
443-
- name: "Cascading Scans Integration Tests"
443+
- name: "cascading Scans Integration Tests"
444444
run: |
445+
# We'll run these in a separate namespace so that only the cascadingRules we want to test will be used
446+
kubectl create namespace cascading-tests
447+
# Install declarative-subsequent-scans hook
448+
helm upgrade --install dssh ./hooks/declarative-subsequent-scans/ -n cascading-tests
449+
# Install nmap
450+
helm -n cascading-tests install nmap ./scanners/nmap/ --set="parserImage.tag=sha-$(git rev-parse --short HEAD)"
451+
# Install ncrack
452+
printf "root\nadmin\n" > users.txt
453+
printf "THEPASSWORDYOUCREATED\n123456\npassword\n" > passwords.txt
454+
kubectl create secret generic --from-file users.txt --from-file passwords.txt ncrack-lists -n cascading-tests
455+
cat <<EOF | helm -n cascading-tests install ncrack ./scanners/ncrack --set="parserImage.tag=sha-$(git rev-parse --short HEAD)" --values -
456+
scannerJob:
457+
extraVolumes:
458+
- name: ncrack-lists
459+
secret:
460+
secretName: ncrack-lists
461+
extraVolumeMounts:
462+
- name: ncrack-lists
463+
mountPath: "/ncrack/"
464+
EOF
465+
# Actually run the tests
445466
cd tests/integration/
446467
npx jest --ci --color cascade
447468
- name: Inspect Post Failure

tests/integration/helpers.js

Lines changed: 61 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const k8sCRDApi = kc.makeApiClient(k8s.CustomObjectsApi);
77
const k8sBatchApi = kc.makeApiClient(k8s.BatchV1Api);
88
const k8sPodsApi = kc.makeApiClient(k8s.CoreV1Api);
99

10-
const namespace = "integration-tests";
10+
let namespace = "integration-tests";
1111

1212
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms * 1000));
1313

@@ -109,6 +109,7 @@ async function disasterRecovery(scanName) {
109109
* @returns {scan.findings} returns findings { categories, severities, count }
110110
*/
111111
async function scan(name, scanType, parameters = [], timeout = 180) {
112+
namespace ="integration-tests"
112113
const scanDefinition = {
113114
apiVersion: "execution.experimental.securecodebox.io/v1",
114115
kind: "Scan",
@@ -165,34 +166,8 @@ async function scan(name, scanType, parameters = [], timeout = 180) {
165166
* @param {number} timeout in seconds
166167
* @returns {scan.findings} returns findings { categories, severities, count }
167168
*/
168-
async function cascadingScan(name, scanType, parameters = [], nameCascade, scanTypeCascade, parametersCascade, intensive, invasive, timeout = 180) {
169-
const cascadingDefinition = {
170-
apiVersion: "cascading.experimental.securecodebox.io/v1",
171-
kind: "CascadingRule",
172-
metadata: {
173-
generateName: `${nameCascade}-`,
174-
labels: {
175-
invasive,
176-
intensive,
177-
},
178-
spec: {
179-
matches: {
180-
anyOf: {
181-
category: "Open Port",
182-
attributes: {
183-
port: 22,
184-
state: "open"
185-
}
186-
}
187-
},
188-
scanSpec: {
189-
scanTypeCascade,
190-
parametersCascade
191-
}
192-
}
193-
}
194-
};
195-
169+
async function cascadingScan(name, scanType, parameters = [], { nameCascade, matchLabels }, timeout = 180) {
170+
namespace = "cascading-tests";
196171

197172
const scanDefinition = {
198173
apiVersion: "execution.experimental.securecodebox.io/v1",
@@ -204,22 +179,12 @@ async function cascadingScan(name, scanType, parameters = [], nameCascade, scanT
204179
spec: {
205180
scanType,
206181
parameters,
182+
cascades: {
183+
matchLabels,
184+
}
207185
},
208-
cascades: {
209-
matchLabels: {
210-
intensive
211-
}
212-
}
213186
};
214187

215-
const { bodyCascade } = await k8sCRDApi.createNamespacedCustomObject(
216-
"cascading.experimental.securecodebox.io",
217-
"v1",
218-
namespace,
219-
"scans",
220-
cascadingDefinition
221-
);
222-
223188
const { body } = await k8sCRDApi.createNamespacedCustomObject(
224189
"execution.experimental.securecodebox.io",
225190
"v1",
@@ -229,7 +194,6 @@ async function cascadingScan(name, scanType, parameters = [], nameCascade, scanT
229194
);
230195

231196
const actualName = body.metadata.name;
232-
const actualNameCascade = bodyCascade.metadata.name;
233197

234198
for (let i = 0; i < timeout; i++) {
235199
await sleep(1);
@@ -238,41 +202,70 @@ async function cascadingScan(name, scanType, parameters = [], nameCascade, scanT
238202
if (status && status.state === "Done") {
239203
// Wait a couple seconds to give kubernetes more time to update the fields
240204
await sleep(2);
241-
242-
for(let j = 0; j < timeout; j++) {
243-
await sleep(1)
244-
const { statusCascade } = await getScan(actualNameCascade);
245-
if (statusCascade && statusCascade.state === "Done") {
246-
await sleep(2);
247-
const { statusCascade } = await getScan(actualNameCascade);
248-
249-
await deleteScan(actualName);
250-
await deleteScan(actualNameCascade);
251-
return statusCascade.findings;
252-
} else if (statusCascade && statusCascade.state === "Errored") {
253-
console.error("Scan Errored");
254-
await disasterRecovery(actualNameCascade);
255-
throw new Error(
256-
`Cascade Scan failed with description "${statusCascade.errorDescription}"`
257-
);
258-
}
259-
console.error("Cascade Scan Timed out!");
260-
await disasterRecovery(actualNameCascade);
261-
262-
throw new Error("timed out while waiting for cascading scan results");
263-
}
264205

206+
break;
265207
} else if (status && status.state === "Errored") {
266208
console.error("Scan Errored");
267209
await disasterRecovery(actualName);
210+
throw new Error(
211+
`Initial Scan failed with description "${status.errorDescription}"`
212+
);
213+
}
268214

215+
if (i === (timeout - 1)) {
269216
throw new Error(
270-
`Scan failed with description "${status.errorDescription}"`
217+
`Initial Scan timed out failed`
271218
);
272219
}
273220
}
274-
console.error("Scan Timed out!");
221+
222+
console.log("First Scan finished")
223+
224+
const { body: scans } = await k8sCRDApi.listNamespacedCustomObject(
225+
"execution.experimental.securecodebox.io",
226+
"v1",
227+
namespace,
228+
namespace,
229+
"scans"
230+
)
231+
232+
let cascadedScan = null;
233+
234+
for (const scan of scans.items) {
235+
if (scan.metadata.annotations && scan.metadata.annotations["cascading.securecodebox.io/chain"] === nameCascade) {
236+
cascadedScan = scan;
237+
break;
238+
}
239+
}
240+
241+
if (cascadedScan === null) {
242+
throw new Error(`Didn't find cascaded Scan for ${nameCascade}`)
243+
}
244+
const actualNameCascade = cascadedScan.metadata.name;
245+
246+
for (let j = 0; j < timeout; j++) {
247+
await sleep(1)
248+
const { status: statusCascade } = await getScan(actualNameCascade);
249+
250+
if (statusCascade && statusCascade.state === "Done") {
251+
await sleep(2);
252+
const { status: statusCascade } = await getScan(actualNameCascade);
253+
254+
await deleteScan(actualName);
255+
await deleteScan(actualNameCascade);
256+
return statusCascade.findings;
257+
} else if (statusCascade && statusCascade.state === "Errored") {
258+
console.error("Scan Errored");
259+
await disasterRecovery(actualName);
260+
await disasterRecovery(actualNameCascade);
261+
throw new Error(
262+
`Cascade Scan failed with description "${statusCascade.errorDescription}"`
263+
);
264+
}
265+
}
266+
console.error("Cascade Scan Timed out!");
275267
await disasterRecovery(actualName);
268+
await disasterRecovery(actualNameCascade);
276269

277270
throw new Error("timed out while waiting for scan results");
278271
}

tests/integration/scanner/cascade.test.js

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,27 @@ test(
77
"nmap-dummy-ssh",
88
"nmap",
99
["-Pn", "-sV", "dummy-ssh.demo-apps.svc"],
10-
"ncrack-ssh",
11-
"ncrack",
12-
["-v", "--user=root,admin", "--pass=THEPASSWORDYOUCREATED,12345", "ssh://{{location}}"],
13-
"high",
14-
"invasive",
10+
{
11+
nameCascade: "ncrack-ssh",
12+
matchLabels: {
13+
"securecodebox.io/invasive": "invasive",
14+
"securecodebox.io/intensive": "high"
15+
}
16+
},
1517
120
1618
);
1719

1820
expect(count).toBe(1);
19-
expect(categories).toEqual(
20-
{
21-
"Discovered Credentials": 1,
22-
}
23-
);
24-
expect(severities).toEqual(
25-
{
26-
"high": 1,
27-
}
28-
);
21+
expect(categories).toEqual(
22+
{
23+
"Discovered Credentials": 1,
24+
}
25+
);
26+
expect(severities).toEqual(
27+
{
28+
"high": 1,
29+
}
30+
);
2931
},
3032
3 * 60 * 1000
3133
);

0 commit comments

Comments
 (0)