Skip to content

Commit

Permalink
Parameterized rules (#244)
Browse files Browse the repository at this point in the history
* - Refactoring evaluation to new form using functions that keep inline
with Rust lifetimes. Ensuring that values from rules files (literals)
can be used alongside values from payload consistently. This make query
evaluation more efficient, allows for caching behavior for queries
themselves to be introduced in addition to variables.

- Added all unit tests for existing query evaluation back for the new evaluation
model.

- Brought consistency with evaluations where some values were retrieved
and others had retrieve failures. Introduced a QueryResult that
correctly captured this aspect. Allowed evaluations to take advantage of
this result, which allowed to correctly test successfully values while
reporting unsuccesful ones.

- Added functionality to be able to filter values within a map directly.
This allowed to use syntax `Resources[ Type == 'AWS::S3::Bucket' ]`
instead of `Resources.*[ Type == 'AWS::S3::Bucket' ]`. This also paves
the way to add key variable capture later like `Resource[ resource_name |
Type == 'AWS::S3::Bucket' ]`. Then `resource_name` can be used as a
variable in other evaluations

- Ensured that all integration guard-examples testing works completely
with the new evaluation engine. Introducing a new engine currently as an
alternative engine that can be enabled using -n flag for validate and
test for testing compatiblity in the field

- Verbose graph for new engine event records got a facelift and produces
very understandable ascii graphs that explains failures well.

* Adding parsing for parameterized rules support.

* Submitting next small cut

* Adding more parser and eval logic

* Adding first test sample successful run, Yay

* 1. Fixed bug for eval_guard_clause end_record to file for error
condition
2. Added support for CFN reporter to report with new engine as well
3. Added example for parameterized rule support

* Moving context to mut

* Migrated Tracker as well

* Adding support for case conversations to test across tools

* Adding variable capture along with parameterized rules

* Added support for reporting variable names

* Added testing for S3 buckets

* Fixing equality clauses for correctly

* Fix lhs when reading inside list

* Fix in operator

* - Added summary table
- Exposed unresolved if there are none

* - Fixed bug with LHS having embedded lists
- Fixed display text to convey right value

* - revert change for correct behavior
TODO: Add variable resolution event

* - Fix reporting and checks for in and eq operations when dealing with
  embedded lists on LHS in comparison with RHS

* Adding SKIPs to context

* Fix issue #186

* SKIP when there is no view projection

* - Adding support for merge values
- Adding support for serialization from Lambda

* Changing Event Tracing

* Minor fixes

* Removing functional as it serves no purpose

* - Adding support for String contains for in operation
- Fixing rule for correctness

* Added tests for "in" string contains

* BlockClause entry for tracking

* Fix for to being None

* Fixed bug when performing filtering over all values

* Exposing parameterized rules output and message

* Adding support for same name rules for Config and CFN in the same file

* Adding console reporter with improved messaging for checks

* Output fix

* Added support for run tests from root directory based on convention

* Make handling literals consistent

* Removing remanant literal handling

* Adding new format for checks

* Adding support for 'validate' to pick all guard files

* Initial cut for built in support functions

* - Next cut of builtin function support
- fixing parse_string with escapes initial cut

* Added support for embedded strings

* Adding more built in functions

* Adding traversal for JSON pointer based extraction

* Minor warning fixes

* CFN Awareness with auto-detection

* Added single line with resource information

* Few more mods

* Improved reporting for CFN template driven by auto-detection

* Fixed reporting failures

* Bumping up version for Guard

* - Fixed bug with reporting
- Fixed testing

* Support for Terraform plan files

* - Fixing IN operation reporting
- Adding code view propagation

* Remove dead code

* - Refactoring evaluation to new form using functions that keep inline
with Rust lifetimes. Ensuring that values from rules files (literals)
can be used alongside values from payload consistently. This make query
evaluation more efficient, allows for caching behavior for queries
themselves to be introduced in addition to variables.

- Added all unit tests for existing query evaluation back for the new evaluation
model.

- Brought consistency with evaluations where some values were retrieved
and others had retrieve failures. Introduced a QueryResult that
correctly captured this aspect. Allowed evaluations to take advantage of
this result, which allowed to correctly test successfully values while
reporting unsuccesful ones.

- Added functionality to be able to filter values within a map directly.
This allowed to use syntax `Resources[ Type == 'AWS::S3::Bucket' ]`
instead of `Resources.*[ Type == 'AWS::S3::Bucket' ]`. This also paves
the way to add key variable capture later like `Resource[ resource_name |
Type == 'AWS::S3::Bucket' ]`. Then `resource_name` can be used as a
variable in other evaluations

- Ensured that all integration guard-examples testing works completely
with the new evaluation engine. Introducing a new engine currently as an
alternative engine that can be enabled using -n flag for validate and
test for testing compatiblity in the field

- Verbose graph for new engine event records got a facelift and produces
very understandable ascii graphs that explains failures well.

* Adding parsing for parameterized rules support.

* Submitting next small cut

* Adding more parser and eval logic

* Adding first test sample successful run, Yay

* 1. Fixed bug for eval_guard_clause end_record to file for error
condition
2. Added support for CFN reporter to report with new engine as well
3. Added example for parameterized rule support

* Moving context to mut

* Migrated Tracker as well

* Adding support for case conversations to test across tools

* Adding variable capture along with parameterized rules

* Added support for reporting variable names

* Added testing for S3 buckets

* Fixing equality clauses for correctly

* Fix lhs when reading inside list

* Fix in operator

* - Added summary table
- Exposed unresolved if there are none

* - Fixed bug with LHS having embedded lists
- Fixed display text to convey right value

* - revert change for correct behavior
TODO: Add variable resolution event

* - Fix reporting and checks for in and eq operations when dealing with
  embedded lists on LHS in comparison with RHS

* Adding SKIPs to context

* Fix issue #186

* SKIP when there is no view projection

* - Adding support for merge values
- Adding support for serialization from Lambda

* Changing Event Tracing

* Minor fixes

* Removing functional as it serves no purpose

* - Adding support for String contains for in operation
- Fixing rule for correctness

* Added tests for "in" string contains

* BlockClause entry for tracking

* Fix for to being None

* Fixed bug when performing filtering over all values

* Exposing parameterized rules output and message

* Adding support for same name rules for Config and CFN in the same file

* Adding console reporter with improved messaging for checks

* Output fix

* Added support for run tests from root directory based on convention

* Make handling literals consistent

* Removing remanant literal handling

* Adding new format for checks

* Adding support for 'validate' to pick all guard files

* Initial cut for built in support functions

* - Next cut of builtin function support
- fixing parse_string with escapes initial cut

* Added support for embedded strings

* Adding more built in functions

* Adding traversal for JSON pointer based extraction

* Minor warning fixes

* CFN Awareness with auto-detection

* Added single line with resource information

* Few more mods

* Improved reporting for CFN template driven by auto-detection

* Fixed reporting failures

* Bumping up version for Guard

* - Fixed bug with reporting
- Fixed testing

* Support for Terraform plan files

* - Fixing IN operation reporting
- Adding code view propagation

* Remove dead code

* Fixing YAML with line numbers and more

* Marker tracking for locations in file

* Inline code for template for CFN

* Improving the message for CFN templates

* Fixing CFN template level functions

* Ensuring chain works correctly for default display

* Fixing test command to ensure all tests are correctly covered

* Bug fix needed for list-of-lists

* One pending in testing

* TODO introduce new string_in operator to no overload

* Push out

* Add fixes for compilation errors

* Remove unused imports

* Remove 2 repeated command line args

* Added overloaded behavior for data argument, verified payload & dir values

* Move re-used scan for data into a method

* Add support for multiple args for rules

* Move file extension check into a method

* Move string literals to constants

* Resolve conflict with type

* Move literals from test to constants

* Add support for input-parameters as files

* Add directory support for input-parameters

* Updated help for input-parameters arg

* Add unit test cases for various input combinations of data, rules and input-parameters

* Move app name and app version to constants

* Move string literals for rulegen to constants

* Add security related unit tests for validate

* Adding project contributer

* Updated placeholder in LICENSE

* Updated occurrences of organization

* Remove instructions from LICENSE

* Add more project contributors

* Update README.md for cfn-guard-lambda

Co-authored-by: diwakar <dchakrav-github@gmail.com>
Co-authored-by: dchakrav-github <42748809+dchakrav-github@users.noreply.github.com>
Co-authored-by: diwakar <diwakar@amazon.com>
Co-authored-by: Akshay Rane <raneaks@amazon.com>
Co-authored-by: Bryan Ayala <bryaayal@amazon.com>
  • Loading branch information
6 people committed Jun 30, 2022
1 parent 2a41f44 commit 901d40a
Show file tree
Hide file tree
Showing 78 changed files with 16,970 additions and 679 deletions.
117 changes: 115 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 1 addition & 12 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -175,18 +175,7 @@

END OF TERMS AND CONDITIONS

APPENDIX: How to apply the Apache License to your work.

To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright [yyyy] [name of copyright owner]
Copyright 2020-2022 Amazon Web Services, Inc. or its affiliates. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
2 changes: 1 addition & 1 deletion NOTICE
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
AWS CloudFormation Guard
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
Copyright Amazon Web Services, Inc. or its affiliates. All Rights Reserved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
- name: Allowed from CORRECT, expected PASS
input:
Resources:
snsPolicy:
Type: AWS::SNS::TopicPolicy
Properties:
PolicyDocument:
Statement: [
{
"Sid": "grant-1234-publish",
"Effect": "Allow",
"Principal": {
"AWS": "111122223333"
},
"Action": ["sns:Publish"],
"Resource": "arn:aws:sns:us-east-2:444455556666:MyTopic"
}]
expectations:
rules:
check_sns_topic_cross_account: PASS

- name: 666677778888 account not in list, FAIL
input:
Resources:
snsPolicy:
Type: AWS::SNS::TopicPolicy
Properties:
PolicyDocument:
Statement: [
{
"Sid": "grant-1234-publish",
"Effect": "Allow",
"Principal": {
"AWS": ["111122223333", "666677778888"]
},
"Action": ["sns:Publish"],
"Resource": "arn:aws:sns:us-east-2:444455556666:MyTopic"
}]
expectations:
rules:
check_sns_topic_cross_account: FAIL

- name: Accesse via an AWS service, PASS expected as 444455556666 was allowed
input:
Resources:
snsPolicy:
Type: AWS::SNS::TopicPolicy
Properties:
PolicyDocument:
Statement: [
{
"Effect": "Allow",
"Principal": {
"Service": "s3.amazonaws.com"
},
"Action": "sns:Publish",
"Resource": "arn:aws:sns:us-east-2:111122223333:MyTopic",
"Condition": {
"StringEquals": {
"AWS:SourceAccount": "444455556666"
}
}
}]
expectations:
rules:
check_sns_topic_cross_account: PASS

- name: Accesse via an AWS service, FAIL expected as no Condition was specified to narrow
input:
Resources:
snsPolicy:
Type: AWS::SNS::TopicPolicy
Properties:
PolicyDocument:
Statement: [
{
"Effect": "Allow",
"Principal": {
"Service": "s3.amazonaws.com"
},
"Action": "sns:Publish",
"Resource": "arn:aws:sns:us-east-2:111122223333:MyTopic",
}]
expectations:
rules:
check_sns_topic_cross_account: FAIL

Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
let allowed = [
/111122223333/,
/444455556666/
]

rule check_direct_principals(principals) {
%principals in %allowed
}

rule check_aws_specified(principals) {
%principals.AWS in %allowed
}

rule check_via_aws_service(statement) {
when %statement.Principal.Service exists {
%statement.Condition[ keys == /String(Equals|Like)|Arn(Equals|Like)/ ] not empty {
let source_accounts = this[ keys == /(aws|AWS):[sS]ource(Account|Owner|Arn|ARN)/ ]
%source_accounts in %allowed
}
}
}

rule check_only_allowed_aws_accounts(statement) {
%statement
{
when Effect == 'Allow'
{
check_direct_principals(Principal) or
check_aws_specified(Principal) or
check_via_aws_service(this)
}
}
}

rule check_sns_topic_cross_account {
Resources[ Type == 'AWS::SNS::TopicPolicy' ] {
check_only_allowed_aws_accounts(Properties.PolicyDocument.Statement[*])
}
}
4 changes: 2 additions & 2 deletions guard-examples/cross-account/sns-cross-account.guard
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ rule sns_cross_account_only_allowed_accounts {
# when accessed via any AWS services, ensure that source account is only from allowed lists
# We want to check StringEquals, StringLike, ArnEquals, ArnLike checks
#
let expected_conditions = Condition[ keys == /String(Equals|Like)|Arn(Equals|Like)/ ].*
let expected_conditions = Condition[ keys == /String(Equals|Like)|Arn(Equals|Like)/ ]

#
# Ensure that these are specified, else it is an error
Expand All @@ -47,7 +47,7 @@ rule sns_cross_account_only_allowed_accounts {
#
# Then extract values against these (aws|AWS):[sS]ourceAccount, (aws|AWS):[sS]ourceOwner, (aws|AWS):[sS]ource(Arn|ARN)
#
let source_accounts = %expected_conditions[ keys == /(aws|AWS):[sS]ource(Account|Owner|Arn|ARN)/ ].*
let source_accounts = %expected_conditions[ keys == /(aws|AWS):[sS]ource(Account|Owner|Arn|ARN)/ ]

#
# It is an error to not specify this. Ensure the ones specified match allowed accounts
Expand Down
2 changes: 1 addition & 1 deletion guard-lambda/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "cfn-guard-lambda"
version = "2.0.4"
authors = ["Diwakar Chakravarthy", "John Tompkins", "Omkar Hegde", "Priya Padmanaban", "aws-cloudformation-developers <aws-cloudformation-developers@amazon.com>"]
authors = ["Diwakar Chakravarthy", "John Tompkins", "Omkar Hegde", "Priya Padmanaban", "Bryan Ayala", "aws-cloudformation-developers <aws-cloudformation-developers@amazon.com>"]
description = "Lambda version of cfn-guard. Checks JSON- or YAML- formatted structured data for policy compliance using a simple, policy-as-code, declarative syntax"
license = "Apache-2.0"
edition = "2018"
Expand Down

0 comments on commit 901d40a

Please sign in to comment.