diff --git a/.rubocop.yml b/.rubocop.yml index 7dcda814..e096ca07 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -37,3 +37,6 @@ Naming/RescuedExceptionsVariableName: Gemspec/RequiredRubyVersion: Enabled: false + +Metrics/ClassLength: + Max: 115 diff --git a/cfn-nag.gemspec b/cfn-nag.gemspec index 411084da..5abfbad8 100644 --- a/cfn-nag.gemspec +++ b/cfn-nag.gemspec @@ -24,8 +24,7 @@ Gem::Specification.new do |s| # versus what we used to run tests in cfn-nag before publishing cfn-nag # they are coupled and we are doing a good bit of experimenting in cfn-model # i might consider collapsing them again.... - s.add_runtime_dependency('cfn-model', '0.1.35') - + s.add_runtime_dependency('cfn-model', '0.4.0') s.add_runtime_dependency('jmespath', '~> 1.3.1') s.add_runtime_dependency('logging', '~> 2.2.2') s.add_runtime_dependency('netaddr', '~> 1.5.1') diff --git a/circle.txt b/circle.txt new file mode 100644 index 00000000..163be395 --- /dev/null +++ b/circle.txt @@ -0,0 +1,30 @@ +*** LOCAL GEMS *** + +ast (2.4.0) +bundler (default: 1.17.3) +cfn-model (0.1.29) +cfn-nag (0.0.0) +diff-lcs (1.3) +docile (1.3.1) +jaro_winkler (1.5.2) +jmespath (1.3.1) +json (2.2.0) +kwalify (0.7.2) +little-plugger (1.1.4) +logging (2.2.2) +multi_json (1.13.1) +netaddr (1.5.1) +parallel (1.17.0) +parser (2.6.3.0) +rainbow (3.0.0) +rspec (3.8.0) +rspec-core (3.8.0) +rspec-expectations (3.8.3) +rspec-mocks (3.8.0) +rspec-support (3.8.0) +rubocop (0.68.1) +ruby-progressbar (1.10.0) +simplecov (0.16.1) +simplecov-html (0.10.2) +trollop (2.1.3) +unicode-display_width (1.5.0) diff --git a/lib/cfn-nag/cfn_nag.rb b/lib/cfn-nag/cfn_nag.rb index 4fc619b3..0729b8f7 100644 --- a/lib/cfn-nag/cfn_nag.rb +++ b/lib/cfn-nag/cfn_nag.rb @@ -85,10 +85,12 @@ def audit(cloudformation_string:, parameter_values_string: nil) begin cfn_model = CfnParser.new.parse cloudformation_string, - parameter_values_string + parameter_values_string, + true violations += @custom_rule_loader.execute_custom_rules(cfn_model) violations = filter_violations_by_blacklist_and_profile(violations) + violations = mark_line_numbers(violations, cfn_model) rescue Psych::SyntaxError, ParserError => parser_error violations << fatal_violation(parser_error.to_s) rescue JSON::ParserError => json_parameters_error @@ -101,6 +103,16 @@ def audit(cloudformation_string:, parameter_values_string: nil) private + def mark_line_numbers(violations, cfn_model) + violations.each do |violation| + violation.logical_resource_ids.each do |logical_resource_id| + violation.line_numbers << cfn_model.line_numbers[logical_resource_id] + end + end + + violations + end + def filter_violations_by_blacklist_and_profile(violations) violations = filter_violations_by_profile( profile_definition: @profile_definition, diff --git a/lib/cfn-nag/result_view/simple_stdout_results.rb b/lib/cfn-nag/result_view/simple_stdout_results.rb index 173eb93c..8bb8d940 100644 --- a/lib/cfn-nag/result_view/simple_stdout_results.rb +++ b/lib/cfn-nag/result_view/simple_stdout_results.rb @@ -8,7 +8,8 @@ def message_violations(violations) violations.each do |violation| message message_type: "#{violation.type} #{violation.id}", message: violation.message, - logical_resource_ids: violation.logical_resource_ids + logical_resource_ids: violation.logical_resource_ids, + line_numbers: violation.line_numbers end end @@ -38,7 +39,8 @@ def render(results) def message(message_type:, message:, - logical_resource_ids: nil) + logical_resource_ids: nil, + line_numbers: []) logical_resource_ids = nil if logical_resource_ids == [] @@ -47,7 +49,8 @@ def message(message_type:, puts "| #{message_type.upcase}" puts '|' puts "| Resources: #{logical_resource_ids}" unless logical_resource_ids.nil? - puts '|' unless logical_resource_ids.nil? + puts "| Line Numbers: #{line_numbers}" unless line_numbers.empty? + puts '|' unless line_numbers.empty? && logical_resource_ids.nil? puts "| #{message}" end diff --git a/lib/cfn-nag/violation.rb b/lib/cfn-nag/violation.rb index c56a96ff..c7eb0b7d 100644 --- a/lib/cfn-nag/violation.rb +++ b/lib/cfn-nag/violation.rb @@ -4,17 +4,19 @@ # Rule definition for violations class Violation < RuleDefinition - attr_reader :logical_resource_ids + attr_reader :logical_resource_ids, :line_numbers def initialize(id:, type:, message:, - logical_resource_ids: nil) + logical_resource_ids: nil, + line_numbers: []) super id: id, type: type, message: message @logical_resource_ids = logical_resource_ids + @line_numbers = line_numbers end def to_s @@ -23,7 +25,8 @@ def to_s def to_h super.to_h.merge( - logical_resource_ids: @logical_resource_ids + logical_resource_ids: @logical_resource_ids, + line_numbers: @line_numbers ) end diff --git a/line_numbers.patch b/line_numbers.patch new file mode 100644 index 00000000..b6f4a22f --- /dev/null +++ b/line_numbers.patch @@ -0,0 +1,437 @@ +diff --git a/cfn-nag.gemspec b/cfn-nag.gemspec +index ba8bf0f..7be251b 100644 +--- a/cfn-nag.gemspec ++++ b/cfn-nag.gemspec +@@ -20,7 +20,7 @@ Gem::Specification.new do |s| + s.add_development_dependency('rubocop') + s.add_development_dependency('simplecov', '~> 0.11') + +- s.add_runtime_dependency('cfn-model', '~> 0.1.28') ++ s.add_runtime_dependency('cfn-model') + s.add_runtime_dependency('jmespath', '~> 1.3.1') + s.add_runtime_dependency('logging', '~> 2.2.2') + s.add_runtime_dependency('netaddr', '~> 1.5.1') +diff --git a/lib/cfn-nag/cfn_nag.rb b/lib/cfn-nag/cfn_nag.rb +index 4fc619b..7a83c3d 100644 +--- a/lib/cfn-nag/cfn_nag.rb ++++ b/lib/cfn-nag/cfn_nag.rb +@@ -85,7 +85,8 @@ class CfnNag + + begin + cfn_model = CfnParser.new.parse cloudformation_string, +- parameter_values_string ++ parameter_values_string, ++ true # With line numbers + violations += @custom_rule_loader.execute_custom_rules(cfn_model) + + violations = filter_violations_by_blacklist_and_profile(violations) +diff --git a/lib/cfn-nag/custom_rules/SecurityGroupIngressCidrNon32Rule.rb b/lib/cfn-nag/custom_rules/SecurityGroupIngressCidrNon32Rule.rb +index c9d28e7..1e712a5 100644 +--- a/lib/cfn-nag/custom_rules/SecurityGroupIngressCidrNon32Rule.rb ++++ b/lib/cfn-nag/custom_rules/SecurityGroupIngressCidrNon32Rule.rb +@@ -24,7 +24,11 @@ class SecurityGroupIngressCidrNon32Rule < BaseRule + # targeted against inline ingress only + def audit_impl(cfn_model) + violating_security_groups = cfn_model.security_groups.select do |security_group| ++ puts security_group + violating_ingresses = security_group.ingresses.select do |ingress| ++ puts "########################" ++ puts ingress ++ puts "########################" + ip4_cidr_range?(ingress) || ip6_cidr_range?(ingress) + end + +@@ -32,6 +36,7 @@ class SecurityGroupIngressCidrNon32Rule < BaseRule + end + + violating_ingresses = cfn_model.standalone_ingress.select do |standalone_ingress| ++ standalone_ingress = standalone_ingress['value'] + ip4_cidr_range?(standalone_ingress) || ip6_cidr_range?(standalone_ingress) + end + +diff --git a/lib/cfn-nag/ip_addr.rb b/lib/cfn-nag/ip_addr.rb +index 979e0f0..3321da4 100644 +--- a/lib/cfn-nag/ip_addr.rb ++++ b/lib/cfn-nag/ip_addr.rb +@@ -20,6 +20,9 @@ module IpAddr + end + + def ip4_cidr_range?(ingress) ++ puts "#{ingress.methods}" ++ puts "|#{ingress.cidrIp.class}|" ++ puts "|#{ingress.cidrIp}|" + ingress.cidrIp.is_a?(String) && !ingress.cidrIp.end_with?('/32') + end + +diff --git a/publish.sh b/publish.sh +index 490bc45..cc67d18 100755 +--- a/publish.sh ++++ b/publish.sh +@@ -86,6 +86,6 @@ fi + gem build cfn-nag.gemspec + gem push cfn-nag-${GEM_VERSION}.gem + +-docker build -t essej2003/cfn_nag:${GEM_VERSION} . ++docker build -t $docker_org/cfn_nag:${GEM_VERSION} . + echo $docker_password | docker login -u $docker_user --password-stdin +-docker push essej2003/cfn_nag:${GEM_VERSION} ++docker push $docker_org/cfn_nag:${GEM_VERSION} +diff --git a/spec/cfn_nag_integration/cfn_nag_cloudfront_distribution_spec.rb b/spec/cfn_nag_integration/cfn_nag_cloudfront_distribution_spec.rb +index 9c0e8e5..d133312 100644 +--- a/spec/cfn_nag_integration/cfn_nag_cloudfront_distribution_spec.rb ++++ b/spec/cfn_nag_integration/cfn_nag_cloudfront_distribution_spec.rb +@@ -20,7 +20,7 @@ describe CfnNag do + Violation.new( + id: 'W10', type: Violation::WARNING, + message: 'CloudFront Distribution should enable access logging', +- logical_resource_ids: %w[rDistribution2] ++ logical_resource_ids: [{ name: 'rDistribution2', line: 46 }] + ) + ] + } +diff --git a/spec/cfn_nag_integration/cfn_nag_ec2_volume_spec.rb b/spec/cfn_nag_integration/cfn_nag_ec2_volume_spec.rb +index dfae2bf..230c44a 100644 +--- a/spec/cfn_nag_integration/cfn_nag_ec2_volume_spec.rb ++++ b/spec/cfn_nag_integration/cfn_nag_ec2_volume_spec.rb +@@ -21,7 +21,16 @@ describe CfnNag do + id: 'F1', type: Violation::FAILING_VIOLATION, + message: + 'EBS volume should have server-side encryption enabled', +- logical_resource_ids: %w[NewVolume1 NewVolume2] ++ logical_resource_ids: [ ++ { ++ name: 'NewVolume1', ++ line: 4 ++ }, ++ { ++ name: 'NewVolume2', ++ line: 13 ++ } ++ ] + ) + ] + } +diff --git a/spec/cfn_nag_integration/cfn_nag_elasticloadbalancing_loadbalancer_spec.rb b/spec/cfn_nag_integration/cfn_nag_elasticloadbalancing_loadbalancer_spec.rb +index 981321e..dc70b65 100644 +--- a/spec/cfn_nag_integration/cfn_nag_elasticloadbalancing_loadbalancer_spec.rb ++++ b/spec/cfn_nag_integration/cfn_nag_elasticloadbalancing_loadbalancer_spec.rb +@@ -21,7 +21,16 @@ describe CfnNag do + id: 'W26', type: Violation::WARNING, + message: + 'Elastic Load Balancer should have access logging enabled', +- logical_resource_ids: %w[elb1 elb2] ++ logical_resource_ids: [ ++ { ++ name: 'elb1', ++ line: 4 ++ }, ++ { ++ name: 'elb2', ++ line: 19 ++ } ++ ] + ) + ] + } +diff --git a/spec/cfn_nag_integration/cfn_nag_iam_user_spec.rb b/spec/cfn_nag_integration/cfn_nag_iam_user_spec.rb +index 42d1cf6..69cf998 100644 +--- a/spec/cfn_nag_integration/cfn_nag_iam_user_spec.rb ++++ b/spec/cfn_nag_integration/cfn_nag_iam_user_spec.rb +@@ -21,7 +21,7 @@ describe CfnNag do + Violation.new(id: 'F2000', + type: Violation::FAILING_VIOLATION, + message: 'User is not assigned to a group', +- logical_resource_ids: %w[myuser2]) ++ logical_resource_ids: [{ name: 'myuser2', line: 4 }]) + ] + } + } +diff --git a/spec/cfn_nag_integration/cfn_nag_lambda_permission_spec.rb b/spec/cfn_nag_integration/cfn_nag_lambda_permission_spec.rb +index ae6dbec..2ee96a4 100644 +--- a/spec/cfn_nag_integration/cfn_nag_lambda_permission_spec.rb ++++ b/spec/cfn_nag_integration/cfn_nag_lambda_permission_spec.rb +@@ -20,15 +20,15 @@ describe CfnNag do + Violation.new(id: 'F3', + type: Violation::FAILING_VIOLATION, + message: 'IAM role should not allow * action on its permissions policy', +- logical_resource_ids: %w[LambdaExecutionRole]), ++ logical_resource_ids: [{ name: 'LambdaExecutionRole', line: 49 }]), + Violation.new(id: 'W11', + type: Violation::WARNING, + message: 'IAM role should not allow * resource on its permissions policy', +- logical_resource_ids: %w[LambdaExecutionRole]), ++ logical_resource_ids: [{ name: 'LambdaExecutionRole', line: 49 }]), + Violation.new(id: 'F13', + type: Violation::FAILING_VIOLATION, + message: 'Lambda permission principal should not be wildcard', +- logical_resource_ids: %w[lambdaPermission]) ++ logical_resource_ids: [{ name: 'lambdaPermission', line: 23 }]) + ] + } + } +diff --git a/spec/cfn_nag_integration/cfn_nag_rds_instance_spec.rb b/spec/cfn_nag_integration/cfn_nag_rds_instance_spec.rb +index a9f61e9..a316eaf 100644 +--- a/spec/cfn_nag_integration/cfn_nag_rds_instance_spec.rb ++++ b/spec/cfn_nag_integration/cfn_nag_rds_instance_spec.rb +@@ -21,7 +21,7 @@ describe CfnNag do + type: Violation::FAILING_VIOLATION, + message: + 'RDS instance should not be publicly accessible', +- logical_resource_ids: %w[PublicDB]) ++ logical_resource_ids: [{ name: 'PublicDB', line: 4}]) + ] + } + } +@@ -45,13 +45,13 @@ describe CfnNag do + Violation.new( + id: 'F23', type: Violation::FAILING_VIOLATION, + message: 'RDS instance master user password must be Ref to NoEcho Parameter. Default credentials are not recommended', +- logical_resource_ids: %w[BadDb2] ++ logical_resource_ids: [{ name: 'BadDb2', line: 11 }] + ), + Violation.new(id: 'F22', + type: Violation::FAILING_VIOLATION, + message: + 'RDS instance should not be publicly accessible', +- logical_resource_ids: %w[BadDb2]) ++ logical_resource_ids: [{ name: 'BadDb2', line: 11 }]) + ] + } + } +@@ -76,12 +76,30 @@ describe CfnNag do + Violation.new( + id: 'F23', type: Violation::FAILING_VIOLATION, + message: 'RDS instance master user password must be Ref to NoEcho Parameter. Default credentials are not recommended', +- logical_resource_ids: %w[BadDb1 BadDb2] ++ logical_resource_ids: [ ++ { ++ name: 'BadDb1', ++ line: 14 ++ }, ++ { ++ name: 'BadDb2', ++ line: 28 ++ } ++ ] + ), + Violation.new( + id: 'F24', type: Violation::FAILING_VIOLATION, + message: 'RDS instance master username must be Ref to NoEcho Parameter. Default credentials are not recommended', +- logical_resource_ids: %w[BadDb1 BadDb2] ++ logical_resource_ids: [ ++ { ++ name: 'BadDb1', ++ line: 14 ++ }, ++ { ++ name: 'BadDb2', ++ line: 28 ++ } ++ ] + ) + ] + } +diff --git a/spec/cfn_nag_integration/cfn_nag_s3_bucket_policy_spec.rb b/spec/cfn_nag_integration/cfn_nag_s3_bucket_policy_spec.rb +index 91d15ca..1ab5836 100644 +--- a/spec/cfn_nag_integration/cfn_nag_s3_bucket_policy_spec.rb ++++ b/spec/cfn_nag_integration/cfn_nag_s3_bucket_policy_spec.rb +@@ -21,13 +21,23 @@ describe CfnNag do + type: Violation::FAILING_VIOLATION, + message: + 'S3 Bucket policy should not allow * action', +- logical_resource_ids: +- %w[S3BucketPolicy S3BucketPolicy2]), ++ logical_resource_ids: [ ++ { ++ name: 'S3BucketPolicy', ++ line: 25 ++ }, ++ { ++ name: 'S3BucketPolicy2', ++ line: 50 ++ } ++ ] ++ ), + Violation.new(id: 'F16', + type: Violation::FAILING_VIOLATION, + message: + 'S3 Bucket policy should not allow * principal', +- logical_resource_ids: %w[S3BucketPolicy2]) ++ logical_resource_ids: [{ name: 'S3BucketPolicy2', line: 50 }] ++ ) + ] + } + } +diff --git a/spec/cfn_nag_integration/cfn_nag_s3_bucket_spec.rb b/spec/cfn_nag_integration/cfn_nag_s3_bucket_spec.rb +index c0f8003..f67f748 100644 +--- a/spec/cfn_nag_integration/cfn_nag_s3_bucket_spec.rb ++++ b/spec/cfn_nag_integration/cfn_nag_s3_bucket_spec.rb +@@ -20,13 +20,14 @@ describe CfnNag do + Violation.new( + id: 'W31', type: Violation::WARNING, + message: 'S3 Bucket likely should not have a public read acl', +- logical_resource_ids: %w[S3BucketRead] ++ logical_resource_ids: [{ name: 'S3BucketRead', line: 4 }] + ), + Violation.new(id: 'F14', + type: Violation::FAILING_VIOLATION, + message: + 'S3 Bucket should not have a public read-write acl', +- logical_resource_ids: %w[S3BucketReadWrite]) ++ logical_resource_ids: [{ name: 'S3BucketReadWrite', line: 12 }] ++ ) + ] + } + } +diff --git a/spec/cfn_nag_integration/cfn_nag_security_group_spec.rb b/spec/cfn_nag_integration/cfn_nag_security_group_spec.rb +index 1b72c79..2dd0e27 100644 +--- a/spec/cfn_nag_integration/cfn_nag_security_group_spec.rb ++++ b/spec/cfn_nag_integration/cfn_nag_security_group_spec.rb +@@ -48,7 +48,7 @@ describe CfnNag do + Violation.new( + id: 'F1000', type: Violation::FAILING_VIOLATION, + message: 'Missing egress rule means all traffic is allowed outbound. Make this explicit if it is desired configuration', +- logical_resource_ids: %w[sg] ++ logical_resource_ids: [{ name: 'sg', line: 4 }] + ) + ] + } +@@ -74,22 +74,40 @@ describe CfnNag do + Violation.new( + id: 'W9', type: Violation::WARNING, + message: 'Security Groups found with ingress cidr that is not /32', +- logical_resource_ids: %w[sg2] ++ logical_resource_ids: [{ name: 'sg2', line: 18 }] + ), + Violation.new( + id: 'W2', type: Violation::WARNING, + message: 'Security Groups found with cidr open to world on ingress. This should never be true on instance. Permissible on ELB', +- logical_resource_ids: %w[sg2] ++ logical_resource_ids: [{ name: 'sg2', line: 18 }] + ), + Violation.new( + id: 'W27', type: Violation::WARNING, + message: 'Security Groups found ingress with port range instead of just a single port', +- logical_resource_ids: %w[sg sg2] ++ logical_resource_ids: [ ++ { ++ name: 'sg', ++ line: 4 ++ }, ++ { ++ name: 'sg2', ++ line: 18 ++ } ++ ] + ), + Violation.new( + id: 'F1000', type: Violation::FAILING_VIOLATION, + message: 'Missing egress rule means all traffic is allowed outbound. Make this explicit if it is desired configuration', +- logical_resource_ids: %w[sg sg2] ++ logical_resource_ids: [ ++ { ++ name: 'sg', ++ line: 4 ++ }, ++ { ++ name: 'sg2', ++ line: 18 ++ } ++ ] + ) + ] + } +@@ -140,7 +158,7 @@ describe CfnNag do + id: 'W9', type: Violation::WARNING, + message: + 'Security Groups found with ingress cidr that is not /32', +- logical_resource_ids: %w[sg] ++ logical_resource_ids: [{ name: 'sg', line: 4 }] + ) + ] + } +@@ -169,7 +187,16 @@ describe CfnNag do + id: 'W9', type: Violation::WARNING, + message: + 'Security Groups found with ingress cidr that is not /32', +- logical_resource_ids: %w[sg sg2] ++ logical_resource_ids: [ ++ { ++ name: 'sg', ++ line: 10 ++ }, ++ { ++ name: 'sg2', ++ line: 30 ++ } ++ ] + ) + ] + } +diff --git a/spec/cfn_nag_integration/cfn_nag_sns_policy_spec.rb b/spec/cfn_nag_integration/cfn_nag_sns_policy_spec.rb +index 842f2b9..bd79c48 100644 +--- a/spec/cfn_nag_integration/cfn_nag_sns_policy_spec.rb ++++ b/spec/cfn_nag_integration/cfn_nag_sns_policy_spec.rb +@@ -22,8 +22,24 @@ describe CfnNag do + Violation.new( + id: 'F18', type: Violation::FAILING_VIOLATION, + message: 'SNS topic policy should not allow * principal', +- logical_resource_ids: %w[mysnspolicy0 mysnspolicy1 +- mysnspolicy2 mysnspolicy3] ++ logical_resource_ids: [ ++ { ++ name: 'mysnspolicy0', ++ line: 10 ++ }, ++ { ++ name: 'mysnspolicy1', ++ line: 28 ++ }, ++ { ++ name: 'mysnspolicy2', ++ line: 53 ++ }, ++ { ++ name: 'mysnspolicy3', ++ line: 83 ++ } ++ ] + ) + ] + } +diff --git a/spec/cfn_nag_integration/cfn_nag_sqs_policy_spec.rb b/spec/cfn_nag_integration/cfn_nag_sqs_policy_spec.rb +index dbd066f..dfabd76 100644 +--- a/spec/cfn_nag_integration/cfn_nag_sqs_policy_spec.rb ++++ b/spec/cfn_nag_integration/cfn_nag_sqs_policy_spec.rb +@@ -21,8 +21,16 @@ describe CfnNag do + Violation.new( + id: 'W18', type: Violation::WARNING, + message: 'SQS Queue policy should not allow Allow+NotAction', +- logical_resource_ids: %w[QueuePolicyWithNotAction +- QueuePolicyWithNotAction2] ++ logical_resource_ids: [ ++ { ++ name: 'QueuePolicyWithNotAction', ++ line: 18 ++ }, ++ { ++ name: 'QueuePolicyWithNotAction2', ++ line: 35 ++ } ++ ] + ) + ] + } +diff --git a/spec/cfn_nag_spec.rb b/spec/cfn_nag_spec.rb +index 7dc81a4..8eb8f62 100644 +--- a/spec/cfn_nag_spec.rb ++++ b/spec/cfn_nag_spec.rb +@@ -107,7 +107,7 @@ describe CfnNag do + Violation.new( + id: 'F16', type: Violation::FAILING_VIOLATION, + message: 'S3 Bucket policy should not allow * principal', +- logical_resource_ids: %w[S3BucketPolicy2] ++ logical_resource_ids: [{ name: 'S3BucketPolicy2', line: 50 }] + ) + ] + } diff --git a/local.txt b/local.txt new file mode 100644 index 00000000..86d76e9a --- /dev/null +++ b/local.txt @@ -0,0 +1,28 @@ +ast (2.4.0) +bundler (1.16.6) +cfn-model (0.1.29) +cfn-nag (0.0.0) +diff-lcs (1.3) +docile (1.3.1) +jaro_winkler (1.5.2) +jmespath (1.3.1) +json (2.2.0) +kwalify (0.7.2) +little-plugger (1.1.4) +logging (2.2.2) +multi_json (1.13.1) +netaddr (1.5.1) +parallel (1.17.0) +parser (2.6.3.0) +rainbow (3.0.0) +rspec (3.8.0) +rspec-core (3.8.0) +rspec-expectations (3.8.3) +rspec-mocks (3.8.0) +rspec-support (3.8.0) +rubocop (0.68.1) +ruby-progressbar (1.10.0) +simplecov (0.16.1) +simplecov-html (0.10.2) +trollop (2.1.3) +unicode-display_width (1.5.0) diff --git a/publish.sh.orig b/publish.sh.orig new file mode 100755 index 00000000..2d6f6104 --- /dev/null +++ b/publish.sh.orig @@ -0,0 +1,77 @@ +#!/bin/bash -ex +set -o pipefail + +set +x +if [[ -z ${rubygems_api_key} ]]; +then + echo rubygems_api_key must be set in the environment + exit 1 +fi +set -x + +git config --global user.email "build@build.com" +git config --global user.name "build" + +mkdir -p ~/.gem + +set +ex +echo :rubygems_api_key: ${rubygems_api_key} > ~/.gem/credentials +set -ex +chmod 0600 ~/.gem/credentials + +# git describe returns the latest tag +current_tag=$(git describe) + +# Check if '-' in git describe. If so, we +# have advanced past the latest tag (and will +# need to compute new version) +tagged_commit=1 +if echo $current_tag | grep -q '-'; then + tagged_commit=0 +fi + +# strip off initial 'v' and everything after digits and . +current_version=$(git describe | sed 's/^\(v\)\([0-9.]*\).*$/\2/') +# strip .### from end to get major.minor version +current_minor=$(echo $current_version | sed 's/\.\([0-9]*\)$//') +# get third dotted field for patch version +current_patch=$(echo $current_version | cut -f 3 -d . ) + +if [[ ${current_version} == nil ]]; +then + # No version determined from tag, assume 0.0.0 + GEM_VERSION='0.0.0' +elif [ $tagged_commit = 1 ]; then + # Current commit was tagged with version, use it + GEM_VERSION=$current_version +else + # Current commit was goes past a tag, increment patch + GEM_VERSION="$current_minor."$((current_patch + 1)) +fi + +export GEM_VERSION + +#on circle ci - head is ambiguous for reasons that i don't grok +#we haven't made the new tag and we can't if we are going to annotate +head=$(git rev-parse HEAD) + +issue_prefix='^#' +echo "Remember! You need to start your commit messages with #{issue_prefix}x, where x is the issue number your commit resolves." + +if [[ ${current_version} == nil ]]; +then + log_rev_range=${head} +else + log_rev_range="v${current_version}..${head}" +fi + +export issues=""$(git log ${log_rev_range} --oneline | awk '{print $2}' | grep "${issue_prefix}" | uniq) + +if [ $tagged_commit = 0 ]; then + git tag -a "v${GEM_VERSION}" -m "${GEM_VERSION}" -m "Issues with commits, not necessarily closed: ${issues}" + git push --tags +fi + +# gemspec respects GEM_VERSION envvar +gem build cfn-nag.gemspec +gem push cfn-nag-${GEM_VERSION}.gem diff --git a/publish.sh.rej b/publish.sh.rej new file mode 100644 index 00000000..2b6fd0a1 --- /dev/null +++ b/publish.sh.rej @@ -0,0 +1,15 @@ +*************** +*** 86,91 **** + gem build cfn-nag.gemspec + gem push cfn-nag-${GEM_VERSION}.gem + +- docker build -t essej2003/cfn_nag:${GEM_VERSION} . + echo $docker_password | docker login -u $docker_user --password-stdin +- docker push essej2003/cfn_nag:${GEM_VERSION} +--- 86,91 ---- + gem build cfn-nag.gemspec + gem push cfn-nag-${GEM_VERSION}.gem + ++ docker build -t $docker_org/cfn_nag:${GEM_VERSION} . + echo $docker_password | docker login -u $docker_user --password-stdin ++ docker push $docker_org/cfn_nag:${GEM_VERSION} diff --git a/spec/cfn_nag_integration/cfn_nag_cloudfront_distribution_spec.rb b/spec/cfn_nag_integration/cfn_nag_cloudfront_distribution_spec.rb index 9c0e8e56..3ac1bc10 100644 --- a/spec/cfn_nag_integration/cfn_nag_cloudfront_distribution_spec.rb +++ b/spec/cfn_nag_integration/cfn_nag_cloudfront_distribution_spec.rb @@ -20,7 +20,8 @@ Violation.new( id: 'W10', type: Violation::WARNING, message: 'CloudFront Distribution should enable access logging', - logical_resource_ids: %w[rDistribution2] + logical_resource_ids: %w[rDistribution2], + line_numbers: [46] ) ] } diff --git a/spec/cfn_nag_integration/cfn_nag_ec2_instance_spec.rb b/spec/cfn_nag_integration/cfn_nag_ec2_instance_spec.rb index e362276c..96b62476 100644 --- a/spec/cfn_nag_integration/cfn_nag_ec2_instance_spec.rb +++ b/spec/cfn_nag_integration/cfn_nag_ec2_instance_spec.rb @@ -20,7 +20,8 @@ Violation.new( id: 'W1', type: Violation::WARNING, message: 'Specifying credentials in the template itself is probably not the safest thing', - logical_resource_ids: %w[EC2I4LBA1] + logical_resource_ids: %w[EC2I4LBA1], + line_numbers: [11] ) ] } diff --git a/spec/cfn_nag_integration/cfn_nag_ec2_volume_spec.rb b/spec/cfn_nag_integration/cfn_nag_ec2_volume_spec.rb index dfae2bf1..ffe98715 100644 --- a/spec/cfn_nag_integration/cfn_nag_ec2_volume_spec.rb +++ b/spec/cfn_nag_integration/cfn_nag_ec2_volume_spec.rb @@ -21,7 +21,8 @@ id: 'F1', type: Violation::FAILING_VIOLATION, message: 'EBS volume should have server-side encryption enabled', - logical_resource_ids: %w[NewVolume1 NewVolume2] + logical_resource_ids: %w[NewVolume1 NewVolume2], + line_numbers: [4, 13] ) ] } diff --git a/spec/cfn_nag_integration/cfn_nag_elasticloadbalancing_loadbalancer_spec.rb b/spec/cfn_nag_integration/cfn_nag_elasticloadbalancing_loadbalancer_spec.rb index 981321e0..5abd7dc9 100644 --- a/spec/cfn_nag_integration/cfn_nag_elasticloadbalancing_loadbalancer_spec.rb +++ b/spec/cfn_nag_integration/cfn_nag_elasticloadbalancing_loadbalancer_spec.rb @@ -21,7 +21,8 @@ id: 'W26', type: Violation::WARNING, message: 'Elastic Load Balancer should have access logging enabled', - logical_resource_ids: %w[elb1 elb2] + logical_resource_ids: %w[elb1 elb2], + line_numbers: [4, 19] ) ] } diff --git a/spec/cfn_nag_integration/cfn_nag_iam_user_spec.rb b/spec/cfn_nag_integration/cfn_nag_iam_user_spec.rb index 42d1cf63..2a24fd40 100644 --- a/spec/cfn_nag_integration/cfn_nag_iam_user_spec.rb +++ b/spec/cfn_nag_integration/cfn_nag_iam_user_spec.rb @@ -21,7 +21,8 @@ Violation.new(id: 'F2000', type: Violation::FAILING_VIOLATION, message: 'User is not assigned to a group', - logical_resource_ids: %w[myuser2]) + logical_resource_ids: %w[myuser2], + line_numbers: [4]) ] } } diff --git a/spec/cfn_nag_integration/cfn_nag_lambda_permission_spec.rb b/spec/cfn_nag_integration/cfn_nag_lambda_permission_spec.rb index 0aa6902e..170d2574 100644 --- a/spec/cfn_nag_integration/cfn_nag_lambda_permission_spec.rb +++ b/spec/cfn_nag_integration/cfn_nag_lambda_permission_spec.rb @@ -20,15 +20,18 @@ Violation.new(id: 'F3', type: Violation::FAILING_VIOLATION, message: 'IAM role should not allow * action on its permissions policy', - logical_resource_ids: %w[LambdaExecutionRole]), + logical_resource_ids: %w[LambdaExecutionRole], + line_numbers: [49]), Violation.new(id: 'W11', type: Violation::WARNING, message: 'IAM role should not allow * resource on its permissions policy', - logical_resource_ids: %w[LambdaExecutionRole]), + logical_resource_ids: %w[LambdaExecutionRole], + line_numbers: [49]), Violation.new(id: 'F13', type: Violation::FAILING_VIOLATION, message: 'Lambda permission principal should not be wildcard', - logical_resource_ids: %w[lambdaPermission]) + logical_resource_ids: %w[lambdaPermission], + line_numbers: [23]) ] } } diff --git a/spec/cfn_nag_integration/cfn_nag_rds_instance_spec.rb b/spec/cfn_nag_integration/cfn_nag_rds_instance_spec.rb index a9f61e94..0592e2b1 100644 --- a/spec/cfn_nag_integration/cfn_nag_rds_instance_spec.rb +++ b/spec/cfn_nag_integration/cfn_nag_rds_instance_spec.rb @@ -21,7 +21,8 @@ type: Violation::FAILING_VIOLATION, message: 'RDS instance should not be publicly accessible', - logical_resource_ids: %w[PublicDB]) + logical_resource_ids: %w[PublicDB], + line_numbers: [4]) ] } } @@ -45,13 +46,15 @@ Violation.new( id: 'F23', type: Violation::FAILING_VIOLATION, message: 'RDS instance master user password must be Ref to NoEcho Parameter. Default credentials are not recommended', - logical_resource_ids: %w[BadDb2] + logical_resource_ids: %w[BadDb2], + line_numbers: [11] ), Violation.new(id: 'F22', type: Violation::FAILING_VIOLATION, message: 'RDS instance should not be publicly accessible', - logical_resource_ids: %w[BadDb2]) + logical_resource_ids: %w[BadDb2], + line_numbers: [11]) ] } } @@ -76,12 +79,14 @@ Violation.new( id: 'F23', type: Violation::FAILING_VIOLATION, message: 'RDS instance master user password must be Ref to NoEcho Parameter. Default credentials are not recommended', - logical_resource_ids: %w[BadDb1 BadDb2] + logical_resource_ids: %w[BadDb1 BadDb2], + line_numbers: [14, 28] ), Violation.new( id: 'F24', type: Violation::FAILING_VIOLATION, message: 'RDS instance master username must be Ref to NoEcho Parameter. Default credentials are not recommended', - logical_resource_ids: %w[BadDb1 BadDb2] + logical_resource_ids: %w[BadDb1 BadDb2], + line_numbers: [14, 28] ) ] } diff --git a/spec/cfn_nag_integration/cfn_nag_s3_bucket_policy_spec.rb b/spec/cfn_nag_integration/cfn_nag_s3_bucket_policy_spec.rb index 91d15caf..6dbdaf2b 100644 --- a/spec/cfn_nag_integration/cfn_nag_s3_bucket_policy_spec.rb +++ b/spec/cfn_nag_integration/cfn_nag_s3_bucket_policy_spec.rb @@ -21,13 +21,14 @@ type: Violation::FAILING_VIOLATION, message: 'S3 Bucket policy should not allow * action', - logical_resource_ids: - %w[S3BucketPolicy S3BucketPolicy2]), + logical_resource_ids: %w[S3BucketPolicy S3BucketPolicy2], + line_numbers: [25, 50]), Violation.new(id: 'F16', type: Violation::FAILING_VIOLATION, message: 'S3 Bucket policy should not allow * principal', - logical_resource_ids: %w[S3BucketPolicy2]) + logical_resource_ids: %w[S3BucketPolicy2], + line_numbers: [50]) ] } } diff --git a/spec/cfn_nag_integration/cfn_nag_s3_bucket_spec.rb b/spec/cfn_nag_integration/cfn_nag_s3_bucket_spec.rb index c0f80038..1a9fd715 100644 --- a/spec/cfn_nag_integration/cfn_nag_s3_bucket_spec.rb +++ b/spec/cfn_nag_integration/cfn_nag_s3_bucket_spec.rb @@ -20,13 +20,15 @@ Violation.new( id: 'W31', type: Violation::WARNING, message: 'S3 Bucket likely should not have a public read acl', - logical_resource_ids: %w[S3BucketRead] + logical_resource_ids: %w[S3BucketRead], + line_numbers: [4] ), Violation.new(id: 'F14', type: Violation::FAILING_VIOLATION, message: 'S3 Bucket should not have a public read-write acl', - logical_resource_ids: %w[S3BucketReadWrite]) + logical_resource_ids: %w[S3BucketReadWrite], + line_numbers: [12]) ] } } diff --git a/spec/cfn_nag_integration/cfn_nag_security_group_spec.rb b/spec/cfn_nag_integration/cfn_nag_security_group_spec.rb index 1b72c791..bd12d135 100644 --- a/spec/cfn_nag_integration/cfn_nag_security_group_spec.rb +++ b/spec/cfn_nag_integration/cfn_nag_security_group_spec.rb @@ -48,7 +48,8 @@ Violation.new( id: 'F1000', type: Violation::FAILING_VIOLATION, message: 'Missing egress rule means all traffic is allowed outbound. Make this explicit if it is desired configuration', - logical_resource_ids: %w[sg] + logical_resource_ids: %w[sg], + line_numbers: [4] ) ] } @@ -74,22 +75,26 @@ Violation.new( id: 'W9', type: Violation::WARNING, message: 'Security Groups found with ingress cidr that is not /32', - logical_resource_ids: %w[sg2] + logical_resource_ids: %w[sg2], + line_numbers: [18] ), Violation.new( id: 'W2', type: Violation::WARNING, message: 'Security Groups found with cidr open to world on ingress. This should never be true on instance. Permissible on ELB', - logical_resource_ids: %w[sg2] + logical_resource_ids: %w[sg2], + line_numbers: [18] ), Violation.new( id: 'W27', type: Violation::WARNING, message: 'Security Groups found ingress with port range instead of just a single port', - logical_resource_ids: %w[sg sg2] + logical_resource_ids: %w[sg sg2], + line_numbers: [4, 18] ), Violation.new( id: 'F1000', type: Violation::FAILING_VIOLATION, message: 'Missing egress rule means all traffic is allowed outbound. Make this explicit if it is desired configuration', - logical_resource_ids: %w[sg sg2] + logical_resource_ids: %w[sg sg2], + line_numbers: [4, 18] ) ] } @@ -140,7 +145,8 @@ id: 'W9', type: Violation::WARNING, message: 'Security Groups found with ingress cidr that is not /32', - logical_resource_ids: %w[sg] + logical_resource_ids: %w[sg], + line_numbers: [10] ) ] } @@ -169,7 +175,8 @@ id: 'W9', type: Violation::WARNING, message: 'Security Groups found with ingress cidr that is not /32', - logical_resource_ids: %w[sg sg2] + logical_resource_ids: %w[sg sg2], + line_numbers: [10, 30] ) ] } diff --git a/spec/cfn_nag_integration/cfn_nag_sns_policy_spec.rb b/spec/cfn_nag_integration/cfn_nag_sns_policy_spec.rb index 842f2b9c..c18938d1 100644 --- a/spec/cfn_nag_integration/cfn_nag_sns_policy_spec.rb +++ b/spec/cfn_nag_integration/cfn_nag_sns_policy_spec.rb @@ -23,7 +23,8 @@ id: 'F18', type: Violation::FAILING_VIOLATION, message: 'SNS topic policy should not allow * principal', logical_resource_ids: %w[mysnspolicy0 mysnspolicy1 - mysnspolicy2 mysnspolicy3] + mysnspolicy2 mysnspolicy3], + line_numbers: [10, 28, 53, 83] ) ] } diff --git a/spec/cfn_nag_integration/cfn_nag_sqs_policy_spec.rb b/spec/cfn_nag_integration/cfn_nag_sqs_policy_spec.rb index dbd066f4..fc7d2ed6 100644 --- a/spec/cfn_nag_integration/cfn_nag_sqs_policy_spec.rb +++ b/spec/cfn_nag_integration/cfn_nag_sqs_policy_spec.rb @@ -22,7 +22,8 @@ id: 'W18', type: Violation::WARNING, message: 'SQS Queue policy should not allow Allow+NotAction', logical_resource_ids: %w[QueuePolicyWithNotAction - QueuePolicyWithNotAction2] + QueuePolicyWithNotAction2], + line_numbers: [18, 35] ) ] } diff --git a/spec/cfn_nag_spec.rb b/spec/cfn_nag_spec.rb index 7dc81a4e..0b03af91 100644 --- a/spec/cfn_nag_spec.rb +++ b/spec/cfn_nag_spec.rb @@ -107,7 +107,8 @@ Violation.new( id: 'F16', type: Violation::FAILING_VIOLATION, message: 'S3 Bucket policy should not allow * principal', - logical_resource_ids: %w[S3BucketPolicy2] + logical_resource_ids: %w[S3BucketPolicy2], + line_numbers: [50] ) ] } @@ -147,17 +148,20 @@ Violation.new( id: 'W9', type: Violation::WARNING, message: 'Security Groups found with ingress cidr that is not /32', - logical_resource_ids: %w[sgOpenIngress] + logical_resource_ids: %w[sgOpenIngress], + line_numbers: [4] ), Violation.new( id: 'W2', type: Violation::WARNING, message: 'Security Groups found with cidr open to world on ingress. This should never be true on instance. Permissible on ELB', - logical_resource_ids: %w[sgOpenIngress] + logical_resource_ids: %w[sgOpenIngress], + line_numbers: [4] ), Violation.new( id: 'F1000', type: Violation::FAILING_VIOLATION, message: 'Missing egress rule means all traffic is allowed outbound. Make this explicit if it is desired configuration', - logical_resource_ids: %w[sgOpenIngress] + logical_resource_ids: %w[sgOpenIngress], + line_numbers: [4] ) ] } @@ -196,17 +200,20 @@ Violation.new( id: 'W9', type: Violation::WARNING, message: 'Security Groups found with ingress cidr that is not /32', - logical_resource_ids: %w[sgOpenIngress sgOpenIngress2] + logical_resource_ids: %w[sgOpenIngress sgOpenIngress2], + line_numbers: [ 4, 20] ), Violation.new( id: 'W2', type: Violation::WARNING, message: 'Security Groups found with cidr open to world on ingress. This should never be true on instance. Permissible on ELB', - logical_resource_ids: %w[sgOpenIngress sgOpenIngress2] + logical_resource_ids: %w[sgOpenIngress sgOpenIngress2], + line_numbers: [4, 20] ), Violation.new( id: 'F1000', type: Violation::FAILING_VIOLATION, message: 'Missing egress rule means all traffic is allowed outbound. Make this explicit if it is desired configuration', - logical_resource_ids: %w[sgOpenIngress sgOpenIngress2] + logical_resource_ids: %w[sgOpenIngress sgOpenIngress2], + line_numbers: [4, 20] ) ] } diff --git a/spec/test_templates/yaml/foo.sh b/spec/test_templates/yaml/foo.sh new file mode 100644 index 00000000..988d10a6 --- /dev/null +++ b/spec/test_templates/yaml/foo.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +echo "Foo!" diff --git a/spec/test_templates/yaml/screwyou.yml b/spec/test_templates/yaml/screwyou.yml new file mode 100644 index 00000000..88b1d02c --- /dev/null +++ b/spec/test_templates/yaml/screwyou.yml @@ -0,0 +1,2 @@ +--- +Foo: Bar diff --git a/spec/test_templates/yaml/security_group/sg_with_suppression.yml b/spec/test_templates/yaml/security_group/sg_with_suppression.yml index 17af444f..8df36933 100644 --- a/spec/test_templates/yaml/security_group/sg_with_suppression.yml +++ b/spec/test_templates/yaml/security_group/sg_with_suppression.yml @@ -16,7 +16,6 @@ Resources: ToPort: 46 IpProtocol: tcp - sgOpenIngress2: Type: AWS::EC2::SecurityGroup Properties: