From 00d96e1b7812444f66a2f1bbf4200a8f82c8e6df Mon Sep 17 00:00:00 2001 From: counter Date: Wed, 18 Jan 2023 19:38:48 -0800 Subject: [PATCH] switching screenshots to the cloud --- app.js | 92 +++++++++++++++++++++++++++++++++------------- docker-compose.yml | 2 + package.json | 1 + 3 files changed, 69 insertions(+), 26 deletions(-) diff --git a/app.js b/app.js index 5be57c2..41cff02 100644 --- a/app.js +++ b/app.js @@ -1,4 +1,5 @@ const bodyParser = require('body-parser'); +const { Storage } = require('@google-cloud/storage'); const express = require('express'); const fs = require('fs'); const zlib = require('zlib'); @@ -212,17 +213,34 @@ async function get_app_server() { // When the "finish" event is called we delete the original // uncompressed image file left behind by multer. - input_read_stream.pipe(gzip).pipe(output_gzip_stream).on('finish', async (error) => { - if(error) { - console.error(`An error occurred while writing the XSS payload screenshot (gzipped) to disk:`); - console.error(error); - } + if (process.env.USE_CLOUD_STORAGE == "true"){ + const storage = new Storage(); + //creating a bucket instance + const bucket = storage.bucket(process.env.BUCKET_NAME); + //compressing the file using gzip + const gzip = zlib.createGzip(); + //uploading the gzipped file to GCS + await bucket.upload(input_read_stream.pipe(gzip), { + gzip: true, + destination: payload_fire_image_filename, + metadata: { + cacheControl: 'public, max-age=31536000', + }, + }); + console.log(`${fileName} has been uploaded to GCS.`); + await asyncfs.unlink(multer_temp_image_path); + }else{ + input_read_stream.pipe(gzip).pipe(output_gzip_stream).on('finish', async (error) => { + if(error) { + console.error(`An error occurred while writing the XSS payload screenshot (gzipped) to disk:`); + console.error(error); + } - console.log(`Gzip stream complete, deleting multer temp file: ${multer_temp_image_path}`); - - await asyncfs.unlink(multer_temp_image_path); - }); + console.log(`Gzip stream complete, deleting multer temp file: ${multer_temp_image_path}`); + await asyncfs.unlink(multer_temp_image_path); + }); + } const payload_fire_id = uuid.v4(); var payload_fire_data = { id: payload_fire_id, @@ -264,6 +282,9 @@ async function get_app_server() { }); app.get('/screenshots/:screenshotFilename', async (req, res) => { + if (! req.session.authenticated === true){ + res.status(401).send('Unauthorized'); + } const screenshot_filename = req.params.screenshotFilename; // Come correct or don't come at all. @@ -272,25 +293,44 @@ async function get_app_server() { } const gz_image_path = `${SCREENSHOTS_DIR}/${screenshot_filename}.gz`; - - const image_exists = await check_file_exists(gz_image_path); + + if (process.env.USE_CLOUD_STORAGE == "true"){ + const storage = new Storage(); + + const bucket = storage.bucket(process.env.BUCKET_NAME); - if(!image_exists) { - return res.sendStatus(404); - } + const file = bucket.file(gz_image_path); + try { + // Download the gzipped image + const [image] = await file.download(); + // Send the gzipped image in the response + res.set('Content-Encoding', 'gzip'); + res.set('Content-Type', 'application/gzip'); + res.send(image); + } catch (error) { + console.error(error); + res.status(404).send(`Error retrieving image from GCS`); + } + }else{ + const image_exists = await check_file_exists(gz_image_path); - // Return the gzipped image file with the appropriate - // Content-Encoding header, should be widely supported. - res.sendFile(gz_image_path, { - // Why leak anything you don't have to? - lastModified: false, - acceptRanges: false, - cacheControl: true, - headers: { - "Content-Type": "image/png", - "Content-Encoding": "gzip" - } - }) + if(!image_exists) { + return res.sendStatus(404); + } + + // Return the gzipped image file with the appropriate + // Content-Encoding header, should be widely supported. + res.sendFile(gz_image_path, { + // Why leak anything you don't have to? + lastModified: false, + acceptRanges: false, + cacheControl: true, + headers: { + "Content-Type": "image/png", + "Content-Encoding": "gzip" + } + }) + } }); diff --git a/docker-compose.yml b/docker-compose.yml index f00f47c..eed8745 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -48,6 +48,8 @@ services: - DATABASE_PASSWORD=xsshunterexpress - DATABASE_HOST=postgresdb - NODE_ENV=production + - USE_CLOUD_STORAGE=true + - BUCKET_NAME=YourBucket ports: - "80:80" - "443:443" diff --git a/package.json b/package.json index e0d8fe4..d9f41a7 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@nvanexan/node-client-sessions": "^0.8.0", "bcrypt": "^5.0.1", "cors": "^2.8.5", + "@google-cloud/storage": "^6.9.0", "express": "^4.17.1", "express-jsonschema": "^1.1.6", "greenlock-express": "^4.0.3",