@serverless/safeguards-plugin
Advanced tools
Comparing version 1.0.0 to 1.0.1
154
index.js
@@ -0,6 +1,12 @@ | ||
'use strict'; | ||
const runPolicies = require('./safeguards'); | ||
const { getApp, getDeployProfiles } = require('@serverless/platform-sdk'); | ||
const chalk = require('chalk'); | ||
const yml = require('yamljs'); | ||
class ServerlessSafeguardPlugin { | ||
constructor(sls) { | ||
constructor(sls, options) { | ||
this.sls = sls; | ||
this.options = options; | ||
this.provider = this.sls.getProvider('aws'); | ||
@@ -10,5 +16,36 @@ this.state = {}; | ||
this.beforeDeployResources = this.beforeDeployResources.bind(this); | ||
this.export = this.export.bind(this); | ||
this.commands = { | ||
safeguards: { | ||
commands: { | ||
export: { | ||
lifecycleEvents: ['export'], | ||
usage: | ||
'Generate @serverless/safeguards-plugin compatible configuration from Serverless Framework Pro Safegurds', | ||
options: { | ||
org: { | ||
usage: 'Specify the org if you do not have an org set in serverless.yml', | ||
shortcut: 'o', | ||
required: false, | ||
}, | ||
app: { | ||
usage: 'Specify the app if you do not have an app set in the serverless.yml', | ||
shortcut: 'a', | ||
required: false, | ||
}, | ||
service: { | ||
usage: 'Specify the service if you do not have a service set in the serverless.yml', | ||
shortcut: 's', | ||
required: false, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}; | ||
this.hooks = { | ||
'before:deploy:deploy': this.beforeDeployResources, | ||
'safeguards:export:export': this.export, | ||
}; | ||
@@ -20,4 +57,119 @@ } | ||
} | ||
async export() { | ||
const accessKey = process.env.SERVERLESS_ACCESS_KEY; | ||
const orgName = this.options.org || this.sls.service.org; | ||
const appName = this.options.app || this.sls.service.app; | ||
const exportedSafeguardConfig = []; | ||
if (!orgName) { | ||
this.sls.cli.log( | ||
chalk.red('You must specify an org in your serverless.yml or use the --org option') | ||
); | ||
process.exit(-1); | ||
} | ||
if (!appName) { | ||
this.sls.cli.log( | ||
chalk.red('You must specify an app in your serverless.yml or use the --app option') | ||
); | ||
process.exit(-1); | ||
} | ||
if (!accessKey) { | ||
this.sls.cli.log(chalk.red('You must set the SERVERLESS_ACCESS_KEY environment variable')); | ||
this.sls.cli.log( | ||
`You can get an access key from https://app.serverless.com/${orgName}/settings/accessKeys` | ||
); | ||
process.exit(-1); | ||
} | ||
const app = await getApp({ | ||
tenant: orgName, | ||
token: accessKey, | ||
app: appName, | ||
}); | ||
/** | ||
* The deploymentProfiles object returns {default: ..., stage: {dev:..., prod:... }} | ||
* object, so this flattens to {default:..., dev:..., prod:...} | ||
*/ | ||
const stageMapping = { | ||
default: app.deploymentProfiles.default, | ||
...app.deploymentProfiles.stages, | ||
}; | ||
let profiles = []; | ||
try { | ||
profiles = await getDeployProfiles({ | ||
accessKey, | ||
tenant: orgName, | ||
}); | ||
} catch (err) { | ||
this.sls.cli.log(chalk.red('Failed to get the deployment profile for unknown reason')); | ||
this.sls.cli.log(err); | ||
process.exit(-1); | ||
} | ||
profiles.forEach((profile) => { | ||
// | ||
/** | ||
* Identifies the stage from stageMapping based on deploymentProfile. | ||
* If the profile is not in used in one of the stages in the current | ||
* app/service, then stage will be undefined. | ||
*/ | ||
const stage = Object.keys(stageMapping).find( | ||
(profileUid) => stageMapping[profileUid] === profile.deploymentProfileUid | ||
); | ||
/** | ||
* Skip adding the policies from deployment profiles which are not | ||
* used in any of the stages in the app/service. | ||
*/ | ||
if (stage) { | ||
profile.safeguardsPolicies.forEach((policy) => { | ||
const policySetting = { | ||
title: policy.title, | ||
description: policy.description, | ||
safeguard: policy.safeguardName, | ||
enforcementLevel: policy.enforcementLevel, | ||
config: policy.safeguardConfig, | ||
}; | ||
/** | ||
* If the stage is default, then we skip setting the "stage" property. | ||
* By not defining the stage, the policy will apply to all stages. | ||
*/ | ||
if (stage !== 'default') { | ||
policySetting.stage = stage; | ||
} | ||
exportedSafeguardConfig.push(policySetting); | ||
}); | ||
} | ||
}); | ||
const content = { | ||
plugins: ['@serverless/safeguards-plugin;'], | ||
custom: { | ||
safeguards: exportedSafeguardConfig, | ||
}, | ||
}; | ||
const generatedYaml = yml.stringify(content, 10, 2); | ||
this.sls.cli.log( | ||
chalk.yellow( | ||
'To migrate safeguards from Serverless Framework Pro dashboard to the @severless/safeguards-plugin:' | ||
) | ||
); | ||
this.sls.cli.log(chalk.yellow(' 1. Add the YAML below into your serverless.yml')); | ||
this.sls.cli.log(chalk.yellow(' 2. Delete the safeguards from the deployment profiles')); | ||
this.sls.cli.log( | ||
chalk.yellow( | ||
' 3. If you are not using other SF Pro features, then you can also remove the `org` and `app` fields from serverless.com' | ||
) | ||
); | ||
this.sls.cli.log(`\n\n${chalk.reset(generatedYaml)}`); | ||
} | ||
} | ||
module.exports = ServerlessSafeguardPlugin; |
{ | ||
"name": "@serverless/safeguards-plugin", | ||
"version": "1.0.0", | ||
"version": "1.0.1", | ||
"description": "Serverless Framework Plugin for Safeguards", | ||
@@ -29,2 +29,3 @@ "main": "index.js", | ||
"dependencies": { | ||
"@serverless/platform-sdk": "^2.3.1", | ||
"chalk": "^4.1.0", | ||
@@ -31,0 +32,0 @@ "fs-extra": "^9.0.1", |
@@ -28,3 +28,3 @@ # Safeguards | ||
``` | ||
serverless plugin install --name serverless-safeguards-plugin | ||
serverless plugin install --name @serverless/safeguards-plugin | ||
``` | ||
@@ -34,3 +34,3 @@ | ||
`npm i serverless-safeguards-plugin --save-dev` | ||
`npm i @serverless/safeguards-plugin --save-dev` | ||
@@ -41,3 +41,3 @@ and add this to your `serverless.yml`: | ||
plugins: | ||
- serverless-safeguards-plugin | ||
- '@serverless/safeguards-plugin' | ||
``` | ||
@@ -154,3 +154,3 @@ | ||
plugins: | ||
- serverless-safeguards-plugin | ||
- @serverless/safeguards-plugin | ||
@@ -178,10 +178,39 @@ custom: | ||
Serverless Framework Pro also supported safeguards which you can configure in the dashboard; however, this feature has been open source and repackaged in this plugin. Here is how you can migrate your existing configuration in SF Pro to use the serverless-safeguards-plugin instead. | ||
Serverless Framework Pro safeguards have been open source and repackaged in this plugin. Here is how you can migrate your existing configuration in SF Pro to use the `@serverless/safeguards-plugin` instead. | ||
In Serverless Framework Pro, the safeguards are added to deployment profiles. Each deployment profile then can be associated with an individual stage in an app. It can also be assocaited with the _default_ stage in the app. In the serverless-safeguards-plugin, policies are added to individual services and can be configured for a subset of stages. | ||
#### How safeguards work in Serverless Framework Pro | ||
### Migration steps: | ||
- Safeguard policies are added to deployment profiles. | ||
- Each deployment profile then can be associated with an individual stage in an app. | ||
- A deployment profile can also be assocaited with the _default_ stage in the app. | ||
1. Install the `serverless-safeguard-plugin` to every project which used the Serverless Framework Pro safeguards. | ||
2. For each policy defined in the SF Pro dashboard, copy the configuration (name, description, enforcement level, config), into the `custom.safeguards` of your `serverless.yml`. The fields from the Safeguard Policies in the SF Pro dashboard match 1-1 with the fields in the serverless-safeguards-plugin, so it should be as easy as copy-pasting. | ||
#### How safeguard work in @serverless/safeguards-plugin | ||
- Safeguard policies are added to each `serverless.yml` file under `custom.safeguards`. | ||
- Safeguard policies are associated with stages by setting the `stage` field of each policy. | ||
#### Breaking change | ||
The breaking change is best described with the example below. Suppose you have an app with two stages configured, dev and prod. You also have a default | ||
stage which has some safeguard policies. | ||
- default | ||
- dev | ||
- prod | ||
In Serverless Framework Pro, if you deploy to one of the two stages (`dev` or `prod`) then the safegurad policies from the `default` stage | ||
willl NOT run. However, with `@serverless/safeguards-plugin`, you specify default policies by not setting the `stage` field, in which case, the | ||
default policies will also run. | ||
### Automatic Migration | ||
1. [Install the `@serverless/safeguard-plugin`](#installation) to every serverless.yml which uses the Serverless Framework Pro safeguards. | ||
2. Run `serverless safeguards export` from the working directory of the project. | ||
3. Copy the generated YAML into the `serverless.yml`. | ||
4. Delete the safeguards from the deployment profiles in Serverless Framework Pro. | ||
### Manually Migration | ||
1. [Install the `@serverless/safeguard-plugin`](#installation) to every serverless.yml which uses the Serverless Framework Pro safeguards. | ||
2. For each policy defined in the SF Pro dashboard, copy the configuration (name, description, enforcement level, config), into the `custom.safeguards` of your `serverless.yml`. The fields from the Safeguard Policies in the SF Pro dashboard match 1-1 with the fields in the `@serverless/safeguards-plugin`, so it should be as easy as copy-pasting. | ||
3. Set the `stage` field of each policy in `serverless.yml` to match the stage names used in the app. For example, if you had a policy `allowed-regions` in the deployment profile and it was associated with the `prod` stage, then add the field `stage: prod` to the policy in the `serverless.yml`. | ||
@@ -188,0 +217,0 @@ 4. In SF Pro you have the ability to define stages (e.g. `prod`, `qa`) or use the `default` stage. The default stage is used to enforce safeguard policies from the deployment profile on any stages that don't match the other defined stages. For example, if you have `prod` and `qa` defined, but you deploy to `feature-x`, then the policies associated with the `default` stage will be used. For these policies, do not set the `stage` field, which will cause those policies to be enforced on all stages. At the moment, there isn't a way to define a blacklist for the stages. |
@@ -26,3 +26,3 @@ 'use strict'; | ||
enforcementLevel: policy.enforcementLevel || 'error', | ||
title: policy.title || `Policy: ${safeguardName}`, | ||
title: policy.title || `Policy: ${policy.safeguard}`, | ||
description: policy.description, | ||
@@ -29,0 +29,0 @@ stage: policy.stage, |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
56075
902
599
9
6
+ Added@serverless/platform-sdk@2.3.2(transitive)
+ Addedagent-base@5.1.1(transitive)
+ Addedansi-styles@3.2.1(transitive)
+ Addedasync-limiter@1.0.1(transitive)
+ Addedbuffer-from@1.1.2(transitive)
+ Addedchalk@2.4.2(transitive)
+ Addedcolor-convert@1.9.3(transitive)
+ Addedcolor-name@1.1.3(transitive)
+ Addeddebug@4.3.7(transitive)
+ Addeddeep-extend@0.6.0(transitive)
+ Addedescape-string-regexp@1.0.5(transitive)
+ Addedhas-flag@3.0.0(transitive)
+ Addedhttps-proxy-agent@4.0.0(transitive)
+ Addedimurmurhash@0.1.4(transitive)
+ Addedini@1.3.8(transitive)
+ Addedis-docker@1.1.0(transitive)
+ Addedis-wsl@1.1.0(transitive)
+ Addedjwt-decode@2.2.0(transitive)
+ Addedminimist@1.2.8(transitive)
+ Addedms@2.1.3(transitive)
+ Addednode-fetch@2.7.0(transitive)
+ Addedopn@5.5.0(transitive)
+ Addedquerystring@0.2.1(transitive)
+ Addedramda@0.25.0(transitive)
+ Addedrc@1.2.8(transitive)
+ Addedregenerator-runtime@0.13.11(transitive)
+ Addedsignal-exit@3.0.7(transitive)
+ Addedsource-map@0.6.1(transitive)
+ Addedsource-map-support@0.5.21(transitive)
+ Addedstrip-json-comments@2.0.1(transitive)
+ Addedsupports-color@5.5.0(transitive)
+ Addedtr46@0.0.3(transitive)
+ Addeduuid@3.4.0(transitive)
+ Addedwebidl-conversions@3.0.1(transitive)
+ Addedwhatwg-url@5.0.0(transitive)
+ Addedwrite-file-atomic@2.4.3(transitive)
+ Addedws@6.2.3(transitive)