cfn-nag 0.0.44 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/bin/cfn_nag +27 -11
  3. data/bin/cfn_nag_rules +5 -4
  4. data/bin/cfn_nag_scan +29 -0
  5. data/lib/cfn-nag.rb +3 -0
  6. data/lib/cfn-nag/cfn_nag.rb +115 -0
  7. data/lib/cfn-nag/custom_rule_loader.rb +72 -0
  8. data/lib/cfn-nag/custom_rules/CloudFormationAuthenticationRule.rb +28 -0
  9. data/lib/cfn-nag/custom_rules/CloudFrontDistributionAccessLoggingRule.rb +24 -0
  10. data/lib/cfn-nag/custom_rules/EbsVolumeHasSseRule.rb +24 -0
  11. data/lib/cfn-nag/custom_rules/ElasticLoadBalancerAccessLoggingRule.rb +24 -0
  12. data/lib/cfn-nag/custom_rules/IamManagedPolicyNotActionRule.rb +25 -0
  13. data/lib/cfn-nag/custom_rules/IamManagedPolicyNotResourceRule.rb +25 -0
  14. data/lib/cfn-nag/custom_rules/IamManagedPolicyWildcardActionRule.rb +25 -0
  15. data/lib/cfn-nag/custom_rules/IamManagedPolicyWildcardResourceRule.rb +25 -0
  16. data/lib/cfn-nag/custom_rules/IamPolicyNotActionRule.rb +25 -0
  17. data/lib/cfn-nag/custom_rules/IamPolicyNotResourceRule.rb +25 -0
  18. data/lib/cfn-nag/custom_rules/IamPolicyWildcardActionRule.rb +25 -0
  19. data/lib/cfn-nag/custom_rules/IamPolicyWildcardResourceRule.rb +25 -0
  20. data/lib/cfn-nag/custom_rules/IamRoleNotActionOnPermissionsPolicyRule.rb +28 -0
  21. data/lib/cfn-nag/custom_rules/IamRoleNotActionOnTrustPolicyRule.rb +25 -0
  22. data/lib/cfn-nag/custom_rules/IamRoleNotPrincipalOnTrustPolicyRule.rb +25 -0
  23. data/lib/cfn-nag/custom_rules/IamRoleNotResourceOnPermissionsPolicyRule.rb +28 -0
  24. data/lib/cfn-nag/custom_rules/IamRoleWildcardActionOnPermissionsPolicyRule.rb +28 -0
  25. data/lib/cfn-nag/custom_rules/IamRoleWildcardActionOnTrustPolicyRule.rb +27 -0
  26. data/lib/cfn-nag/custom_rules/IamRoleWildcardResourceOnPermissionsPolicyRule.rb +28 -0
  27. data/lib/cfn-nag/custom_rules/LambdaPermissionInvokeFunctionActionRule.rb +24 -0
  28. data/lib/cfn-nag/custom_rules/LambdaPermissionWildcardPrincipalRule.rb +24 -0
  29. data/lib/cfn-nag/custom_rules/ManagedPolicyOnUserRule.rb +24 -0
  30. data/lib/cfn-nag/custom_rules/PolicyOnUserRule.rb +24 -0
  31. data/lib/cfn-nag/custom_rules/S3BucketPolicyNotActionRule.rb +25 -0
  32. data/lib/cfn-nag/custom_rules/S3BucketPolicyNotPrincipalRule.rb +25 -0
  33. data/lib/cfn-nag/custom_rules/S3BucketPolicyWildcardActionRule.rb +30 -0
  34. data/lib/cfn-nag/custom_rules/S3BucketPolicyWildcardPrincipalRule.rb +29 -0
  35. data/lib/cfn-nag/custom_rules/S3BucketPublicReadAclRule.rb +29 -0
  36. data/lib/cfn-nag/custom_rules/S3BucketPublicReadWriteAclRule.rb +29 -0
  37. data/lib/cfn-nag/custom_rules/SecurityGroupEgressOpenToWorldRule.rb +39 -0
  38. data/lib/cfn-nag/custom_rules/SecurityGroupEgressPortRangeRule.rb +38 -0
  39. data/lib/cfn-nag/custom_rules/SecurityGroupIngressCidrNon32Rule.rb +40 -0
  40. data/lib/cfn-nag/custom_rules/SecurityGroupIngressOpenToWorldRule.rb +39 -0
  41. data/lib/cfn-nag/custom_rules/SecurityGroupIngressPortRangeRule.rb +38 -0
  42. data/lib/{custom_rules/security_group_missing_egress.rb → cfn-nag/custom_rules/SecurityGroupMissingEgressRule.rb} +6 -12
  43. data/lib/cfn-nag/custom_rules/SnsTopicPolicyNotActionRule.rb +25 -0
  44. data/lib/cfn-nag/custom_rules/SnsTopicPolicyNotPrincipalRule.rb +26 -0
  45. data/lib/cfn-nag/custom_rules/SnsTopicPolicyWildcardPrincipalRule.rb +29 -0
  46. data/lib/cfn-nag/custom_rules/SqsQueuePolicyNotActionRule.rb +25 -0
  47. data/lib/cfn-nag/custom_rules/SqsQueuePolicyNotPrincipalRule.rb +25 -0
  48. data/lib/cfn-nag/custom_rules/SqsQueuePolicyWildcardActionRule.rb +30 -0
  49. data/lib/cfn-nag/custom_rules/SqsQueuePolicyWildcardPrincipalRule.rb +29 -0
  50. data/lib/cfn-nag/custom_rules/UserHasInlinePolicyRule.rb +25 -0
  51. data/lib/cfn-nag/custom_rules/UserMissingGroupRule.rb +28 -0
  52. data/lib/cfn-nag/custom_rules/WafWebAclDefaultActionRule.rb +34 -0
  53. data/lib/cfn-nag/custom_rules/base.rb +28 -0
  54. data/lib/cfn-nag/custom_rules/unencrypted_s3_put_allowed.rb +58 -0
  55. data/lib/{profile.rb → cfn-nag/profile.rb} +0 -1
  56. data/lib/{profile_loader.rb → cfn-nag/profile_loader.rb} +2 -2
  57. data/lib/{result_view → cfn-nag/result_view}/json_results.rb +0 -0
  58. data/lib/{result_view → cfn-nag/result_view}/rules_view.rb +0 -0
  59. data/lib/{result_view → cfn-nag/result_view}/simple_stdout_results.rb +5 -12
  60. data/lib/cfn-nag/rule_definition.rb +36 -0
  61. data/lib/cfn-nag/rule_dumper.rb +23 -0
  62. data/lib/cfn-nag/rule_registry.rb +43 -0
  63. data/lib/cfn-nag/template_discovery.rb +24 -0
  64. data/lib/cfn-nag/violation.rb +58 -0
  65. metadata +79 -36
  66. data/lib/cfn_nag.rb +0 -219
  67. data/lib/custom_rule_loader.rb +0 -64
  68. data/lib/custom_rules/unencrypted_s3_put_allowed.rb +0 -58
  69. data/lib/custom_rules/user_missing_group.rb +0 -34
  70. data/lib/json_rules/basic_rules.rb +0 -49
  71. data/lib/json_rules/cfn_rules.rb +0 -4
  72. data/lib/json_rules/cidr_rules.rb +0 -77
  73. data/lib/json_rules/cloudfront_rules.rb +0 -4
  74. data/lib/json_rules/ebs_rules.rb +0 -4
  75. data/lib/json_rules/iam_policy_rules.rb +0 -153
  76. data/lib/json_rules/iam_user_rules.rb +0 -15
  77. data/lib/json_rules/lambda_rules.rb +0 -9
  78. data/lib/json_rules/loadbalancer_rules.rb +0 -9
  79. data/lib/json_rules/port_rules.rb +0 -33
  80. data/lib/json_rules/s3_bucket_rules.rb +0 -51
  81. data/lib/json_rules/sns_rules.rb +0 -29
  82. data/lib/json_rules/sqs_rules.rb +0 -25
  83. data/lib/model/action_parser.rb +0 -27
  84. data/lib/model/cfn_model.rb +0 -182
  85. data/lib/model/iam_user_parser.rb +0 -34
  86. data/lib/model/parser_registry.rb +0 -31
  87. data/lib/model/s3_bucket_policy.rb +0 -25
  88. data/lib/model/s3_bucket_policy_parser.rb +0 -28
  89. data/lib/model/security_group_parser.rb +0 -59
  90. data/lib/rule.rb +0 -208
  91. data/lib/rule_registry.rb +0 -45
  92. data/lib/violation.rb +0 -41
