Skip to content

Commit 95418b9

Browse files
FLS-448 Malware virus scanning for client side file upload (#195)
* Malware scanning for client side file upload * Fix e2e test to have malware detection changes * Disable Virus scan capability in local development but enable in e2e * Adding in-progress state till file gets the tag * Change endpoint into POST to a check and delete file based on the tag from guard duty * Addressing review comments * Adding .env to get AWS params * Sonar fix
1 parent de23a20 commit 95418b9

File tree

14 files changed

+245
-57
lines changed

14 files changed

+245
-57
lines changed

.github/workflows/copilot_deploy.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,11 @@ jobs:
295295
- name: Start containers
296296
run: docker compose -f docker-compose.e2e.yml up -d
297297

298+
- name: Add localstack to /etc/hosts
299+
run: |
300+
echo "127.0.0.1 localhost localstack host.docker.internal" | sudo tee -a /etc/hosts
301+
cat /etc/hosts
302+
298303
- name: Create S3 bucket
299304
run: docker exec localstack /bin/sh -c "awslocal s3api create-bucket --bucket fsd-bucket --create-bucket-configuration LocationConstraint=eu-west-2 --region eu-west-2"
300305

copilot/fsd-form-runner-adapter/manifest.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ variables:
7171
SINGLE_REDIS: true
7272
JWT_AUTH_COOKIE_NAME: "fsd_user_token"
7373
JWT_AUTH_ENABLED: true
74+
ENABLE_VIRUS_SCAN: true
7475
LOG_PRETTY_PRINT: false
7576

7677
secrets:

docker-compose.e2e.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ services:
4444
- SINGLE_REDIS=true
4545
- FORM_RUNNER_ADAPTER_REDIS_INSTANCE_URI=redis://redis-data:6379
4646
- PREVIEW_MODE=true
47+
- ENABLE_VIRUS_SCAN=true
4748
command: yarn runner start:test
4849
logging:
4950
driver: "json-file"

e2e-test/cypress.config.js

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ const {defineConfig} = require("cypress");
22
const webpack = require("@cypress/webpack-preprocessor");
33
const preprocessor = require("@badeball/cypress-cucumber-preprocessor");
44
const path = require("path");
5+
const AWS = require('aws-sdk');
6+
const dotenv = require("dotenv");
7+
dotenv.config({ path: path.resolve(__dirname, "../docker-localstack/.awslocal.env") });
58

69

710
console.log("****************** starting e2e ******************")
8-
console.log(`e2e entry : [${path.resolve(__dirname, "../digital-form-builder/e2e")}]\n`)
911

1012
async function setupNodeEvents(on, config) {
1113
// This is required for the preprocessor to be able to generate JSON reports after each run, and more,
@@ -33,6 +35,45 @@ async function setupNodeEvents(on, config) {
3335
},
3436
})
3537
);
38+
39+
on('task', {
40+
async tagAllS3Objects({ tags }) {
41+
console.log('tagAllS3Objects task started with tags:', tags);
42+
const s3 = new AWS.S3({
43+
endpoint: process.env.AWS_ENDPOINT_OVERRIDE,
44+
s3ForcePathStyle: true,
45+
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
46+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
47+
region: process.env.AWS_DEFAULT_REGION,
48+
});
49+
try {
50+
const listedObjects = await s3.listObjectsV2({ Bucket: 'fsd-bucket' }).promise();
51+
if (!listedObjects.Contents || listedObjects.Contents.length === 0) {
52+
const msg = `No objects found in bucket fsd-bucket`;
53+
console.log(msg);
54+
return msg;
55+
}
56+
const taggingPromises = listedObjects.Contents.map((obj) => {
57+
console.log(`Tagging object: ${obj.Key}`);
58+
return s3.putObjectTagging({
59+
Bucket: 'fsd-bucket',
60+
Key: obj.Key,
61+
Tagging: {
62+
TagSet: Object.entries(tags).map(([Key, Value]) => ({ Key, Value })),
63+
},
64+
}).promise();
65+
});
66+
await Promise.all(taggingPromises);
67+
const successMsg = `${listedObjects.Contents.length} object(s) in fsd-bucket tagged successfully.`;
68+
console.log(successMsg);
69+
return successMsg;
70+
} catch (error) {
71+
console.error("Error tagging S3 objects:", error);
72+
throw error;
73+
}
74+
},
75+
});
76+
3677
// Make sure to return the config object as it might have been modified by the plugin
3778
return config;
3879
}

e2e-test/cypress/e2e/runner/clientSideFileUpload.feature

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ Feature: Client Side File Upload
1313
And I continue
1414
Then I see the error "Test Client Side file Upload is required" for "Upload the independent survey of works" component with problem title
1515

