Skip to content
Open
22 changes: 22 additions & 0 deletions assets/libraries/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -1711,6 +1711,28 @@
"tunnel2_inside_cidr": "tunnel2_inside_cidr"
}
},
"terraform-aws-modules/sns/aws": {
"resources": [
"aws_sns_topic",
"aws_sns_topic_data_protection_policy",
"aws_sns_topic_policy",
"aws_sns_topic_subscription"
],
"inputs": {
"archive_policy": "archive_policy",
"content_based_deduplication": "content_based_deduplication",
"delivery_policy": "delivery_policy",
"display_name": "display_name",
"fifo_throughput_scope": "fifo_throughput_scope",
"fifo-topic": "fifo-topic",
"kms_master_key_id": "kms_master_key_id",
"name": "name",
"signature_version": "signature_version",
"tags": "tags",
"tracing_config": "tracing_config",
"policy": "topic_policy"
}
},
"terraform-aws-modules/notify-slack/aws": {
"resources": [
"aws_cloudwatch_log_group",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ CxPolicy[result] {
statement.Effect == "Allow"
common_lib.any_principal(statement)

not is_access_limited_to_an_account_id(statement)

result := {
"documentId": id,
"resourceType": modules[m],
Expand All @@ -25,3 +27,10 @@ CxPolicy[result] {
"searchLine": common_lib.build_search_line(["playbooks", t, modules[m], "policy"], []),
}
}

is_access_limited_to_an_account_id(statement) {
common_lib.valid_key(statement, "Condition")
condition_keys := ["aws:SourceOwner", "aws:SourceAccount", "aws:ResourceAccount", "aws:PrincipalAccount", "aws:VpceAccount"]
condition_operator := statement.Condition[op][key]
lower(key) == lower(condition_keys[_])
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
Statement:
- Effect: Allow
Action: Publish
Principal: NotAll
Principal: "arn:aws:iam::123456789012:root"

- name: Create alarm SNS topic
sns_topic:
Expand All @@ -42,4 +42,4 @@
Statement:
- Effect: Allow
Action: Publish
Principal: NotAll
Principal: "arn:aws:iam::123456789012:root"
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
- name: Create SNS topic with safe policy
community.aws.sns_topic:
name: secure-topic
display_name: "Secure SNS Topic"
state: present
policy:
Id: secure-topic-policy
Version: "2012-10-17"
Statement:
- Sid: AllowPublishFromSpecificAccount
Effect: Allow
Resource: "arn:aws:sns:*:*:secure-topic"
Principal: "*"
Action: sns:Publish
Condition:
StringEquals:
aws:SourceAccount: "123456789012"

- name: Create alarm SNS topic
sns_topic:
name: alarms
state: present
display_name: "alarm SNS topic"
delivery_policy:
http:
defaultHealthyRetryPolicy:
minDelayTarget: 2
maxDelayTarget: 4
numRetries: 3
numMaxDelayRetries: 5
backoffFunction: exponential
disableSubscriptionOverrides: true
defaultThrottlePolicy:
maxReceivesPerSecond: 10
policy:
Version: '2022-05-02'
Statement:
- Effect: Allow
Action: Publish
Principal: "*"
Condition:
StringEquals:
aws:SourceAccount: "123456789012"
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
- name: Create SNS topic with mixed conditions
community.aws.sns_topic:
name: mixed-topic
display_name: "Mixed SNS Topic"
state: present
policy:
Id: mixed-topic-policy
Version: "2012-10-17"
Statement:
- Sid: AllowAnyPrincipalWithRestrictions
Effect: Allow
Resource: "arn:aws:sns:*:*:mixed-topic"
Principal: "*"
Action: sns:Publish
Condition:
StringEquals:
aws:SourceAccount: "123456789012"

- name: Create alarm SNS topic
sns_topic:
name: alarms
state: present
display_name: "alarm SNS topic"
delivery_policy:
http:
defaultHealthyRetryPolicy:
minDelayTarget: 2
maxDelayTarget: 4
numRetries: 3
numMaxDelayRetries: 5
backoffFunction: exponential
disableSubscriptionOverrides: true
defaultThrottlePolicy:
maxReceivesPerSecond: 10
policy:
Version: '2022-05-02'
Statement:
- Effect: Allow
Action: Publish
Principal: "*"
Condition:
StringEquals:
aws:SourceAccount: "123456789012"
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
Statement:
- Action: Publish
Effect: Allow
Principal: "*"
Principal:
AWS: "*"

- name: Create alarm SNS topic
sns_topic:
name: "alarms"
Expand All @@ -52,4 +54,5 @@
Statement:
- Effect: Allow
Action: Publish
Principal: '*'
Principal:
AWS: "*"
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
{
"queryName": "SNS Topic is Publicly Accessible",
"severity": "CRITICAL",
"line": 50,
"line": 52,
"fileName": "positive.yaml"
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ CxPolicy[result] {
common_lib.is_allow_effect(statement)
common_lib.any_principal(statement)

not is_access_limited_to_an_account_id(statement)

result := {
"documentId": input.document[i].id,
"resourceType": resource.Type,
Expand All @@ -24,3 +26,10 @@ CxPolicy[result] {
"searchLine": common_lib.build_search_line(["Resource", name, "Properties", "PolicyDocument"], []),
}
}

is_access_limited_to_an_account_id(statement) {
common_lib.valid_key(statement, "Condition")
condition_keys := ["aws:SourceOwner", "aws:SourceAccount", "aws:ResourceAccount", "aws:PrincipalAccount", "aws:VpceAccount"]
condition_operator := statement.Condition[op][key]
lower(key) == lower(condition_keys[_])
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
AWSTemplateFormatVersion: '2010-09-09'
Description: ''
Resources:
snsPolicy:
Type: AWS::SNS::TopicPolicy
Properties:
PolicyDocument:
Statement: [
{
"Sid": "MyTopicPolicy",
"Effect": "Allow",
"Principal": "*",
"Action": ["sns:Publish"],
"Resource": "arn:aws:sns:MyTopic",
"Condition": {
"StringEquals":
{
"aws:SourceAccount": "123456789012"
}
}
}]
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
AWSTemplateFormatVersion: '2010-09-09'
Description: ''
Resources:
snsPolicy:
Type: AWS::SNS::TopicPolicy
Properties:
PolicyDocument:
Statement: [
{
"Sid": "MyTopicPolicy",
"Effect": "Allow",
"Principal": "*",
"Action": ["sns:Publish"],
"Resource": "arn:aws:sns:MyTopic",
"Condition": {
"StringEquals":
{
"aws:ResourceAccount": "123456789012"
}
}
}]
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "",
"Resources": {
"snsPolicy": {
"Type": "AWS::SNS::TopicPolicy",
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Sid": "MyTopicPolicy",
"Effect": "Allow",
"Principal": "*",
"Action": [
"sns:Publish"
],
"Resource": "arn:aws:sns:MyTopic",
"Condition": {
"StringEquals": {
"aws:SourceAccount": "123456789012"
}
}
}
]
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "",
"Resources": {
"snsPolicy": {
"Type": "AWS::SNS::TopicPolicy",
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Sid": "MyTopicPolicy",
"Effect": "Allow",
"Principal": "*",
"Action": [
"sns:Publish"
],
"Resource": "arn:aws:sns:MyTopic",
"Condition": {
"StringEquals": {
"aws:ResourceAccount": "123456789012"
}
}
}
]
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ CxPolicy[result] {
common_lib.is_allow_effect(statement)
tf_lib.anyPrincipal(statement)

not is_access_limited_to_an_account_id(statement)

result := {
"documentId": input.document[i].id,
"resourceType": "aws_sns_topic",
Expand All @@ -24,3 +26,67 @@ CxPolicy[result] {
"searchLine": common_lib.build_search_line(["resource", "aws_sns_topic", name, "policy"], []),
}
}

CxPolicy[result] {
module := input.document[i].module[name]
keyToCheck := common_lib.get_module_equivalent_key("aws", module.source, "aws_sns_topic", "policy")
res := get_module_res(module, keyToCheck, name)

result := {
"documentId": input.document[i].id,
"resourceType": "n/a",
"resourceName": "n/a",
"searchKey": res["sk"],
"issueType": "IncorrectValue",
"keyExpectedValue": res["kev"],
"keyActualValue": res["kav"],
"searchLine": res["sl"],
}
}

get_module_res(module, keyToCheck, name) = res {
common_lib.valid_key(module, keyToCheck)
policy := common_lib.json_unmarshal(module[keyToCheck])
st := common_lib.get_statement(policy)
statement := st[_]

common_lib.is_allow_effect(statement)
tf_lib.anyPrincipal(statement)

not is_access_limited_to_an_account_id(statement)

res := {
"sk": sprintf("topic_policy", []),
"kev": sprintf("'Statement.Policy.AWS' shouldn't contain '*'", []),
"kav": sprintf("'Statement.Policy.AWS' contains '*'", []),
"sl": common_lib.build_search_line(["module", name, "topic_policy"], []),
}
} else = res {
common_lib.valid_key(module, "topic_policy_statements")
statement := module.topic_policy_statements[idx]
common_lib.is_allow_effect(statement)
principal := statement.principals[idx_principals]
principal.type == "AWS"
contains(principal.identifiers[idx_identifiers], "*")

not is_access_limited_to_an_account_id(statement)

res := {
"sk": sprintf("module[%s].topic_policy_statements[%d].principals[%d].identifiers[%d]", [name, idx, idx_principals, idx_identifiers]),
"kev": "AWS Principal shouldn't contain '*' on the identifiers",
"kav": "AWS Princiapl contains '*' on the identifiers",
"sl": common_lib.build_search_line(["module", name, "topic_policy_statements", idx, "principals", idx_principals, "identifiers", idx_identifiers], []),
}
}

is_access_limited_to_an_account_id(statement) {
common_lib.valid_key(statement, "Condition")
condition_keys := ["aws:SourceOwner", "aws:SourceAccount", "aws:ResourceAccount", "aws:PrincipalAccount", "aws:VpceAccount"]
condition_operator := statement.Condition[op][key]
lower(key) == lower(condition_keys[_])
} else {
common_lib.valid_key(statement, "condition")
condition_keys := ["aws:SourceOwner", "aws:SourceAccount", "aws:ResourceAccount", "aws:PrincipalAccount", "aws:VpceAccount"]
condition_operator := statement.condition[op][key]
lower(key) == lower(condition_keys[_])
}
Loading
Loading