{"id":13530781,"url":"https://github.com/stelligent/cfn_nag","last_synced_at":"2025-05-14T01:07:05.970Z","repository":{"id":4238438,"uuid":"51515624","full_name":"stelligent/cfn_nag","owner":"stelligent","description":"Linting tool for CloudFormation templates","archived":false,"fork":false,"pushed_at":"2024-08-01T23:27:46.000Z","size":1501,"stargazers_count":1274,"open_issues_count":82,"forks_count":212,"subscribers_count":31,"default_branch":"master","last_synced_at":"2025-04-17T17:39:43.042Z","etag":null,"topics":["amazon","aws","cfn","cfn-nag","cloudformation","cloudformation-security","cloudformation-templates","compliance","continuous-testing","devops","hacktoberfest","iam-rules","lint","linting","open-source","security","security-automation","static-analysis","stelligent","unit-testing"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stelligent.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-02-11T13:15:25.000Z","updated_at":"2025-04-17T00:53:08.000Z","dependencies_parsed_at":"2023-07-06T14:02:08.245Z","dependency_job_id":"532035f5-8c0d-416d-a454-2453e0315d4c","html_url":"https://github.com/stelligent/cfn_nag","commit_stats":{"total_commits":622,"total_committers":52,"mean_commits":"11.961538461538462","dds":0.652733118971061,"last_synced_commit":"8b5f03da74202ba323a145e9d037ddce6cab9dec"},"previous_names":[],"tags_count":350,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stelligent%2Fcfn_nag","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stelligent%2Fcfn_nag/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stelligent%2Fcfn_nag/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stelligent%2Fcfn_nag/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stelligent","download_url":"https://codeload.github.com/stelligent/cfn_nag/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250366726,"owners_count":21418771,"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":["amazon","aws","cfn","cfn-nag","cloudformation","cloudformation-security","cloudformation-templates","compliance","continuous-testing","devops","hacktoberfest","iam-rules","lint","linting","open-source","security","security-automation","static-analysis","stelligent","unit-testing"],"created_at":"2024-08-01T07:00:55.159Z","updated_at":"2025-05-14T01:07:05.936Z","avatar_url":"https://github.com/stelligent.png","language":"Ruby","funding_links":[],"categories":["\u003ca id=\"7e840ca27f1ff222fd25bc61a79b07ba\"\u003e\u003c/a\u003e特定目标","Infrastructure as code security","Tools","Ruby","Инструменты","\u003ca id=\"c71ad1932bbf9c908af83917fe1fd5da\"\u003e\u003c/a\u003eAWS","security","Open Source Repos","Other","Authoring and Testing Tools"],"sub_categories":["\u003ca id=\"c71ad1932bbf9c908af83917fe1fd5da\"\u003e\u003c/a\u003eAWS","Infrastructure as Code Analysis","IAC Security","\u003ca id=\"0476f6b97e87176da0a0d7328f8747e7\"\u003e\u003c/a\u003eblog","CloudFormation","Hooks"],"readme":"\u003cimg src=\"logo.png?raw=true\" width=\"150\"\u003e\n\u003cbr/\u003e\n\n![cfn_nag](https://github.com/stelligent/cfn_nag/workflows/cfn_nag/badge.svg)\n\n# Background\n\nThe cfn-nag tool looks for patterns in CloudFormation templates that may indicate insecure infrastructure.\nRoughly speaking, it will look for:\n\n* IAM rules that are too permissive (wildcards)\n* Security group rules that are too permissive (wildcards)\n* Access logs that aren't enabled\n* Encryption that isn't enabled\n* Password literals\n\nFor more background on the tool, please see this post at Stelligent's blog:\n\n[Finding Security Problems Early in the Development Process of a CloudFormation Template with \"cfn-nag\"](https://stelligent.com/2016/04/07/finding-security-problems-early-in-the-development-process-of-a-cloudformation-template-with-cfn-nag/)\n\n# Installation\n\n## Gem Install\n\nPresuming Ruby \u003e= 2.5.x is installed, installation is just a matter of:\n\n```bash\ngem install cfn-nag\n```\n\n## Brew Install\n\nOn MacOS or Linux you can alternatively install with brew:\n\n```bash\nbrew install ruby brew-gem\nbrew gem install cfn-nag\n```\n\n# CodePipeline\n\nTo run `cfn_nag` as an action in CodePipeline, you can deploy via the [AWS Serverless Application Repository](https://serverlessrepo.aws.amazon.com/applications/us-east-1/275155842945/cfn-nag-pipeline).\n\n# Usage\n\nTo execute:\n\n```bash\ncfn_nag_scan --input-path \u003cpath to cloudformation json\u003e\n```\n\nThe path can be a directory or a particular template.  If it is a directory, all `.json,` `.template`, `.yml` and `.yaml` files will be processed, including recursing into subdirectories.\n\nThe default output format is free-form text, but json output can be selected with the `--output-format json` flag.\n\nOptionally, a `--debug` flag will dump information about the internals of rule loading.\n\nRun with `--help` for a full listing of supported switches.\n\nTo see a list of all the rules cfn-nag currently supports, there is a command-line utility that will dump them to stdout:\n\n```bash\ncfn_nag_rules\n```\n\n## Results\n\n* The results are dumped to stdout\n* A failing violation will return a non-zero exit code.\n* A warning will return a zero/success exit code.\n* A fatal violation stops analysis (per file) because the template is malformed in some severe way\n\n## Running in Docker\n\nA Dockerfile is provided for convenience. It is published on DockerHub as `stelligent/cfn_nag`.\n\n\u003chttps://hub.docker.com/r/stelligent/cfn_nag\u003e\n\nYou can also build it locally.\n\n```bash\ndocker build -t stelligent/cfn_nag .\n```\n\nYou can mount a local directory containing templates into the Docker container and then call cfn_nag in the container. This example uses the test templates used in unit testing cfn_nag:\n\n```bash\n$ docker run -v `pwd`/spec/test_templates:/templates -t stelligent/cfn_nag /templates/json/efs/filesystem_with_encryption.json\n{\n  \"failure_count\": 0,\n  \"violations\": [\n\n  ]\n}\n$ docker run -v `pwd`/spec/test_templates:/templates -t stelligent/cfn_nag /templates/json/efs/filesystem_with_no_encryption.json\n{\n  \"failure_count\": 1,\n  \"violations\": [\n    {\n      \"id\": \"F27\",\n      \"type\": \"FAIL\",\n      \"message\": \"EFS FileSystem should have encryption enabled\",\n      \"logical_resource_ids\": [\n        \"filesystem\"\n      ]\n    }\n  ]\n}\n```\n\n## Running as a GitHub Action\n\n`cfn_nag_scan` can be run as part of a GitHub Workflow to evaluate code during continuous integration pipelines.\n\nIn your GitHub Workflow file, create a step which uses the cfn_nag Action:\n\n```yaml\n- name: Simple test\n  uses: stelligent/cfn_nag@master\n  with:\n    input_path: tests\n```\n\nMore information about the [GitHub Action can be found here](github-action/README.md).\n\n## Results Filtering\n\n### Profiles\n\ncfn-nag supports the notion of a \"profile\" which is effectively an allow list of rules to apply.  The profile is a text file\nthat must contain a rule identifier per line.  When specified via the `--profile-path` command line argument,\ncfn-nag will ONLY return violations from those particular rules.\n\nThe motivation behind creating a \"profile\" is that different developers might care about different rules.  For example, an\n\"infrastructure_developer\" might care about IAM rules, while an \"app_developer\" might not even be able to create\nIAM resources and therefore not care about those rules.\n\nHere is an example profile:\n\n```text\nF1\nF2\nF27\nW3\nW5\n```\n\n### Global Deny List\n\nThe deny list is basically the opposite of the profile: it's a list of rules to NEVER apply.  When specified via the\n`--deny-list-path` command line argument, cfn-nag will NEVER return violations from those particular rules specified\nin the file.\n\nIn case a rule is specified in both, the deny list will take priority over the profile, and the rule will not be applied.\n\nThe format is as follows.  The only two salient fields are `RulesToSuppress` and the `id` per item.  The `reason` won't\nbe interpreted by cfn-nag, but it is recommended to justify and document why the rule should never be applied.\n\n```yaml\nRulesToSuppress:\n- id: W3\n  reason: W3 is something we never care about at enterprise X\n```\n\n### Per-Resource Rule Suppression\n\nIn the event that there is a rule that you want to suppress, a `cfn_nag` `Metadata` key can be added to the affected resource to tell cfn_nag to not raise a failure or warning for that rule.\n\nFor example, if you are setting up a public-facing ELB that's open to inbound connections from the internet with resources like the following:\n\n`public_alb.yaml`\n\n```yaml\n# Partial template\nPublicAlbSecurityGroup:\n  Properties:\n    GroupDescription: 'Security group for a public Application Load Balancer'\n    VpcId:\n      Ref: vpc\n  Type: AWS::EC2::SecurityGroup\nPublicAlbSecurityGroupHttpIngress:\n  Properties:\n    CidrIp: 0.0.0.0/0\n    FromPort: 80\n    GroupId:\n      Ref: PublicAlbSecurityGroup\n    IpProtocol: tcp\n    ToPort: 80\n  Type: AWS::EC2::SecurityGroupIngress\n```\n\ncfn_nag will raise warnings like the following:\n\n```bash\n$ cfn_nag_scan -i public_alb.yaml\n------------------------------------------------------------\npublic_alb.yaml\n------------------------------------------------------------------------------------------------------------------------\n| WARN W9\n|\n| Resources: [\"PublicAlbSecurityGroup\"]\n|\n| Security Groups found with ingress cidr that is not /32\n------------------------------------------------------------\n| WARN W2\n|\n| Resources: [\"PublicAlbSecurityGroup\"]\n|\n| Security Groups found with cidr open to world on ingress.  This should never be true on instance.  Permissible on ELB\n\nFailures count: 0\nWarnings count: 2\n```\n\nBy adding the metadata, these warnings can be suppressed:\n\n`public_alb_with_suppression.yaml`\n\n```yaml\n# Partial template\nPublicAlbSecurityGroup:\n  Properties:\n    GroupDescription: 'Security group for a public Application Load Balancer'\n    VpcId:\n      Ref: vpc\n  Type: AWS::EC2::SecurityGroup\n  Metadata:\n    cfn_nag:\n      rules_to_suppress:\n        - id: W9\n          reason: \"This is a public facing ELB and ingress from the internet should be permitted.\"\n        - id: W2\n          reason: \"This is a public facing ELB and ingress from the internet should be permitted.\"\nPublicAlbSecurityGroupHttpIngress:\n  Properties:\n    CidrIp: 0.0.0.0/0\n    FromPort: 80\n    GroupId:\n      Ref: PublicAlbSecurityGroup\n    IpProtocol: tcp\n    ToPort: 80\n  Type: AWS::EC2::SecurityGroupIngress\n```\n\n```bash\n$ cfn_nag_scan -i public_alb_with_suppression.yaml\n------------------------------------------------------------\npublic_alb_with_supression.yaml\n------------------------------------------------------------\nFailures count: 0\nWarnings count: 0\n```\n\n# Setting Template Parameter Values\n\nCloudFormation Template Parameters can present a problem for static analysis as the values are specified at the point\nof deployment.  In other words, the values aren't available when the static analysis is done - static analysis\ncan only look at the \"code\" that is in front of it.  Therefore a security group ingress rule of 0.0.0.0/0 won't\nbe flagged if the cidr is parameterized and the 0.0.0.0/0 is passed in at deploy time.\n\nTo allow for checking parameter values, a user can specify the parameter values in a JSON file passed on the command line\nto both `cfn_nag` and `cfn_nag_scan` with the `--parameter-values-path=\u003cfilename/uri\u003e` flag.\n\nThe format of the JSON is a single key, \"Parameters\", whose value is a dictionary with each key/value pair mapping to\nthe Parameters:\n\n```json\n{\n  \"Parameters\": {\n    \"Cidr\": \"0.0.0.0/0\"\n  }\n}\n```\n\nThis will provide \"0.0.0.0/0\" to the following Parameter:\n\n```yaml\nParameters:\n  Cidr:\n    Type: String\n```\n\n_BEWARE_ that if there are extra parameters in the JSON, they are quietly ignored (to allow `cfn_nag_scan` to apply\nthe same JSON across all the templates).\n\nIf the JSON is malformed or doesn't meet the above specification, then parsing will fail with a FATAL violation.\n\n# Mappings\n\nPrior to 0.5.55, calls to Fn::FindInMap were effectively ignored.  The underlying model would\nleave them be, and so they would appear as Hash values to rules.  For example: `{ \"Fn::FindInMap\" =\u003e [map1, key1, key2]}`\n\nStarting in 0.5.55, the model will attempt to compute the value for a call to FindInMap and present that value to the\nrules.  This evaluation supports keys that are:\n\n* static text\n* references to parameters (with parameter substitution)\n* references to AWS pseudofunctions (see next section)\n* nested maps\n\nIf the evaluation logic can't figure out the value for a key, it will default to the old behavior of returning the\nHash for the whole expression.\n\n## AWS Pseudofunctions\n\nAlso prior to 0.5.55, calls to AWS pseudofunctions were effectively ignored.  The underlying model would\nleave them be, and so they would appear as Hash values to rules.  For example: `{\"Ref\"=\u003e\"AWS::Region\"}`.\nA common use case is to organize mappings by region, so pseudofunction evaluation is important to better supporting\nmap evaluation.\n\nStarting in 0.5.55, the model will present the following AWS pseudofunctions to rules with the default values:\n\n```text\n'AWS::URLSuffix' =\u003e 'amazonaws.com',\n'AWS::Partition' =\u003e 'aws',\n'AWS::NotificationARNs' =\u003e '',\n'AWS::AccountId' =\u003e '111111111111',\n'AWS::Region' =\u003e 'us-east-1',\n'AWS::StackId' =\u003e 'arn:aws:cloudformation:us-east-1:111111111111:stack/stackname/51af3dc0-da77-11e4-872e-1234567db123',\n'AWS::StackName' =\u003e 'stackname'\n```\n\nAdditionally, the end user can override the value supplied via the traditional parameter substitution mechanism.  For example:\n\n```json\n{\n  \"Parameters\": {\n    \"AWS::Region\": \"eu-west-1\"\n  }\n}\n```\n\n# Controlling the Behavior of Conditions\n\nUp until version 0.4.66 of cfn_nag, the underlying model did not do any processing of Fn::If within a template.  This meant that if a property had a conditional value, it was up to the rule to parse the Fn::If.  Given that an Fn::If could appear just about anywhere, it created a whack-a-mole situation for rule developers.  At best, the rule logic could ignore values that were Hash presuming the value wasn't a Hash in the first place.\n\nIn order to address this issue, the default behavior for cfn_nag is now to substitute Fn::If with the true outcome.  This means by default that rules will not inspect the false outcomes for security violations.\n\nIn addition to substituting Fn::If at the property value level, the same behavior is applied to Fn::If at the top-level of Properties.  For example:\n\n```yaml\nResource1:\n  Type: Foo\n  Properties: !If\n    - IsNone\n    - Description: Up\n    - Description: DOwn\n```\n\nWill look the same as:\n\n```yaml\nResource1:\n  Type: Foo\n  Properties:\n    Description: Up\n```\n\nTo provide some control over this behavior, a user can specify the condition values in a JSON file passed on the command line\nto both `cfn_nag` and `cfn_nag_scan` with the `--condition-values-path=\u003cfilename/uri\u003e` flag.\n\nThe format of the JSON is a a dictionary with each key/value pair mapping to the Conditions:\n\n```json\n{\n  \"Condition1\": true,\n  \"Condition2\": false\n}\n```\n\n# Stelligent Policy Complexity Metrics (spcm)\n\nThe basis for SPCM is described in the blog post [Thought Experiment Proposed Complexity Metric for IAM Policy Documents](https://stelligent.com/2020/03/27/thought-experiment-proposed-complexity-metric-for-iam-policy-documents/).\n\nStarting in version 0.6.0 of cfn_nag:\n\n* `spcm_scan` can scan a directory of CloudFormation templates (like cfn_nag_scan) and generate a report with the SPCM\n   metrics in either JSON or HTML format\n* A rule is added (to cfn_nag) to warn on an IAM::Policy or IAM::Role with a SPCM score of \u003e= 50 (default)\n* The rule threshold can be controlled via the command line: `cfn_nag_scan --rule-arguments spcm_threshold:100`\n* Custom rule developers can now develop rules to accept end user values for settings via the same `--rule-arguments` mechanism.\n  The Rule object only needs to declare an `attr_accessor`, e.g. `attr_accessor :spcm_threshold` and cfn_nag\n  will take care of the details to inject values from the `--rule-arguments`\n\n# Distribution of Custom Rules\n\nThe release of 0.5.x includes some major changes in how custom rules (can) be distributed and loaded.  Before this release,\nthere were two places where rules were loaded from: the `lib/cfn-nag/custom_rules` directory within the core cfn_nag gem,\nand the custom-rule-directory specified on the command line.\n\nThere are two use cases that forced a redesign of how/where custom rules are loaded.  The rule loading mechanism has been\ngeneralized such that custom rule repositories can be used to discover rules.\n\n1. A bunch of \"rule files\" sitting around on a filesystem isn't great from a traditional software development perspective.\nThere is no version or traceability on these files, so 0.5.x introduces the notion of a \"cfn_nag rule gem\".  A developer\ncan develop custom rules as part of a separate gem, version it and install it... and those rules are referenced from cfn_nag\nas long as the gem metadata includes `cfn_nag_rules =\u003e true`.  For a gem named like \"cfn-nag-hipaa-rules\", any \\*.rb under\nlib/cfn-nag-hipaa-rules will be loaded.  Any custom rules should derive from CfnNag::BaseRule in cfn-nag/base_rule (*not* cfn-nag/custom-rules/base).  If the rule must derive from something else, defining a method `cfn_nag_rule?` that returns true will also cause it to be loaded as a rule.\n\n2. When cfn_nag is running in an AWS Lambda - there isn't really a filesystem (besides /tmp) in the traditional sense.\nTherefore, only core rules are usable from the Lambda.  To support custom rules, cfn_nag supports discovering rules\nfrom an S3 bucket instead of the filesystem.\n\nEverything you've likely seen about how to develop custom rules in Ruby still holds true.\n\nTo discover rules from an S3 bucket, create a file `s3.yml` with this content:\n\n```yaml\n---\nrepo_class_name: S3BucketBasedRuleRepo\nrepo_arguments:\n  s3_bucket_name: cfn-nag-rules-my-enterprise\n  prefix: /rules\n```\n\nTo apply *Rule.rb files in the bucket cfn-nag-rules-my-enterprise with the prefix /rules (e.g. /rules/MyNewRule.rb),\nspecify this file on the command line to cfn_nag as such:\n\n```yaml\ncat my_cfn_template.yml | cfn_nag --rule-repository s3.yml\n```\n\nIf rules are in more than one bucket, then create multiple s3*.yml files and specify them in the `--rule-repository` argument.\n\nIf the ambient AWS credentials have permission to access the bucket `cfn-nag-rules-enterprise` then it will find all rules\nlike `/rules/*Rule.rb`. If a particular aws_profile should be used, add it as a key under `repo_arguments`, e.g\n`aws_profile: my_aws_profile`\n\nBeyond the filesystem, gem installs and S3 - the new architecture theoretically supports developing other \"rule repositories\"\nto load rules from DynamoDb, relational databases, or other web services.\n\n# Development\n\n## New Rules\n\nTo author new rules for your own use and/or community contribution, see [Custom Rule Development](custom_rule_development.md) for details.\n\nA screencast demonstrating soup-to-nuts TDD custom rule development is available here:\n\n\u003chttps://www.youtube.com/watch?v=JRZct0naFd4\u0026t=1601s\u003e\n\n## Specs\n\nTo run the specs, you need to ensure you have Docker installed and cfn_nag dependencies installed via\n\n```bash\ngem install bundle\nbundle install\n```\n\nThen, to run all of the specs, just run `rake test:all`.\n\nTo run the end-to-end tests, run `rake test:e2e`. The script will bundle all gems in the Gemfile, build and install the cfn_nag gem locally, install spec dependencies, and then executes tests tagged with 'end_to_end'. It will also pull down sample templates provided by Amazon and run cfn_nag_scan against them, to see if any known-good templates cause exceptions within cfn-nag.\n\n## Local Install\n\nTo install the current git branch locally:\n\n```bash\nbundle install\nscripts/deploy_local.sh\n```\n\n## VS Code Remote Development\n\nThere is a complete remote development environment created and setup with all the tools and settings pre-configured for ease in rule development and creation. You can enable this by using the VS Code Remote development functionality.\n\n* Install the VS Code [Remote Development extension pack](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack)\n* Open the repo in VS Code\n* When prompted `Folder contains a dev container configuration file. Reopen folder to develop in a container` click the `Reopen in Container` button\n* When opening in the future use the `[Dev Container] cfn_nag Development` option\n\nMore information about the VS Code Remote Development setup can be found here, [VS Code Remote Development](vscode_remote_development.md).\n\n# Support\n\nTo report a bug or request a feature, submit an issue through the GitHub repository via: \u003chttps://github.com/stelligent/cfn_nag/issues/new\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstelligent%2Fcfn_nag","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstelligent%2Fcfn_nag","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstelligent%2Fcfn_nag/lists"}