UNPKG

spartan-shield

Version:

nodejs project to package and configure common security middleware.

195 lines (192 loc) 7.09 kB
'use strict' let p = require('./policy') let pkgJson = p.read('./package.json') var nq = [{ type: 'input', name: 'appName', message: 'Q0. What is the name of the application?', default: 'Get this from package.json file' }, { type: 'list', name: 'type', message: 'Q1. Application Type : What kind of application is this? \n * Tip: How will MOST users interact with your application?', default: 1, choices: ['Desktop', 'Web', 'Mobile', 'Kiosk', 'Embedded/IoT (Controller)', 'API'] }, { type: 'input', name: 'hostname', message: "Q1.1 What is the application hostname? \n * Tip: How will users REACH your application, like: 'http://localhost:8080' or 'www.google.com'", default: 'localhost', when: function (answers) { var ask if (answers.type === 'Desktop' || answers.type === 'Embedded/IoT (Controller)') { ask = false } else { ask = true } return ask } }, { // why ask this? Because the response may change the response headers that are set on the application type: 'confirm', name: 'exposure', message: "Q2. Application Accessibility : Will the application be accessible over the Internet? \n * Tip : if this is a possibility in the future, say 'Yes'", default: true, validate: function (answers) { if (answers.exposure !== 'Y' || answers.exposure !== 'N' || answers.exposure !== 'yes' || answers.exposure !== 'no') { return 'Invalid input. Please try again.' } else { return answers.exposure } }, filter: Boolean }, { type: 'confirm', name: 'access', message: "Q3. User Sign-in : Will your application require any kind of sign-in or authentication functionality in order to utilize certain routes or services? \n * Tip : if this is a possibility in the future, say 'Yes'", default: true }, { type: 'list', name: 'sessions', message: "Q4. Sessions : Will the application have predetermined session lengths or can users be logged in indefinitely? \n * Tip : if this is a possibility in the future, say 'Yes'", default: 0, choices: ['User sessions have a set timeout', 'Users can be logged in indefinitely', 'Other session management scheme outside application'] }, { type: 'input', name: 'sessionLength', message: 'Q4.1 What is the default session length (TTL) in seconds?', default: 600, when: function (answers) { return answers.sessions === 'User sessions have a set timeout' }, filter: Number }, { type: 'confirm', name: 'secureTransport', message: "Q5. Connection Security : Does the application force secure transport (HTTPS, SSH, etc) throughout? \n * Tip : if your application responds to requests over non-secure means on any component say 'No'", default: true }, { type: 'list', name: 'content', message: "Q6. Content Acquisition : Is all of the data/content generated and processed within your application? \n * Tip : if you plan to use external APIs at any point, choose the second answer. You'll have the opportunity to specify these sources later", default: 1, choices: [ 'All of the data and content comes from sources that I own or control', "Some of the data and content comes from sources that I don't own or control" ], when: function (answers) { var ask if (answers.type === 'API' || answers.type === 'Embedded/IoT (Controller)') { ask = false } else { ask = true } return ask } }, { type: 'editor', name: 'contentSources', message: "Q6.1. Content Sources: Sweet! What are those sources? (JSON)\n * Tip: While specificity is more secure, it's also limiting. Use '*' operand for more flexible options. Use the formatting in the default", default: '{"default" : ["\'self\'"], "media" : ["\'self\'", "*.pinterest.com", "https://*.flickr.com", "ftp://video.domain.com:21"], "image" : ["\'self\'"], "style" : ["*.bootstrap.com", "https://materializecss.com", "\'self\'"], "script" : ["\'self\'"], "connect": ["http://localhost:5000", "\'self\'"], "frame" : ["\'none\'"]}', when: function (answers) { var floop = "Some of the data and content comes from sources that I don't own or control" return answers.content === floop }, filter: function (value, e) { try { return JSON.parse(value) } catch (e) { return 'Unable to successfully format this object => ' + e } } }, { type: 'confirm', name: 'forms', message: 'Q7. Forms: Will your application utilize input forms for data collection?\n * Tip : Consider collection of ratings, feedback, reviews, search, profiles etc...', default: true }, { // why ask about cache? Because some generated data and user-provided data may be considered sensitive, and we want to make sure that we DON'T cache that information type: 'confirm', name: 'cacheStrategy', message: "Q8. Caching Strategy: Do you have any intention of introducing a caching layer or using a Content Delivery Network (CDN)?\n * Tip : If this is a possibility in the future, choose 'yes'.", default: true }, { type: 'input', name: 'cacheTtl', message: 'Q8.1. Cache Time To Live (TTL): For MOST public data generated by the application, how long (in seconds) should this information be cached?\n * Tip : Shorter TTLs will require more requests of the application origin; longer TTLs may result in stale, invalid data. You can override this on a per-route basis', default: 15780000, when: function (answers) { return answers.cacheStrategy }, validate: function (value) { var valid = !isNaN(parseInt(value)) return valid || 'Please enter a number' }, filter: Number }, { type: 'input', name: 'deployment', message: 'Q9. Application Hosting : Where will application be deployed & hosted? \n * Tip : Looking for GCP, Serverless, AWS, Rackspace, Heroku or similar', default: 'locally hosted', // need a validation for this filter: String }, { type: 'input', name: 'logging', message: 'Q10. Logging and Auditing: Where will application logs be stored? (absolute path)', default: function () { if (pkgJson instanceof Error) { return `/var/log/appName` } else { return `/var/log/${pkgJson.name}/` } } }] var confirmDelete = [ { type: 'confirm', name: 'deleteConfirm', message: 'Are you sure you wish to delete the policy? This action cannot be undone\n', default: true }] var confirmDeleteForce = [ { type: 'confirm', name: 'deleteForceConfirm', message: 'Are you sure? This will not only delete the policy, but also uninstall any associated npm modules.\n', default: true }] var confirmSettings = [ { type: 'confirm', name: 'settingsConfirm', message: 'Is this ok?\n', default: true }] var restoreDefault = [ { type: 'confirm', name: 'restore', message: 'Are you sure? This will completely overwrite your configurations & restore the default policy.\n', default: true }] exports.nq = nq exports.confirmDelete = confirmDelete exports.confirmSettings = confirmSettings exports.confirmDeleteForce = confirmDeleteForce exports.restoreDefault = restoreDefault