Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Enhancement] Add CDKTemplate type to validation command #204

Closed
alexpulver opened this issue Sep 17, 2021 · 3 comments
Closed

[Enhancement] Add CDKTemplate type to validation command #204

alexpulver opened this issue Sep 17, 2021 · 3 comments
Labels
enhancement New feature or request next-release

Comments

@alexpulver
Copy link

Is your feature request related to a problem? Please describe.

I am using the AWS CDK to define my infrastructure. As a background, the AWS CDK has the following composition concept:

Composition is the key pattern for defining higher-level abstractions through constructs. A high-level construct can be composed from any number of lower-level constructs, and in turn, those could be composed from even lower-level constructs, which eventually are composed from AWS resources. From a bottom-up perspective, you use constructs to organize the individual AWS resources you want to deploy using whatever abstractions are convenient for your purpose, with as many layers as you need.

Currently, cfn-guard validation command supports CFNTemplate type, that outputs logical name of resources and relevant properties (e.g., Resource [vol2] property [Properties.Encrypted] in template [sample-template.yaml]), as opposed to property paths and values (e.g., Property [/Resources/vol2/Properties/Encrypted] in data [sample-template.yaml]).

When there is a resource failure during validation, as an AWS CDK developer, I need to map the AWS CloudFormation (CFN) resource logical ID back to the AWS CDK construct in the source code. The AWS CDK automatically generates the CFN logical IDs based on the hierarchy of Construct IDs, referred to as path. For example: APILambdaFunctionServiceRole3284E859. The path for the same logical ID would be something like Backend/Stateless/API/LambdaFunction/ServiceRole/Resource. The part before /API/... refers to CDK stage and CDK stack constructs IDs in this specific example, respectively. Both will be part of the generated CFN template file name: BackendStatelessAD73535F.template.json

The resulting logical IDs are not always easy to read and interpret as compared to the path. Thanks to the separators, the path is quicker to use for finding the construct related to cfn-guard resource failure. Alternatively, I would need to guess the separators, or manually find the aws:cdk:path value for the CFN logical ID in the synthesized CFN template.

Describe the solution you'd like

Add CDKTemplate type to the validation command. Specifying the type will add aws:cdk:path data from the CFN template Metadata section to the output for each resource. The data should be available for all supported output formats. This will address the above problem by making the aws:cdk:path value immediately visible to the AWS CDK developer.

Example for a simple landing page frontend stack:

# Text output
$ cfn-guard validate -t CDKTemplate -d LandingPageFrontend.template.json -r rules.guard --show-summary none
Evaluation of rules rules.guard for template LandingPageFrontend.template.json, number of resource failures = 1
--
Resource [WebsiteBucket4326D7C2 (LandingPageFrontend/Website/Bucket/Resource)] property [Properties] in template [LandingPageFrontend.template.json] is not compliant with [rules.guard/aws_s3_bucket_versioning_defined] because needed value at [{"AccessControl":"PublicRead"}] did not exist. Error message [VersioningConfiguration is not defined]
--

# JSON output
$ cfn-guard validate -o json -t CDKTemplate -d LandingPageFrontend.template.json -r rules.guard --show-summary none | jq
{
  "data_from": "LandingPageFrontend.template.json",
  "rules_from": "rules.guard",
  "not_compliant": {
    "WebsiteBucket4326D7C2 (LandingPageFrontend/Website/Bucket/Resource)": [
      {
        "rule": "aws_s3_bucket_versioning_defined",
        "path": "Properties",
        "provided": {
          "AccessControl": "PublicRead"
        },
        "expected": null,
        "comparison": {
          "operator": "Exists",
          "not_operator_exists": false
        },
        "message": "VersioningConfiguration is not defined"
      }
    ]
  },
  "not_applicable": [],
  "compliant": []
}

Describe alternatives you've considered

