Skip to content

Commit

Permalink
Merge branch 'dchakrav-github-parameterized-rules' into parameterized…
Browse files Browse the repository at this point in the history
…-rules
  • Loading branch information
diwakar committed Nov 18, 2021
2 parents ca562b9 + 1dc5bfa commit f5e1733
Show file tree
Hide file tree
Showing 44 changed files with 16,014 additions and 639 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.

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
10 changes: 8 additions & 2 deletions guard/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cfn-guard"
version = "2.0.3"
version = "2.1.0"
edition = "2018"
authors = ["Diwakar Chakravarthy", "John Tompkins", "Omkar Hegde", "Priya Padmanaban", "aws-cloudformation-developers <[email protected]>"]
description = "AWS CloudFormation Guard is an open-source general-purpose policy-as-code evaluation tool. It provides developers with a simple-to-use, yet powerful and expressive domain-specific language (DSL) to define policies and enables developers to validate JSON- or YAML- formatted structured data with those policies."
Expand Down Expand Up @@ -33,9 +33,15 @@ itertools = "0.4.7"
string-builder = "0.2.0"
enumflags2 = "0.7.1"
enumflags2_derive = "0.7.0"
Inflector = "0.11.4"
urlencoding = "2.1.0"
grep-searcher = "0.1.8"
grep-matcher = "0.1.5"
grep-regex = "0.1.9"
yaml-rust = {git = "https://github.com/dchakrav-github/yaml-rust"}

[dependencies.serde_json]
version = "1.0.60"
features = ["preserve_order"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
20 changes: 13 additions & 7 deletions guard/src/commands/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,19 @@ pub fn validate_and_return_json(
Ok(rules) => {
match input_data {
Ok(root) => {
let root_context = RootScope::new(&rules, &root);
let stacker = StackTracker::new(&root_context);
let reporters = vec![];
let reporter = ConsoleReporter::new(stacker, &reporters, "lambda-run","lambda-payload", true, true, false);
rules.evaluate(&root, &reporter)?;
let json_result = reporter.get_result_json();
return Ok(json_result);
let mut root_scope = crate::rules::eval_context::root_scope(&rules, &root)?;
//let mut tracker = crate::rules::eval_context::RecordTracker::new(&mut root_scope);
let _status = crate::rules::eval::eval_rules_file(&rules, &mut root_scope)?;
let event = root_scope.reset_recorder().extract();
Ok(serde_json::to_string_pretty(&event)?)

// let root_context = RootScope::new(&rules, &root);
// let stacker = StackTracker::new(&root_context);
// let reporters = vec![];
// let reporter = ConsoleReporter::new(stacker, &reporters, "lambda-run","lambda-payload", true, true, false);
// rules.evaluate(&root, &reporter)?;
// let json_result = reporter.get_result_json();
// return Ok(json_result);
}
Err(e) => return Err(e),
}
Expand Down
Loading

0 comments on commit f5e1733

Please sign in to comment.