16-
@wip
1716
Scenario: Adding a single file into the client side file upload
1817
And the form session will be initiated with the given component type "text" key "clientSideFileUploadField1" title "Upload the independent survey of works" answer "" question "Upload the independent survey of works" and finally form "client-side-file-upload-single" and session "045a5791-1d76-45e6-a926-7d4ff26b4113"
1918
| form | redirectPath |
@@ -33,5 +32,12 @@ Feature: Client Side File Upload
3332
When I upload the file "passes.png" wait till upload
3433
Then I see the error "Test Client Side file Upload requires 2 files" for "Upload the independent survey of works" component with problem title
3534

36-
35+
Scenario: Adding a single file into the client side file upload with a virus
36+
And the form session will be initiated with the given component type "text" key "clientSideFileUploadField1" title "Upload the independent survey of works" answer "" question "Upload the independent survey of works" and finally form "client-side-file-upload-single" and session "045a5791-1d76-45e6-a926-7d4ff26b4113"
37+
| form | redirectPath |
38+
| client-side-file-upload-single | / |
39+
And I go to the initialised session URL with generated token
40+
And I continue
41+
When I upload the file "passes.png" with virus then wait till upload
42+
Then I see the error "The selected file contains a virus" for "Upload the independent survey of works" component with problem title
3743

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
import {When} from "@badeball/cypress-cucumber-preprocessor";
22

33
When("I upload the file {string} wait till upload", (filename) => {
4-
cy.get("input[type=file]").attachFile(filename);
5-
cy.wait(2000)
6-
cy.findByRole("button", {name: /continue/i}).click();
4+
cy.get("input[type=file]").attachFile(filename, { force: true });
5+
cy.wait(5000);
6+
const tags = {
7+
GuardDutyMalwareScanStatus: 'NO_THREATS_FOUND'
8+
};
9+
cy.task('tagAllS3Objects', { tags }).then(() => {
10+
cy.wait(5000);
11+
cy.log('tagAllS3Objects task completed');
12+
cy.findByRole("button", { name: /continue/i }).click();
13+
});
714
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import {When} from "@badeball/cypress-cucumber-preprocessor";
2+
3+
When("I upload the file {string} with virus then wait till upload", (filename) => {
4+
cy.get("input[type=file]").attachFile(filename);
5+
cy.wait(5000);
6+
const tags = {
7+
GuardDutyMalwareScanStatus: 'THREATS_FOUND'
8+
};
9+
cy.task('tagAllS3Objects', { tags }).then(() => {
10+
cy.wait(5000);
11+
cy.log('tagAllS3Objects task completed');
12+
});
13+
});

runner/config/custom-environment-variables.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,5 +69,6 @@
6969
"ignoreSectionsFromSummary": "IGNORE_SECTIONS_FROM_SUMMARY_PAGE",
7070
"sentryDsn": "SENTRY_DSN",
7171
"sentryTracesSampleRate": "SENTRY_TRACES_SAMPLE_RATE",
72-
"copilotEnv": "COPILOT_ENV"
72+
"copilotEnv": "COPILOT_ENV",
73+
"enableVirusScan": "ENABLE_VIRUS_SCAN"
7374
}

runner/config/default.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,5 +112,7 @@ module.exports = {
112112
/*sentry configurations*/
113113
sentryDsn: "",
114114
sentryTracesSampleRate: "",
115-
copilotEnv: ""
115+
copilotEnv: "",
116+
117+
enableVirusScan: false,
116118
};

runner/locales/cy.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"filePartiallyUploadError": "Nid yw'r ffeiliau wedi'u llwytho i fyny yn llawn",
2525
"fileUploadSizeError": "Rhaid i'r ffeil fod o dan ",
2626
"fileUploadCombinedSizeError": "Rhaid i faint ffeiliau cyfun fod o dan ",
27+
"fileUploadVirusError": "The selected file contains a virus",
2728
"fileUploadTypeError": "Ni allwch uwchlwytho ffeiliau o'r math hwn.",
2829
"fileUploadCountSingleError": "Dim ond un ffeil y gallwch ei uwchlwytho",
2930
"fileUploadCountMaxError": "Dim ond ffeiliau {maxFiles} y gallwch chi eu huwchlwytho",
@@ -52,6 +53,7 @@
5253
"fileActionCol": "Gweithredu",
5354
"fileActionComplete": "Cyflawn",
5455
"fileActionFailed": "Wedi methu",
56+
"fileActionInProgress": "In progress",
5557
"deleteBtn": "Dileu"
5658
}
5759
},

0 commit comments

Comments
 (0)