@@ -1,64 +0,0 @@
1
- require_relative 'model/parser_registry'
2
- require_relative 'model/cfn_model'
3
- require_relative 'custom_rules/security_group_missing_egress'
4
- require_relative 'custom_rules/unencrypted_s3_put_allowed'
5
- require_relative 'custom_rules/user_missing_group'
6
-
7
- class CustomRuleLoader
8
-
9
- attr_reader :custom_rule_registry
10
-
11
- @custom_rule_directory = '/var/lib/cfn_nag_plugins'
12
-
13
- def self.custom_rule_directory=(directory)
14
- @custom_rule_directory = directory
15
- end
16
-
17
- def self.custom_rule_directory
18
- @custom_rule_directory
19
- end
20
-
21
- def initialize(rule_registry)
22
- @custom_rule_registry = [
23
- SecurityGroupMissingEgressRule,
24
- UserMissingGroupRule,
25
- UnencryptedS3PutObjectAllowedRule
26
- ]
27
- @violations = []
28
- @rule_registry = rule_registry
29
- discover_rules
30
- end
31
-
32
- def custom_rules(input_json)
33
- @violations = []
34
-
35
- @custom_rule_registry.each do |rule_class|
36
- rule = rule_class.new
37
- @rule_registry.definition(id: rule.rule_id,
38
- type: rule.rule_type,
39
- message: rule.rule_text)
40
-
41
- if rule.respond_to? 'custom_parsers'
42
- rule.custom_parsers.each do |custom_parser|
43
- ParserRegistry.instance.add_parser custom_parser[0], custom_parser[1]
44
- end
45
- end
46
-
47
- cfn_model = CfnModel.new.parse(input_json)
48
- audit_result = rule_class.new.audit(cfn_model)
49
- @violations << audit_result unless audit_result.nil?
50
- end
51
- @violations
52
- end
53
-
54
- private
55
-
56
- def discover_rules(rule_directory: CustomRuleLoader.custom_rule_directory)
57
- rules = Dir[File.join(rule_directory, '*Rule.rb')].sort
58
-
59
- rules.each do |rule|
60
- require(rule)
61
- @custom_rule_registry << Object.const_get(File.basename(rule, '.rb'))
62
- end
63
- end
64
- end
@@ -1,58 +0,0 @@
1
- require_relative '../violation'
2
- require 'model/action_parser'
3
-
4
- class UnencryptedS3PutObjectAllowedRule
5
-
6
- def rule_text
7
- 'It appears that the S3 Bucket Policy allows s3:PutObject without server-side encryption'
8
- end
9
-
10
- def rule_type
11
- Violation::WARNING
12
- end
13
-
14
- def rule_id
15
- 'W1000'
16
- end
17
-
18
- def audit(cfn_model)
19
- logical_resource_ids = []
20
- cfn_model.bucket_policies.each do |bucket_policy|
21
- found_statement = bucket_policy.statements.find do |statement|
22
- blocks_put_object_without_encryption(statement)
23
- end
24
- if found_statement.nil?
25
- logical_resource_ids << bucket_policy.logical_resource_id
26
- end
27
- end
28
-
29
- if logical_resource_ids.size > 0
30
- Violation.new(id: rule_id,
31
- type: rule_type,
32
- message: rule_text,
33
- logical_resource_ids: logical_resource_ids)
34
- else
35
- nil
36
- end
37
- end
38
-
39
- private
40
-
41
- def blocks_put_object_without_encryption(statement)
42
- encryption_condition = {
43
- 'StringNotEquals' => {
44
- 's3:x-amz-server-side-encryption' => 'AES256'
45
- }
46
- }
47
-
48
- # this isn't quite complete. parsing the Resource field can be tricky
49
- # looking for a trailing wildcard will likely be right most of the time
50
- # but there are a lot of string manipulations to confuse things so...
51
- # just warn when we can't find at least the Deny+encryption - they may have an
52
- # incomplete Deny (for encryption) and that will slip through
53
- statement['Effect'] == 'Deny' and
54
- ActionParser.new.include?(actual_action: statement['Action'], action_to_look_for: 's3:PutObject') and
55
- S3BucketPolicy::condition_includes?(statement, encryption_condition) and
56
- statement['Principal'] == '*'
57
- end
58
- end
@@ -1,34 +0,0 @@
1
- require_relative '../violation'
2
-
3
- class UserMissingGroupRule
4
-
5
- def rule_text
6
- 'User is not assigned to a group'
7
- end
8
-
9
- def rule_type
10
- Violation::FAILING_VIOLATION
11
- end
12
-
13
- def rule_id
14
- 'F2000'
15
- end
16
-
17
- def audit(cfn_model)
18
- logical_resource_ids = []
19
- cfn_model.iam_users.each do |iam_user|
20
- if iam_user.groups.size == 0
21
- logical_resource_ids << iam_user.logical_resource_id
22
- end
23
- end
24
-
25
- if logical_resource_ids.size > 0
26
- Violation.new(id: rule_id,
27
- type: rule_type,
28
- message: rule_text,
29
- logical_resource_ids: logical_resource_ids)
30
- else
31
- nil
32
- end
33
- end
34
- end
@@ -1,49 +0,0 @@
1
- raw_fatal_assertion id: 'FATAL',
2
- jq: '.Resources|length > 0',
3
- message: 'A CloudFormation template must have at least 1 resource'
4
-
5
-
6
- %w(
7
- AWS::IAM::Role
8
- AWS::IAM::Policy
9
- AWS::IAM::ManagedPolicy
10
- AWS::S3::BucketPolicy
11
- AWS::SQS::QueuePolicy
12
- AWS::SNS::TopicPolicy
13
- AWS::IAM::UserToGroupAddition
14
- AWS::EC2::SecurityGroup
15
- AWS::EC2::SecurityGroupIngress
16
- AWS::EC2::SecurityGroupEgress
17
- ).each do |resource_must_have_properties|
18
- fatal_violation id: 'FATAL',
19
- jq: "[.Resources|with_entries(.value.LogicalResourceId = .key)[] | select(.Type == \"#{resource_must_have_properties}\" and .Properties == null)]|map(.LogicalResourceId)",
20
- message: "#{resource_must_have_properties} must have Properties"
21
- end
22
-
23
- missing_reference_jq = <<END
24
- (
25
- (
26
- ([..|.Ref?]|map(select(. != null)) + [..|."Fn::GetAtt"?[0]]|map(select(. != null)))
27
- )
28
- -
29
- (
30
- ["AWS::AccountId","AWS::StackName","AWS::Region","AWS::StackId","AWS::NoValue","AWS::NotificationARNs"] +
31
- ([.Resources|keys]|flatten) +
32
- (if .Parameters? then ([.Parameters|keys]|flatten) else [] end)
33
- )
34
- )|if length==0 then false else . end
35
- END
36
-
37
- raw_fatal_violation id: 'FATAL',
38
- jq: missing_reference_jq,
39
- message: 'All Ref and Fn::GetAtt must reference existing logical resource ids'
40
-
41
-
42
- %w(
43
- AWS::EC2::SecurityGroupIngress
44
- AWS::EC2::SecurityGroupEgress
45
- ).each do |xgress|
46
- fatal_violation id: 'FATAL',
47
- jq: "[.Resources|with_entries(.value.LogicalResourceId = .key)[] | select(.Type == \"#{xgress}\" and .Properties.GroupName != null)]|map(.LogicalResourceId)",
48
- message: "#{xgress} must not have GroupName - EC2 classic is a no-go!"
49
- end
@@ -1,4 +0,0 @@
1
- warning id: 'W1',
2
- jq: '[.Resources|with_entries(.value.LogicalResourceId = .key)[] | select(.Metadata."AWS::CloudFormation::Authentication") ]|'\
3
- 'map(.LogicalResourceId) ',
4
- message: 'Specifying credentials in the template itself is probably not the safest thing'
@@ -1,77 +0,0 @@
1
- ##### inline ingress
2
- warning id: 'W2',
3
- jq: '[.Resources|with_entries(.value.LogicalResourceId = .key)[] | select(.Type == "AWS::EC2::SecurityGroup" and (.Properties.SecurityGroupIngress|type == "object"))|select(.Properties.SecurityGroupIngress.CidrIp? == "0.0.0.0/0")]|map(.LogicalResourceId)',
4
- message: 'Security Groups found with cidr open to world on ingress. This should never be true on instance. Permissible on ELB'
5
-
6
- warning id: 'W3',
7
- jq: '[.Resources|with_entries(.value.LogicalResourceId = .key)[] | select(.Type == "AWS::EC2::SecurityGroup" and (.Properties.SecurityGroupIngress|type == "array"))|first(select(.Properties.SecurityGroupIngress[].CidrIp? == "0.0.0.0/0"))]|map(.LogicalResourceId)',
8
- message: 'Security Groups found with cidr open to world on ingress array. This should never be true on instance. Permissible on ELB'
9
-
10
- ##### external ingress
11
- warning id: 'W4',
12
- jq: '[.Resources|with_entries(.value.LogicalResourceId = .key)[] | select(.Type == "AWS::EC2::SecurityGroupIngress")|select(.Properties.CidrIp? == "0.0.0.0/0")]|map(.LogicalResourceId)',
13
- message: 'Security Group Standalone Ingress found with cidr open to world. This should never be true on instance. Permissible on ELB'
14
-
15
-
16
- ###### inline egress
17
- warning id: 'W5',
18
- jq: '[.Resources|with_entries(.value.LogicalResourceId = .key)[] | select(.Type == "AWS::EC2::SecurityGroup" and (.Properties.SecurityGroupEgress|type == "object"))|select(.Properties.SecurityGroupEgress.CidrIp? == "0.0.0.0/0")]|map(.LogicalResourceId)',
19
- message: 'Security Groups found with cidr open to world on egress'
20
-
21
-
22
- warning id: 'W6',
23
- jq: '[.Resources|with_entries(.value.LogicalResourceId = .key)[] | select(.Type == "AWS::EC2::SecurityGroup" and (.Properties.SecurityGroupEgress|type == "array"))|first(select(.Properties.SecurityGroupEgress[].CidrIp? == "0.0.0.0/0"))]|map(.LogicalResourceId)',
24
- message: 'Security Groups found with cidr open to world on egress array'
25
-
26
-
27
- ##### external egress
28
- warning id: 'W7',
29
- jq: '[.Resources|with_entries(.value.LogicalResourceId = .key)[] | select(.Type == "AWS::EC2::SecurityGroupEgress")|select(.Properties.CidrIp? == "0.0.0.0/0")]|map(.LogicalResourceId)',
30
- message: 'Security Group Standalone Egress found with cidr open to world.'
31
-
32
- non32_cidr_standalone_ingress = <<END
33
- [.Resources|
34
- with_entries(.value.LogicalResourceId = .key)[] |
35
- select(.Type == "AWS::EC2::SecurityGroupIngress") |
36
- if(.Properties.CidrIp|type == "string")
37
- then select(.Properties.CidrIp|endswith("/32")|not)
38
- else (
39
- if(.Properties.CidrIp|type == "array")
40
- then (select(.Properties.CidrIp[]|if (type == "string") then (endswith("/32")|not) else false end))
41
- else empty
42
- end
43
- )
44
- end ]|map(.LogicalResourceId)
45
- END
46
-
47
- # BEWARE with escapes \d -> \\\d because of how the escapes get munged from ruby through to shell
48
- warning id: 'W8',
49
- jq: non32_cidr_standalone_ingress,
50
- message: 'Security Group Standalone Ingress cidr found that is not /32'
51
-
52
- non_32_cidr_jq_expression = <<END
53
- [.Resources |
54
- with_entries(.value.LogicalResourceId = .key)[] |
55
- select(.Type == "AWS::EC2::SecurityGroup") |
56
- if (.Properties.SecurityGroupIngress|type == "object")
57
- then (
58
- if (.Properties.SecurityGroupIngress.CidrIp|type == "string")
59
- then (select(.Properties.SecurityGroupIngress.CidrIp|endswith("/32")|not))
60
- else empty
61
- end
62
- )
63
- else (
64
- if (.Properties.SecurityGroupIngress|type == "array")
65
- then (
66
- select(.Properties.SecurityGroupIngress[]|(if (.CidrIp|type == "string") then (select(.CidrIp|endswith("/32")|not)) else empty end))
67
- )
68
- else empty
69
- end
70
- )
71
- end
72
- ]|map(.LogicalResourceId)
73
- END
74
-
75
- warning id: 'W9',
76
- jq: non_32_cidr_jq_expression,
77
- message: 'Security Groups found with cidr that is not /32'
@@ -1,4 +0,0 @@
1
- warning id: 'W10',
2
- jq: '[.Resources|with_entries(.value.LogicalResourceId = .key)[] | select(.Type == "AWS::CloudFront::Distribution")|'\
3
- 'select(.Properties.DistributionConfig.Logging == null)]|map(.LogicalResourceId) ',
4
- message: 'CloudFront Distribution should enable access logging'
@@ -1,4 +0,0 @@
1
- violation id: 'F1',
2
- jq: '[.Resources|with_entries(.value.LogicalResourceId = .key)[] | select(.Type == "AWS::EC2::Volume")|'\
3
- 'select(.Properties.Encrypted == null or .Properties.Encrypted == false)]|map(.LogicalResourceId) ',
4
- message: 'EBS volume should have server-side encryption enabled'
@@ -1,153 +0,0 @@
1
- wildcard_action_filter = <<END
2
- def wildcard_action:
3
- if .Statement|type == "object"
4
- then select(.Statement.Effect == "Allow" and (if .Statement.Action|type=="string" then (.Statement.Action == "*") else (.Statement.Action|indices("*")|length > 0) end))
5
- else select(.Statement[]|.Effect == "Allow" and (if .Action|type=="string" then (.Action == "*") else (.Action|indices("*")|length > 0) end))
6
- end;
7
- END
8
-
9
- violation id: 'F2',
10
- jq: wildcard_action_filter +
11
- "[#{resources_by_type('AWS::IAM::Role')}|select(.Properties.AssumeRolePolicyDocument|wildcard_action)]|map(.LogicalResourceId) ",
12
- message: 'IAM role should not allow * action on its trust policy'
13
-
14
- violation id: 'F3',
15
- jq: wildcard_action_filter +
16
- "[#{resources_by_type('AWS::IAM::Role')}|select(.Properties.Policies !=null)|select(.Properties.Policies[].PolicyDocument|wildcard_action)]|map(.LogicalResourceId)",
17
- message: 'IAM role should not allow * action on its permissions policy'
18
-
19
-
20
- violation id: 'F4',
21
- jq: wildcard_action_filter +
22
- "[#{resources_by_type('AWS::IAM::Policy')}|select(.Properties.PolicyDocument|wildcard_action)]|map(.LogicalResourceId) ",
23
- message: 'IAM policy should not allow * action'
24
-
25
-
26
- violation id: 'F5',
27
- jq: wildcard_action_filter +
28
- "[#{resources_by_type('AWS::IAM::ManagedPolicy')}|select(.Properties.PolicyDocument|wildcard_action)]|map(.LogicalResourceId) ",
29
- message: 'IAM managed policy should not allow * action'
30
-
31
- wildcard_resource_filter = <<END
32
- def wildcard_resource:
33
- if .Statement|type == "object"
34
- then select(.Statement.Effect == "Allow" and (if .Statement.Resource|type=="string" then (.Statement.Resource == "*") else (.Statement.Resource|indices("*")|length > 0) end))
35
- else select(.Statement[]|.Effect == "Allow" and (if .Resource|type=="string" then (.Resource == "*") else (.Statement.Resource|indices("*")|length > 0) end))
36
- end;
37
- END
38
-
39
- warning id: 'W11',
40
- jq: wildcard_resource_filter +
41
- "[#{resources_by_type('AWS::IAM::Role')}|select(.Properties.Policies !=null)|select(.Properties.Policies[].PolicyDocument|wildcard_resource)]|map(.LogicalResourceId)",
42
- message: 'IAM role should not allow * resource on its permissions policy'
43
-
44
-
45
- warning id: 'W12',
46
- jq: wildcard_resource_filter +
47
- "[#{resources_by_type('AWS::IAM::Policy')}|select(.Properties.PolicyDocument|wildcard_resource)]|map(.LogicalResourceId)",
48
- message: 'IAM policy should not allow * resource'
49
-
50
- warning id: 'W13',
51
- jq: wildcard_resource_filter +
52
- "[#{resources_by_type('AWS::IAM::ManagedPolicy')}|select(.Properties.PolicyDocument|wildcard_resource)]|map(.LogicalResourceId)",
53
- message: 'IAM managed policy should not allow * resource'
54
-
55
- allow_not_action_filter = <<END
56
- def allow_not_action:
57
- if .Statement|type == "object"
58
- then select(.Statement.Effect == "Allow" and .Statement.NotAction != null)
59
- else select(.Statement[]|(.Effect == "Allow" and .NotAction != null))
60
- end;
61
- END
62
-
63
- warning id: 'W14',
64
- jq: allow_not_action_filter +
65
- "[#{resources_by_type('AWS::IAM::Role')}|select(.Properties.AssumeRolePolicyDocument|allow_not_action)]|map(.LogicalResourceId)",
66
- message: 'IAM role should not allow Allow+NotAction on trust permissinos'
67
-
68
-
69
- warning id: 'W15',
70
- jq: allow_not_action_filter +
71
- "[#{resources_by_type('AWS::IAM::Role')}|select(.Properties.Policies !=null)|select(.Properties.Policies[].PolicyDocument|allow_not_action)]|map(.LogicalResourceId)",
72
- message: 'IAM role should not allow Allow+NotAction'
73
-
74
-
75
- warning id: 'W16',
76
- jq: allow_not_action_filter +
77
- "[#{resources_by_type('AWS::IAM::Policy')}|select(.Properties.PolicyDocument|allow_not_action)]|map(.LogicalResourceId)",
78
- message: 'IAM policy should not allow Allow+NotAction'
79
-
80
-
81
- warning id: 'W17',
82
- jq: allow_not_action_filter +
83
- "[#{resources_by_type('AWS::IAM::ManagedPolicy')}|select(.Properties.PolicyDocument|allow_not_action)]|map(.LogicalResourceId)",
84
- message: 'IAM managed policy should not allow Allow+NotAction'
85
-
86
- warning id: 'W18',
87
- jq: allow_not_action_filter +
88
- "[#{resources_by_type('AWS::SQS::QueuePolicy')}|select(.Properties.PolicyDocument|allow_not_action)]|map(.LogicalResourceId)",
89
- message: 'SQS Queue policy should not allow Allow+NotAction'
90
-
91
- warning id: 'W19',
92
- jq: allow_not_action_filter +
93
- "[#{resources_by_type('AWS::SNS::TopicPolicy')}|select(.Properties.PolicyDocument|allow_not_action)]|map(.LogicalResourceId)",
94
- message: 'SNS Topic policy should not allow Allow+NotAction'
95
-
96
- warning id: 'W20',
97
- jq: allow_not_action_filter +
98
- "[#{resources_by_type('AWS::S3::BucketPolicy')}|select(.Properties.PolicyDocument|allow_not_action)]|map(.LogicalResourceId)",
99
- message: 'S3 Bucket policy should not allow Allow+NotAction'
100
-
101
- allow_not_resource_filter = <<END
102
- def allow_not_resource:
103
- if .Statement|type == "object"
104
- then select(.Statement.Effect == "Allow" and .Statement.NotResource != null)
105
- else select(.Statement[]|(.Effect == "Allow" and .NotResource != null))
106
- end;
107
- END
108
-
109
- warning id: 'W21',
110
- jq: allow_not_resource_filter +
111
- "[#{resources_by_type('AWS::IAM::Role')}|select(.Properties.Policies !=null)|select(.Properties.Policies[].PolicyDocument|allow_not_resource)]|map(.LogicalResourceId)",
112
- message: 'IAM role should not allow Allow+NotResource'
113
-
114
-
115
- warning id: 'W22',
116
- jq: allow_not_resource_filter +
117
- "[#{resources_by_type('AWS::IAM::Policy')}|select(.Properties.PolicyDocument|allow_not_resource)]|map(.LogicalResourceId)",
118
- message: 'IAM policy should not allow Allow+NotResource'
119
-
120
-
121
- warning id: 'W23',
122
- jq: allow_not_resource_filter +
123
- "[#{resources_by_type('AWS::IAM::ManagedPolicy')}|select(.Properties.PolicyDocument|allow_not_resource)]|map(.LogicalResourceId)",
124
- message: 'IAM managed policy should not allow Allow+NotResource'
125
-
126
-
127
- allow_not_principal_filter = <<END
128
- def allow_not_principal:
129
- if .Statement|type == "object"
130
- then select(.Statement.Effect == "Allow" and .Statement.NotPrincipal != null)
131
- else select(.Statement[]|(.Effect == "Allow" and .NotPrincipal != null))
132
- end;
133
- END
134
-
135
- violation id: 'F6',
136
- jq: allow_not_principal_filter +
137
- "[#{resources_by_type('AWS::IAM::Role')}|select(.Properties.AssumeRolePolicyDocument|allow_not_principal)]|map(.LogicalResourceId)",
138
- message: 'IAM role should not allow Allow+NotPrincipal in its trust policy'
139
-
140
- violation id: 'F7',
141
- jq: allow_not_principal_filter +
142
- "[#{resources_by_type('AWS::SQS::QueuePolicy')}|select(.Properties.PolicyDocument|allow_not_principal)]|map(.LogicalResourceId)",
143
- message: 'SQS Queue policy should not allow Allow+NotPrincipal'
144
-
145
- violation id: 'F8',
146
- jq: allow_not_principal_filter +
147
- "[#{resources_by_type('AWS::SNS::TopicPolicy')}|select(.Properties.PolicyDocument|allow_not_principal)]|map(.LogicalResourceId)",
148
- message: 'SNS Topic policy should not allow Allow+NotPrincipal'
149
-
150
- violation id: 'F9',
151
- jq: allow_not_principal_filter +
152
- "[#{resources_by_type('AWS::S3::BucketPolicy')}|select(.Properties.PolicyDocument|allow_not_principal)]|map(.LogicalResourceId)",
153
- message: 'S3 Bucket policy should not allow Allow+NotPrincipal'