{"id":15859868,"url":"https://github.com/skierkowski/serverless-safeguards-plugin","last_synced_at":"2025-07-14T13:07:08.417Z","repository":{"id":124029678,"uuid":"281706684","full_name":"skierkowski/serverless-safeguards-plugin","owner":"skierkowski","description":null,"archived":false,"fork":false,"pushed_at":"2020-07-23T02:49:34.000Z","size":95,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-06T18:19:21.931Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/skierkowski.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-07-22T14:55:36.000Z","updated_at":"2024-09-11T16:28:10.000Z","dependencies_parsed_at":null,"dependency_job_id":"1002b084-c32e-4ff8-b885-630ee3eb97ca","html_url":"https://github.com/skierkowski/serverless-safeguards-plugin","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skierkowski%2Fserverless-safeguards-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skierkowski%2Fserverless-safeguards-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skierkowski%2Fserverless-safeguards-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skierkowski%2Fserverless-safeguards-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skierkowski","download_url":"https://codeload.github.com/skierkowski/serverless-safeguards-plugin/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":237651172,"owners_count":19344670,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-05T21:40:20.558Z","updated_at":"2025-02-07T13:16:11.468Z","avatar_url":"https://github.com/skierkowski.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Safeguards\n\n**Safeguards** is a policy-as-code framework for Serverless Framework which enables you to inspect your `serverless.yml` file, and the generated Cloud Formation templates, for compliance with security, operational, and organizational, best practices. Safeguards are made available as a stand-alone Serverless Framework plugin with no external dependencies.\n\n### Highlights\n\n- **Stand-alone** - it has no external dependencies on any services.\n- **Extensible** - While the plugin comes with over a dozen policies out of the box, you can define new Safeguards and add them to your repo.\n- **Configurable** - Safeguards are implemented to accept configuration as input so you can customize the policies for each safeguard.\n- **Proactive** - Safeguards are evaluated _before_ any infrastructure is provisioned by evaluating the generated cloud formation template and serverless.yml.\n- **Environment-specific** - Policies can be associated with stages you can enforce different policies on development environments and production environments.\n\n## Docs\n\n- [Installation](#installation)\n- [Defining policies](#defining-policies)\n- [Usage](#usage)\n- [Example](#example)\n- [Migrating from Serverless Framework Pro](#migrating-from-serverless-framework-pro)\n- [Available Safeguards](#safeguards-available-with-plugin)\n- [Custom policies](#custom-policies)\n\n## Installation\n\nTo install **automatically** run this single command:\n\n```\nserverless plugin install --name serverless-safeguards-plugin\n```\n\nTo install **manually**, run this command,\n\n`npm i serverless-safeguards-plugin --save-dev`\n\nand add this to your `serverless.yml`:\n\n```yaml\nplugins:\n  - serverless-safeguards-plugin\n```\n\n## Defining Policies\n\nSafeguard policies are defined as an array in the `serverless.yml` in the `custom.safeguards` field. You can add multiple policies, and you can use the same safeguard multiple times.\n\n```yaml\ncustom:\n  safeguards:\n    - safeguard:\n      title:\n      description:\n      enforcementLevel:\n      config:\n      stage:\n```\n\n### Fields\n\n#### `title` (optional)\n\nThis is a user-readable name for the Safeguard policy. When the policy check is run in the CLI, the Safeguard policy name is used in the output.\n\n#### `description` (optional)\n\nThe description should explain the intent of the policy. When the Safeguard policy check runs in the CLI this description will be displayed if the policy check fails. It is recommended that the description provides instructions on how to resolve an issue if the service is not compliant with the policy.\n\n#### `safeguard` (required)\n\nThe Safeguard ID. There are [over a dozen safeguards made availabe with the plugin](#safeguards-available-with-plugin). Each plugin has an `ID` (e.g. `allowed-runtimes`) which is used to reference in the policy.\n\n#### `enforcementLevel` (optional, default: `error`)\n\nThe enforcement level can be set to either `warning` or `error`. When the Safeguard policy check runs in the CLI and the policy check passes, then enforcement level will have no impact on the deployment. However, if the policy check fails, then the enforcement level will control if the deployment can continue. If the enforcement level is set to `warning`, then the CLI will return a warning message but the deployment will continue. If the enforcement level is set to `error`, then the CLI will return an error message and the deployment will be blocked from continuing.\n\n#### `config`\n\nSome safeguards may allow or require configurations. For example, the [Allowed Runtimes (allowed-runtimes)](#allowed-runtimes) Safeguard requires a list of allowed AWS Lambda Runtimes for functions. This field allows you to customize the settings for the Safeguard policy.\n\n#### `path` (optional)\n\nIf using a custom policy, this references the relative path to the safeguard base directory.\n\n#### `stage` (optional)\n\nBy default a policy will run on all deployments, regardless of stage. However, if you want to scope the policy to only certain stages (e.g. `prod`), you can enforce the policy only on the selected stages. The stage field accepts string, or an array of strings, and if the current stage matches any of those, then the policy will be enforced.\n\n## Usage\n\nThe policy checks are performed as a part of the `serverless deploy` command.\nThis will load the safeguard settings from the `serverless.yml` file to\ndetermine which policies to evaluate.\n\n**Example deploy**\n\n```\n$ sls deploy\n...\nServerless: Safeguards Results:\n\n   Summary --------------------------------------------------\n\n   passed - require-dlq\n   passed - allowed-runtimes\n   passed - no-secret-env-vars\n   passed - allowed-stages\n   failed - require-cfn-role\n   passed - allowed-regions\n   passed - framework-version\n   failed - no-wild-iam-role-statements\n\n   Details --------------------------------------------------\n\n   1) Failed - no cfnRole set\n      details: https://git.io/fhpFZ\n      Require the cfnRole option, which specifies a particular role for CloudFormation to assume while deploying.\n\n\n   2) Failed - iamRoleStatement granting Resource='*'. Wildcard resources in iamRoleStatements are not permitted.\n      details: https://git.io/fjfk7\n      Prevent \"*\" permissions being used in AWS IAM Roles by checking for wildcards on Actions and Resources in grant statements.\n\n\nServerless: Safeguards Summary: 6 passed, 0 warnings, 2 errors\n...\n```\n\n### Policy check results\n\nWhen a policy check is performed, the policy can respond with a **pass**,\n**fail** or **warning**. A fail will block and prevent the deploy from\noccurring. A warning will display a message but the deploy will continue.\n\nIf one or more of the policy checks fail the command will return a 1 exit code so\nit can be detected from a script or CI/CD service.\n\n## Example\n\n```yaml\nservice: aws-node-rest-api\n\nprovider:\n  name: aws\n  runtime: nodejs12.x\n  region: us-east-1\n\nfunctions:\n  hello:\n    handler: handler.hello\n\nplugins:\n  - serverless-safeguards-plugin\n\ncustom:\n  safeguards:\n    - title: No secrets in lambda ENV VARs\n      safeguard: no-secret-env-vars\n\n    - title: Restrict regions\n      safeguard: allowed-regions\n      description: Only deployments in US regions are allowed\n      enforcementLevel: error # if this policy fails, then BLOCK the deployment\n      config: # this configures the allowed-regions safeguard\n        - us-east-1\n        - us-east-2\n        - us-west-1\n        - us-west-2\n      stage: # this policy will only be enforced if you deploy to prod or qa\n        - prod\n        - qa\n```\n\n## Migrating from Serverless Framework Pro\n\nServerless 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.\n\nIn 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.\n\n### Migration steps:\n\n1. Install the `serverless-safeguard-plugin` to every project which used the Serverless Framework Pro safeguards.\n2. 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.\n3. 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`.\n4. 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.\n\n# Safeguards available with plugin\n\nThe following policies are included and configurable in the [Serverless\nFramework Dashboard](https://app.serverless.com/).\n\n### No \"\\*\" in IAM Role statements\n\n**ID: no-wild-iam-role-statements**\n\nThis policy performs a simple check to prevent \"\\*\" permissions being used in\nAWS IAM Roles by checking for wildcards on Actions and Resources in grant\nstatements.\n\n#### Resolution\n\nUpdate the [custom IAM Roles](https://serverless.com/framework/docs/providers/aws/guide/iam#custom-iam-roles)\nin the `serverless.yml` to remove IAM Role Statements which grant access to \"\\*\"\non Actions and Resources. If a plugin generates IAM Role Statements, follow the\ninstructions provided by the plugin developer to mitigate the issue.\n\n### No clear-text credentials in environment variables\n\n**ID: no-secret-env-vars**\n\nEnsures that the [environment variables configured on the AWS Lambda functions](https://serverless.com/framework/docs/providers/aws/guide/functions#environment-variables)\ndo not contain environment variables values which follow patterns of common\ncredential formats.\n\n#### Resolution\n\nResolving this issue requires that the AWS Lambda function environment variables\ndo not contain any plain-text credentials; however, your functions may still\nrequire those credentials to be passed in by other means.\n\nThere are two recommended alternatives of passing in credentials to your AWS\nLambda functions:\n\n- **SSM Parameter Store**: The article \"[You should use SSM Parameter Store over Lambda env variables](https://hackernoon.com/you-should-use-ssm-parameter-store-over-lambda-env-variables-5197fc6ea45b)\"\n  by Yan Cui provides a detailed explanation for using the SSM Parameters in your\n  Serverless Framework service to save and retrieve credentials.\n- **KMS Encryption**: Encrypt the environment variables using [KMS Keys](https://serverless.com/framework/docs/providers/aws/guide/functions#kms-keys).\n\n### Ensure Dead Letter Queues are attached to functions\n\n**ID: require-dlq**\n\nEnsures all functions with any of the events listed below, or functions with\nzero events, have an attached [Dead Letter Queue](https://docs.aws.amazon.com/lambda/latest/dg/dlq.html).\n\n**Events:**\n\n- s3\n- sns\n- alexaSkill\n- iot\n- cloudwachEvent\n- cloudwatchLog\n- cognitoUserPool\n- alexaHomeSkill\n\n#### Resolution\n\nConfigure the [Dead Letter Queue with SNS or SQS](https://serverless.com/framework/docs/providers/aws/guide/functions#dead-letter-queue-dlq)\nfor all the functions which require the DLQ to be configured.\n\n### Allowed Runtimes\n\n**ID: allowed-runtimes**\n\nThis limits the runtimes that can be used in services. It is configurable with a list of allowed\nruntimes or a regular expression.\n\n```yaml\n- nodejs8.10\n- python3.7\n# or:\nnode.*\n```\n\n#### Resolution\n\nEnsure you are using a runtime that is in the list of allowed runtimes or matches the regex of\nallowed runtimes.\n\n### Allowed stages\n\n**ID: allowed-stages**\n\nThis limits the stages that can be used in services. It is configurable with a list of allowed\nstages or a regular expression.\n\n```yaml\n- prod\n- dev\n# or:\n'(prod|qa|dev-.*)'\n```\n\n#### Resolution\n\nEnsure you are using a runtime that is in the list of allowed stages or matches the regex of\nallowed stages.\n\n### Framework Version\n\n**ID: framework-version**\n\nThis policy limits which versions of the Serverless Framework can be used. It is configured with a\n[semver](https://semver.org/) expression.\n\n```yaml\n\u003e=1.44.0 \u003c2.0.0\n```\n\n#### Resolution\n\nInstall an allowed version of the framework: `npm i -g serverless@$ALLOWED_VERSION`\n\n### Require Cloudformation Deployment Role\n\n**ID: require-cfn-role**\n\nThis rule requires you to specify the\n[`cfnRole` option](https://serverless.com/framework/docs/providers/aws/guide/serverless.yml/)\nin your `serverless.yml`. It has no\nconfiguration options.\n\n#### Resolution\n\nAdd `cfnRole` to your `serverless.yml`.\n\n### Required stack tags\n\n**ID: required-stack-tags**\n\nThis rule requires you to specify certain tags in the\n[`stackTags` option](https://serverless.com/framework/docs/providers/aws/guide/serverless.yml/)\nin your `serverless.yml`. It is configured with a mapping of keys to regex's. All the keys must be\npresent and value must match the regex.\n\n```yaml\nsomeTagName: '.*'\n```\n\n### Require Global VPC\n\n**ID: require-global-vpc**\n\nThis rule requires all your functions to be configured with a VPC. By default they are required to\nhave at least two subnet IDs to allow for AZ failover. It is configurable with a `minNumSubnets`\noption:\n\n```yaml\nminNumSubnets: 1 # if you don't want to require 2 and AZ support\n```\n\n#### Resolution\n\nAdd a global VPC configuration to your config:\nhttps://serverless.com/framework/docs/providers/aws/guide/functions/#vpc-configuration\n\n### Allowed function names\n\n**ID: allowed-function-names**\n\nThis rule allows you enforce naming conventions functions deployed to AWS lambda.\nIt is configured with a regular expression. It features one extra addition: variables for stage,\nservice and function(the key in the serverless yaml) names. See below for some examples.\n\nRequire using Serverless's standard naming scheme:\n\n```\n${SERVICE}-${STAGE}-${FUNCTION}\n```\n\nOr, if you want custom names with stage first and underscores instead of dashes:\n\n```\n${STAGE}_${SERVICE}_${FUNCTION}\n```\n\n#### Resolution\n\nUse the `name:` config option on the function object to customize the deployed function name to\nmatch the regex: https://serverless.com/framework/docs/providers/aws/guide/functions/#configuration\n\n### Require Description\n\n**ID: require-description**\n\nThis rule requires that all functions have a description of minimum or maximum length. By default\nit requires a minimum length of 30 and the lambda maximum of 256. Both these values are\nconfigurable however. Here is a config that requires a slightly longer config but doesn't allow as\nlong a maximum:\n\n```yaml\nminLength: 50\nmaxLength: 100\n```\n\n#### Resolution\n\nAdd a function description to all your lambdas that is with in the minimum and maximum required\nlengths.\n\n### Allowed Regions\n\n**ID: allowed-regions**\n\nThis rule allows you to restrict the regions to which a service may be deployed. It is configured\nwith a list of regions:\n\n```yaml\n# eg, us-east-1 and us-west-2 only\n- us-east-1\n- us-west-2\n```\n\n### Restricted deploy times\n\n**ID: restricted-deploy-times**\n\nThis policy blocks deploys at certain times. It is configured with a list of objects containing a\ntime, duration and optional interval.\n\n```yaml\n# no deploy specific holidays, eg Rosh Hashanah 2019\n- time: 2019-09-29T18:20 # ISO8601 date or datetime\n  duration: P2D30M # IS8601 duration\n# no deploy a specific day but repeating, eg all future Christmases\n- time: 2019-12-25\n  duration: P1D\n  interval: P1Y\n# no deploy fri noon - monday 6AM\n- time: 2019-03-08T12:00:00\n  duration: P2D18H\n  interval: P1W\n```\n\nIf you only need to specify one interval you can also directly use that object, eg:\n\n```yaml\n# no deployments on friday, saturday, sunday\ntime: 2019-03-08\nduration: P3D\ninterval: P1W\n```\n\n#### Resolution\n\nWait! You're not supposed to be deploying!\n\n### Forbid S3 HTTP Access\n\n**ID: forbid-s3-http-access**\n\nThis policy requires that you have a `BucketPolicy` forbidding access over HTTP for each bucket.\nThere are no configuration options.\n\n#### Resolution\n\nFor a bucket without a name such as the `ServerlessDeploymentBucket` ensure that the `resources`\nsection of your serverless yaml contains a policy like the following using `Ref`s.\nIf using a different bucket, update the logical name in the `Ref`.\n\n```yaml\nresources:\n  Resources:\n    ServerlessDeploymentBucketPolicy:\n      Type: 'AWS::S3::BucketPolicy'\n      Properties:\n        Bucket: { Ref: ServerlessDeploymentBucket }\n        PolicyDocument:\n          Statement:\n            - Action: 's3:*'\n              Effect: 'Deny'\n              Principal: '*'\n              Resource:\n                Fn::Join:\n                  - ''\n                  - - 'arn:aws:s3:::'\n                    - Ref: ServerlessDeploymentBucket\n                    - '/*'\n              Condition:\n                Bool:\n                  aws:SecureTransport: false\n```\n\nIf using a bucket with a name, say configured in the `custom` section of your config, use a policy\nlike this:\n\n```yaml\nresources:\n  Resources:\n    NamedBucketPolicy:\n      Type: 'AWS::S3::BucketPolicy'\n      Properties:\n        Bucket: ${self:custom.bucketName}\n        PolicyDocument:\n          Statement:\n            - Action: 's3:*'\n              Effect: 'Deny'\n              Principal: '*'\n              Resource: 'arn:aws:s3:::${self:custom.bucketName}/*'\n              Condition:\n                Bool:\n                  aws:SecureTransport: false\n```\n\n# Custom Policies\n\nIn addition to built-in policies, you can add custom policies to your application.\n\n## Creating a custom service policy\n\nA service policy is simply a Javascript packaged in a module export which you can use in the\nServerless Framework project for your service. To start with a custom policy first create a\ndirectory in your working directory (e.g. `./policies`) to store the policy files.\n\nCreate a single JS file to define your policy (e.g. `my-custom-policy.js`) in the\npolicies directory.\n\n**./policies/my-custom-policy.js**\n\n```javascript\nmodule.exports = function myCustomPolicy(policy, service) {\n  // policy.fail(“Configuration is not compliant with policy”)\n  policy.approve();\n};\n```\n\nThere are two primary methods you can use to control the behavior of the policy checks\nwhen running the `deploy` command.\n\n- `approve()` - Passes the policy to allow the deploy to continue.\n- `fail(message)` - Fails the policy check and returns an failure message.\n\nTo define the policy method you’ll need to inspect the configuration. The entire\nconfiguration is made available in the service object. Use the [default policies](https://github.com/serverless/enterprise-plugin/tree/master/src/lib/safeguards/policies)\nand [example policies](https://github.com/serverless/enterprise-plugin/tree/master/examples/safeguards-example-service/policies)\nas reference to the content of the service object.\n\n### Enabling a custom policy\n\nOnce the policy is implemented and saved in the directory, add the `safeguards`\nblock to the `serverless.yml` file and set the `location` property to reference\nthe relative path of the policies directory. To enable the policy you must also\nadd it to the list of policies.\n\n**serverless.yml**\n\n```yaml\ncustom:\n  safeguards:\n    - title: Require stage name in table name\n      safeguard: stage-in-table-name\n      path: ./policies\n```\n\n### Adding settings to your policy\n\nCustom policies may also include configuration parameters. The policy function\naccepts a third parameter (`options` in the example below) which contains the\nsettings defined in the `serverless.yml` file.\n\n**./policies/my-custom-policy.js**\n\n```javascript\nmodule.exports = function myCustomPolicy(policy, service, options) {\n  // options.max = 2\n  policy.approve();\n};\n```\n\n**serverless.yml**\n\n```yaml\ncustom:\n  safeguards:\n    - title: my custom policy\n      safeguard: my-custom-policy\n      path: ./policies\n      config:\n        max: 2\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskierkowski%2Fserverless-safeguards-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskierkowski%2Fserverless-safeguards-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskierkowski%2Fserverless-safeguards-plugin/lists"}