Allow specifying aws:cdk:path in the custom message. `cfn-guard doesn't currently support variables in the custom message. Even if it did, this approach prone to errors, as one might forget to add the value, or use different formats.

Add a new key to the output - for example aws:cdk:path besides existing path for JSON output. I think it will unnecessarily expand the generic schema for a specific use case.

Additional context

Below are full examples of a template, rules file, existing outputs with CFNTemplate type, and suggested outputs with CDKTemplate type.

LandingPageFrontend.template.json

{
  "Resources": {
    "WebsiteBucket4326D7C2": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "AccessControl": "PublicRead"
      },
      "Metadata": {
        "aws:cdk:path": "LandingPageFrontend/Website/Bucket/Resource"
      }
    }
  }
}

rules.guard

let aws_s3_bucket_resources = Resources.*[ Type == 'AWS::S3::Bucket' ]

rule aws_s3_bucket_versioning_defined {
  when %aws_s3_bucket_resources not empty {
    %aws_s3_bucket_resources {
      Properties {
        VersioningConfiguration exists <<VersioningConfiguration is not defined>>
      }
    }
  }
}
$ cfn-guard validate -t CFNTemplate -d LandingPageFrontend.template.json -r rules.guard --show-summary none
Evaluation of rules rules.guard for template LandingPageFrontend.template.json, number of resource failures = 1
--
Resource [WebsiteBucket4326D7C2] property [Properties] in template [LandingPageFrontend.template.json] is not compliant with [rules.guard/aws_s3_bucket_versioning_defined] because needed value at [{"AccessControl":"PublicRead"}] did not exist. Error message [VersioningConfiguration is not defined]
--

$ cfn-guard validate -o json -t CFNTemplate -d LandingPageFrontend.template.json -r rules.guard --show-summary none
{
  "data_from": "LandingPageFrontend.template.json",
  "rules_from": "rules.guard",
  "not_compliant": {
    "WebsiteBucket4326D7C2": [
      {
        "rule": "aws_s3_bucket_versioning_defined",
        "path": "Properties",
        "provided": {
          "AccessControl": "PublicRead"
        },
        "expected": null,
        "comparison": {
          "operator": "Exists",
          "not_operator_exists": false
        },
        "message": "VersioningConfiguration is not defined"
      }
    ]
  },
  "not_applicable": [],
  "compliant": []
}

$ cfn-guard validate -t CDKTemplate -d LandingPageFrontend.template.json -r rules.guard --show-summary none
Evaluation of rules rules.guard for template LandingPageFrontend.template.json, number of resource failures = 1
--
Resource [WebsiteBucket4326D7C2 (LandingPageFrontend/Website/Bucket/Resource)] property [Properties] in template [LandingPageFrontend.template.json] is not compliant with [rules.guard/aws_s3_bucket_versioning_defined] because needed value at [{"AccessControl":"PublicRead"}] did not exist. Error message [VersioningConfiguration is not defined]
--

$ cfn-guard validate -o json -t CDKTemplate -d LandingPageFrontend.template.json -r rules.guard --show-summary none
{
  "data_from": "LandingPageFrontend.template.json",
  "rules_from": "rules.guard",
  "not_compliant": {
    "WebsiteBucket4326D7C2 (LandingPageFrontend/Website/Bucket/Resource)": [
      {
        "rule": "aws_s3_bucket_versioning_defined",
        "path": "Properties",
        "provided": {
          "AccessControl": "PublicRead"
        },
        "expected": null,
        "comparison": {
          "operator": "Exists",
          "not_operator_exists": false
        },
        "message": "VersioningConfiguration is not defined"
      }
    ]
  },
  "not_applicable": [],
  "compliant": []
}
@alexpulver alexpulver added the enhancement New feature or request label Sep 17, 2021
@dchakrav-github
Copy link
Contributor

This is related to bug #202 that appends CDK information to the message. Will probably close that bug for this enhancement

@razcloud
Copy link
Contributor

razcloud commented Jul 1, 2022

Please check out the Guard 2.1.0 Release that should resolve this issue.

@razcloud razcloud closed this as completed Jul 1, 2022
@alexpulver
Copy link
Author

Thanks @razcloud! I see CDK-Path in text output, but don't see it in --print-json or -o json. I already opened an additional issue for --print-json (#250) and will open a separate one for -o json. By the way, should there be a difference between --print-json and -o json? Why not have only -o json?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request next-release
Projects
None yet
Development

No branches or pull requests

4 participants