cfn-nag 0.7.15 → 0.8.2

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 (78) hide show
  1. checksums.yaml +4 -4
  2. data/bin/cfn_nag_rules +3 -3
  3. data/bin/spcm_scan +1 -1
  4. data/lib/cfn-nag/base_rule.rb +7 -1
  5. data/lib/cfn-nag/cfn_nag.rb +16 -20
  6. data/lib/cfn-nag/cfn_nag_config.rb +3 -3
  7. data/lib/cfn-nag/cfn_nag_executor.rb +7 -7
  8. data/lib/cfn-nag/cli_options.rb +19 -8
  9. data/lib/cfn-nag/custom_rules/AlexaASKSkillAuthenticationConfigurationClientSecretRule.rb +1 -1
  10. data/lib/cfn-nag/custom_rules/AlexaASKSkillAuthenticationConfigurationRefreshTokenRule.rb +1 -1
  11. data/lib/cfn-nag/custom_rules/AmazonMQBrokerUsersPasswordRule.rb +1 -1
  12. data/lib/cfn-nag/custom_rules/AmplifyAppAccessTokenRule.rb +2 -2
  13. data/lib/cfn-nag/custom_rules/AmplifyAppBasicAuthConfigPasswordRule.rb +2 -2
  14. data/lib/cfn-nag/custom_rules/AmplifyAppOauthTokenRule.rb +2 -2
  15. data/lib/cfn-nag/custom_rules/AmplifyBranchBasicAuthConfigPasswordRule.rb +2 -2
  16. data/lib/cfn-nag/custom_rules/ApiGatewayAccessLoggingRule.rb +1 -1
  17. data/lib/cfn-nag/custom_rules/ApiGatewayCacheEncryptedRule.rb +1 -1
  18. data/lib/cfn-nag/custom_rules/ApiGatewayMethodAuthorizationTypeRule.rb +1 -1
  19. data/lib/cfn-nag/custom_rules/AppStreamDirectoryConfigServiceAccountCredentialsAccountPasswordRule.rb +3 -3
  20. data/lib/cfn-nag/custom_rules/CodePipelineWebhookAuthenticationConfigurationSecretTokenRule.rb +2 -2
  21. data/lib/cfn-nag/custom_rules/CognitoIdentityPoolAllowUnauthenticatedIdentitiesRule.rb +1 -1
  22. data/lib/cfn-nag/custom_rules/DMSEndpointMongoDbSettingsPasswordRule.rb +2 -2
  23. data/lib/cfn-nag/custom_rules/DMSEndpointPasswordRule.rb +2 -2
  24. data/lib/cfn-nag/custom_rules/DirectoryServiceMicrosoftADPasswordRule.rb +2 -2
  25. data/lib/cfn-nag/custom_rules/DirectoryServiceSimpleADPasswordRule.rb +2 -2
  26. data/lib/cfn-nag/custom_rules/DocDBDBClusterMasterUserPasswordRule.rb +2 -2
  27. data/lib/cfn-nag/custom_rules/EC2NetworkAclEntryProtocolRule.rb +3 -7
  28. data/lib/cfn-nag/custom_rules/EKSClusterEncryptionRule.rb +1 -3
  29. data/lib/cfn-nag/custom_rules/EMRClusterKerberosAttributesADDomainJoinPasswordRule.rb +2 -2
  30. data/lib/cfn-nag/custom_rules/EMRClusterKerberosAttributesCrossRealmTrustPrincipalPasswordRule.rb +3 -3
  31. data/lib/cfn-nag/custom_rules/EMRClusterKerberosAttributesKdcAdminPasswordRule.rb +2 -2
  32. data/lib/cfn-nag/custom_rules/ElastiCacheReplicationGroupAuthTokenRule.rb +2 -2
  33. data/lib/cfn-nag/custom_rules/GameLiftFleetInboundPortRangeRule.rb +2 -0
  34. data/lib/cfn-nag/custom_rules/IAMUserLoginProfilePasswordRule.rb +2 -2
  35. data/lib/cfn-nag/custom_rules/IamUserLoginProfilePasswordResetRule.rb +4 -6
  36. data/lib/cfn-nag/custom_rules/KMSKeyWildcardPrincipalRule.rb +1 -1
  37. data/lib/cfn-nag/custom_rules/KinesisFirehoseDeliveryStreamRedshiftDestinationConfigurationPasswordRule.rb +3 -3
  38. data/lib/cfn-nag/custom_rules/KinesisFirehoseDeliveryStreamSplunkDestinationConfigurationHECTokenRule.rb +3 -3
  39. data/lib/cfn-nag/custom_rules/KinesisStreamStreamEncryptionRule.rb +3 -5
  40. data/lib/cfn-nag/custom_rules/LambdaPermissionEventSourceTokenRule.rb +2 -2
  41. data/lib/cfn-nag/custom_rules/LambdaPermissionInvokeFunctionActionRule.rb +1 -1
  42. data/lib/cfn-nag/custom_rules/ManagedBlockchainMemberMemberFabricConfigurationAdminPasswordRule.rb +4 -7
  43. data/lib/cfn-nag/custom_rules/OpsWorksAppAppSourcePasswordRule.rb +2 -2
  44. data/lib/cfn-nag/custom_rules/OpsWorksAppSslConfigurationPrivateKeyRule.rb +2 -2
  45. data/lib/cfn-nag/custom_rules/OpsWorksStackCustomCookbooksSourcePasswordRule.rb +2 -2
  46. data/lib/cfn-nag/custom_rules/OpsWorksStackRdsDbInstancesDbPasswordRule.rb +2 -2
  47. data/lib/cfn-nag/custom_rules/PinpointAPNSChannelPrivateKeyRule.rb +2 -2
  48. data/lib/cfn-nag/custom_rules/PinpointAPNSChannelTokenKeyRule.rb +2 -2
  49. data/lib/cfn-nag/custom_rules/PinpointAPNSSandboxChannelPrivateKeyRule.rb +2 -2
  50. data/lib/cfn-nag/custom_rules/PinpointAPNSSandboxChannelTokenKeyRule.rb +2 -2
  51. data/lib/cfn-nag/custom_rules/PinpointAPNSVoipChannelPrivateKeyRule.rb +2 -2
  52. data/lib/cfn-nag/custom_rules/PinpointAPNSVoipChannelTokenKeyRule.rb +2 -2
  53. data/lib/cfn-nag/custom_rules/PinpointAPNSVoipSandboxChannelPrivateKeyRule.rb +2 -2
  54. data/lib/cfn-nag/custom_rules/PinpointAPNSVoipSandboxChannelTokenKeyRule.rb +2 -2
  55. data/lib/cfn-nag/custom_rules/RDSDBClusterMasterUserPasswordRule.rb +2 -2
  56. data/lib/cfn-nag/custom_rules/RDSDBInstanceMasterUserPasswordRule.rb +2 -2
  57. data/lib/cfn-nag/custom_rules/RDSDBInstanceMasterUsernameRule.rb +2 -2
  58. data/lib/cfn-nag/custom_rules/RedshiftClusterMasterUserPasswordRule.rb +2 -2
  59. data/lib/cfn-nag/custom_rules/ResourceWithExplicitNameRule.rb +1 -1
  60. data/lib/cfn-nag/custom_rules/SecretsManagerSecretKmsKeyIdRule.rb +1 -1
  61. data/lib/cfn-nag/custom_rules/SecurityGroupIngressOpenToWorldRule.rb +1 -1
  62. data/lib/cfn-nag/custom_rules/SecurityGroupIngressPortRangeRule.rb +1 -1
  63. data/lib/cfn-nag/custom_rules/SecurityGroupMissingEgressRule.rb +1 -1
  64. data/lib/cfn-nag/custom_rules/SecurityGroupRuleDescriptionRule.rb +2 -2
  65. data/lib/cfn-nag/custom_rules/base.rb +7 -1
  66. data/lib/cfn-nag/deny_list_loader.rb +43 -0
  67. data/lib/cfn-nag/iam_complexity_metric/spcm.rb +3 -3
  68. data/lib/cfn-nag/result_view/json_results.rb +1 -1
  69. data/lib/cfn-nag/result_view/sarif_results.rb +103 -0
  70. data/lib/cfn-nag/result_view/stdout_results.rb +1 -1
  71. data/lib/cfn-nag/rule_definition.rb +6 -3
  72. data/lib/cfn-nag/rule_registry.rb +1 -0
  73. data/lib/cfn-nag/util/enforce_reference_parameter.rb +1 -1
  74. data/lib/cfn-nag/version.rb +6 -0
  75. data/lib/cfn-nag/violation.rb +11 -0
  76. data/lib/cfn-nag/violation_filtering.rb +9 -9
  77. metadata +7 -5
  78. data/lib/cfn-nag/blacklist_loader.rb +0 -43
@@ -29,9 +29,7 @@ class IamUserLoginProfilePasswordResetRule < BaseRule
29
29
 
30
30
  def iam_user_password_reset_required_key?(login_profile)
31
31
  if login_profile.key? 'PasswordResetRequired'
32
- if login_profile['PasswordResetRequired'].nil?
33
- true
34
- elsif not_truthy?(login_profile['PasswordResetRequired'])
32
+ if login_profile['PasswordResetRequired'].nil? || not_truthy?(login_profile['PasswordResetRequired'])
35
33
  true
36
34
  end
37
35
  else
@@ -40,10 +38,10 @@ class IamUserLoginProfilePasswordResetRule < BaseRule
40
38
  end
41
39
 
42
40
  def violating_iam_users?(iam_user)
43
- if !iam_user.loginProfile.nil?
44
- iam_user_password_reset_required_key?(iam_user.loginProfile)
45
- else
41
+ if iam_user.loginProfile.nil?
46
42
  false
43
+ else
44
+ iam_user_password_reset_required_key?(iam_user.loginProfile)
47
45
  end
48
46
  end
49
47
  end
@@ -6,7 +6,7 @@ require_relative 'base'
6
6
  class KMSKeyWildcardPrincipalRule < BaseRule
7
7
  def rule_text
8
8
  'KMS key should not allow * principal ' \
9
- '(https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html)'
9
+ '(https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html)'
10
10
  end
11
11
 
12
12
  def rule_type
@@ -6,9 +6,9 @@ require_relative 'password_base_rule'
6
6
  class KinesisFirehoseDeliveryStreamRedshiftDestinationConfigurationPasswordRule < PasswordBaseRule
7
7
  def rule_text
8
8
  'Kinesis Firehose DeliveryStream RedshiftDestinationConfiguration Password ' \
9
- 'must not be a plaintext string or a Ref to a Parameter with a ' \
10
- 'Default value. ' \
11
- 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager/ssm-secure value.'
9
+ 'must not be a plaintext string or a Ref to a Parameter with a ' \
10
+ 'Default value. ' \
11
+ 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager/ssm-secure value.'
12
12
  end
13
13
 
14
14
  def rule_type
@@ -6,9 +6,9 @@ require_relative 'password_base_rule'
6
6
  class KinesisFirehoseDeliveryStreamSplunkDestinationConfigurationHECTokenRule < PasswordBaseRule
7
7
  def rule_text
8
8
  'Kinesis Firehose DeliveryStream SplunkDestinationConfiguration HECToken ' \
9
- 'must not be a plaintext string or a Ref to a Parameter with a ' \
10
- 'Default value. ' \
11
- 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
9
+ 'must not be a plaintext string or a Ref to a Parameter with a ' \
10
+ 'Default value. ' \
11
+ 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
12
12
  end
13
13
 
14
14
  def rule_type
@@ -27,11 +27,9 @@ class KinesisStreamStreamEncryptionRule < BaseRule
27
27
  private
28
28
 
29
29
  def violating_kinesis_streams?(kinesis_stream)
30
- if kinesis_stream.streamEncryption.nil?
31
- true
32
- elsif kinesis_stream.streamEncryption['EncryptionType'].nil?
33
- true
34
- elsif kinesis_stream.streamEncryption['KeyId'].nil?
30
+ if kinesis_stream.streamEncryption.nil? ||
31
+ kinesis_stream.streamEncryption['EncryptionType'].nil? ||
32
+ kinesis_stream.streamEncryption['KeyId'].nil?
35
33
  true
36
34
  else
37
35
  kinesis_stream.streamEncryption['EncryptionType'] == 'NONE'
@@ -6,8 +6,8 @@ require_relative 'password_base_rule'
6
6
  class LambdaPermissionEventSourceTokenRule < PasswordBaseRule
7
7
  def rule_text
8
8
  'Lambda Permission EventSourceToken must not be a plaintext string ' \
9
- 'or a Ref to a Parameter with a Default value. ' \
10
- 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
9
+ 'or a Ref to a Parameter with a Default value. ' \
10
+ 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
11
11
  end
12
12
 
13
13
  def rule_type
@@ -6,7 +6,7 @@ require_relative 'base'
6
6
  class LambdaPermissionInvokeFunctionActionRule < BaseRule
7
7
  def rule_text
8
8
  'Lambda permission beside InvokeFunction might not be what you want? ' \
9
- 'Not sure!?'
9
+ 'Not sure!?'
10
10
  end
11
11
 
12
12
  def rule_type
@@ -8,7 +8,7 @@ require_relative 'base'
8
8
  class ManagedBlockchainMemberMemberFabricConfigurationAdminPasswordRule < BaseRule
9
9
  def rule_text
10
10
  'ManagedBlockchain Member MemberFabricConfiguration AdminPasswordRule must ' \
11
- 'not be a plaintext string or a Ref to a NoEcho Parameter with a Default value.'
11
+ 'not be a plaintext string or a Ref to a NoEcho Parameter with a Default value.'
12
12
  end
13
13
 
14
14
  def rule_type
@@ -42,14 +42,11 @@ class ManagedBlockchainMemberMemberFabricConfigurationAdminPasswordRule < BaseRu
42
42
  # 'MemberFabricConfiguration'
43
43
  # 'AdminPassword'
44
44
  def password_property_does_not_exist(member)
45
- if member.memberConfiguration['MemberFrameworkConfiguration'].nil?
46
- true
47
- elsif member.memberConfiguration['MemberFrameworkConfiguration']['MemberFabricConfiguration'].nil?
48
- true
49
- elsif member.memberConfiguration['MemberFrameworkConfiguration']['MemberFabricConfiguration']['AdminPassword'].nil?
45
+ if member.memberConfiguration['MemberFrameworkConfiguration'].nil? ||
46
+ member.memberConfiguration['MemberFrameworkConfiguration']['MemberFabricConfiguration'].nil?
50
47
  true
51
48
  else
52
- false
49
+ member.memberConfiguration['MemberFrameworkConfiguration']['MemberFabricConfiguration']['AdminPassword'].nil?
53
50
  end
54
51
  end
55
52
  end
@@ -6,8 +6,8 @@ require_relative 'password_base_rule'
6
6
  class OpsWorksAppAppSourcePasswordRule < PasswordBaseRule
7
7
  def rule_text
8
8
  'OpsWorks App AppSource Password must not be a plaintext ' \
9
- 'string or a Ref to a Parameter with a Default value. ' \
10
- 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager/ssm-secure value.'
9
+ 'string or a Ref to a Parameter with a Default value. ' \
10
+ 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager/ssm-secure value.'
11
11
  end
12
12
 
13
13
  def rule_type
@@ -6,8 +6,8 @@ require_relative 'password_base_rule'
6
6
  class OpsWorksAppSslConfigurationPrivateKeyRule < PasswordBaseRule
7
7
  def rule_text
8
8
  'OpsWorks App SslConfiguration PrivateKey must not be a plaintext ' \
9
- 'string or a Ref to a Parameter with a Default value. ' \
10
- 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
9
+ 'string or a Ref to a Parameter with a Default value. ' \
10
+ 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
11
11
  end
12
12
 
13
13
  def rule_type
@@ -6,8 +6,8 @@ require_relative 'password_base_rule'
6
6
  class OpsWorksStackCustomCookbooksSourcePasswordRule < PasswordBaseRule
7
7
  def rule_text
8
8
  'OpsWorks Stack CustomCookbooksSource Password must not be a plaintext ' \
9
- 'string or a Ref to a Parameter with a Default value. ' \
10
- 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager/ssm-secure value.'
9
+ 'string or a Ref to a Parameter with a Default value. ' \
10
+ 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager/ssm-secure value.'
11
11
  end
12
12
 
13
13
  def rule_type
@@ -6,8 +6,8 @@ require_relative 'sub_property_with_list_password_base_rule'
6
6
  class OpsWorksStackRdsDbInstancesDbPasswordRule < SubPropertyWithListPasswordBaseRule
7
7
  def rule_text
8
8
  'OpsWorks Stack RDS DbInstance DbPassword must not be a plaintext string '\
9
- 'or a Ref to a Parameter with a Default value. ' \
10
- 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager/ssm-secure value.'
9
+ 'or a Ref to a Parameter with a Default value. ' \
10
+ 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager/ssm-secure value.'
11
11
  end
12
12
 
13
13
  def rule_type
@@ -6,8 +6,8 @@ require_relative 'password_base_rule'
6
6
  class PinpointAPNSChannelPrivateKeyRule < PasswordBaseRule
7
7
  def rule_text
8
8
  'Pinpoint APNSChannel PrivateKey must not be a plaintext string ' \
9
- 'or a Ref to a Parameter with a Default value. ' \
10
- 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
9
+ 'or a Ref to a Parameter with a Default value. ' \
10
+ 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
11
11
  end
12
12
 
13
13
  def rule_type
@@ -6,8 +6,8 @@ require_relative 'password_base_rule'
6
6
  class PinpointAPNSChannelTokenKeyRule < PasswordBaseRule
7
7
  def rule_text
8
8
  'Pinpoint APNSChannel TokenKey must not be a plaintext string ' \
9
- 'or a Ref to a Parameter with a Default value. ' \
10
- 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
9
+ 'or a Ref to a Parameter with a Default value. ' \
10
+ 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
11
11
  end
12
12
 
13
13
  def rule_type
@@ -6,8 +6,8 @@ require_relative 'password_base_rule'
6
6
  class PinpointAPNSSandboxChannelPrivateKeyRule < PasswordBaseRule
7
7
  def rule_text
8
8
  'Pinpoint APNSSandboxChannel PrivateKey must not be a plaintext string ' \
9
- 'or a Ref to a Parameter with a Default value. ' \
10
- 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
9
+ 'or a Ref to a Parameter with a Default value. ' \
10
+ 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
11
11
  end
12
12
 
13
13
  def rule_type
@@ -6,8 +6,8 @@ require_relative 'password_base_rule'
6
6
  class PinpointAPNSSandboxChannelTokenKeyRule < PasswordBaseRule
7
7
  def rule_text
8
8
  'Pinpoint APNSSandboxChannel TokenKey must not be a plaintext string ' \
9
- 'or a Ref to a Parameter with a Default value. ' \
10
- 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
9
+ 'or a Ref to a Parameter with a Default value. ' \
10
+ 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
11
11
  end
12
12
 
13
13
  def rule_type
@@ -6,8 +6,8 @@ require_relative 'password_base_rule'
6
6
  class PinpointAPNSVoipChannelPrivateKeyRule < PasswordBaseRule
7
7
  def rule_text
8
8
  'Pinpoint APNSVoipChannel PrivateKey must not be a plaintext string ' \
9
- 'or a Ref to a Parameter with a Default value. ' \
10
- 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
9
+ 'or a Ref to a Parameter with a Default value. ' \
10
+ 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
11
11
  end
12
12
 
13
13
  def rule_type
@@ -6,8 +6,8 @@ require_relative 'password_base_rule'
6
6
  class PinpointAPNSVoipChannelTokenKeyRule < PasswordBaseRule
7
7
  def rule_text
8
8
  'Pinpoint APNSChannel TokenKey must not be a plaintext string ' \
9
- 'or a Ref to a Parameter with a Default value. ' \
10
- 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
9
+ 'or a Ref to a Parameter with a Default value. ' \
10
+ 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
11
11
  end
12
12
 
13
13
  def rule_type
@@ -6,8 +6,8 @@ require_relative 'password_base_rule'
6
6
  class PinpointAPNSVoipSandboxChannelPrivateKeyRule < PasswordBaseRule
7
7
  def rule_text
8
8
  'Pinpoint APNSVoipSandboxChannel PrivateKey must not be a plaintext ' \
9
- 'string or a Ref to a Parameter with a Default value. ' \
10
- 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
9
+ 'string or a Ref to a Parameter with a Default value. ' \
10
+ 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
11
11
  end
12
12
 
13
13
  def rule_type
@@ -6,8 +6,8 @@ require_relative 'password_base_rule'
6
6
  class PinpointAPNSVoipSandboxChannelTokenKeyRule < PasswordBaseRule
7
7
  def rule_text
8
8
  'Pinpoint APNSVoipSandboxChannel TokenKey must not be a plaintext string ' \
9
- 'or a Ref to a Parameter with a Default value. ' \
10
- 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
9
+ 'or a Ref to a Parameter with a Default value. ' \
10
+ 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
11
11
  end
12
12
 
13
13
  def rule_type
@@ -6,8 +6,8 @@ require_relative 'password_base_rule'
6
6
  class RDSDBClusterMasterUserPasswordRule < PasswordBaseRule
7
7
  def rule_text
8
8
  'RDS DB Cluster master user password must not be a plaintext string ' \
9
- 'or a Ref to a Parameter with a Default value. ' \
10
- 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager/ssm-secure value.'
9
+ 'or a Ref to a Parameter with a Default value. ' \
10
+ 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager/ssm-secure value.'
11
11
  end
12
12
 
13
13
  def rule_type
@@ -6,8 +6,8 @@ require_relative 'password_base_rule'
6
6
  class RDSDBInstanceMasterUserPasswordRule < PasswordBaseRule
7
7
  def rule_text
8
8
  'RDS instance master user password must not be a plaintext string ' \
9
- 'or a Ref to a Parameter with a Default value. ' \
10
- 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager/ssm-secure value.'
9
+ 'or a Ref to a Parameter with a Default value. ' \
10
+ 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager/ssm-secure value.'
11
11
  end
12
12
 
13
13
  def rule_type
@@ -7,8 +7,8 @@ require_relative 'password_base_rule'
7
7
  class RDSDBInstanceMasterUsernameRule < PasswordBaseRule
8
8
  def rule_text
9
9
  'RDS instance master username must not be a plaintext string ' \
10
- 'or a Ref to a Parameter with a Default value. ' \
11
- 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
10
+ 'or a Ref to a Parameter with a Default value. ' \
11
+ 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager value.'
12
12
  end
13
13
 
14
14
  def rule_type
@@ -6,8 +6,8 @@ require_relative 'password_base_rule'
6
6
  class RedshiftClusterMasterUserPasswordRule < PasswordBaseRule
7
7
  def rule_text
8
8
  'Redshift Cluster master user password must not be a plaintext string ' \
9
- 'or a Ref to a Parameter with a Default value. ' \
10
- 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager/ssm-secure value.'
9
+ 'or a Ref to a Parameter with a Default value. ' \
10
+ 'Can be Ref to a NoEcho Parameter without a Default, or a dynamic reference to a secretsmanager/ssm-secure value.'
11
11
  end
12
12
 
13
13
  def rule_type
@@ -26,7 +26,7 @@ class ResourceWithExplicitNameRule < BaseRule
26
26
 
27
27
  def rule_text
28
28
  'Resource found with an explicit name, this disallows updates that ' \
29
- 'require replacement of this resource'
29
+ 'require replacement of this resource'
30
30
  end
31
31
 
32
32
  def rule_type
@@ -6,7 +6,7 @@ require_relative 'boolean_base_rule'
6
6
  class SecretsManagerSecretKmsKeyIdRule < BooleanBaseRule
7
7
  def rule_text
8
8
  'Secrets Manager Secret should explicitly specify KmsKeyId.' \
9
- ' Besides control of the key this will allow the secret to be shared cross-account'
9
+ ' Besides control of the key this will allow the secret to be shared cross-account'
10
10
  end
11
11
 
12
12
  def rule_type
@@ -9,7 +9,7 @@ class SecurityGroupIngressOpenToWorldRule < BaseRule
9
9
 
10
10
  def rule_text
11
11
  'Security Groups found with cidr open to world on ingress. This should ' \
12
- 'never be true on instance. Permissible on ELB'
12
+ 'never be true on instance. Permissible on ELB'
13
13
  end
14
14
 
15
15
  def rule_type
@@ -6,7 +6,7 @@ require_relative 'base'
6
6
  class SecurityGroupIngressPortRangeRule < BaseRule
7
7
  def rule_text
8
8
  'Security Groups found ingress with port range instead of just a single ' \
9
- 'port'
9
+ 'port'
10
10
  end
11
11
 
12
12
  def rule_type
@@ -6,7 +6,7 @@ require_relative 'base'
6
6
  class SecurityGroupMissingEgressRule < BaseRule
7
7
  def rule_text
8
8
  'Missing egress rule means all traffic is allowed outbound. Make this ' \
9
- 'explicit if it is desired configuration'
9
+ 'explicit if it is desired configuration'
10
10
  end
11
11
 
12
12
  def rule_type
@@ -8,8 +8,8 @@ require 'cfn-nag/util/blank'
8
8
  class SecurityGroupRuleDescriptionRule < BaseRule
9
9
  def rule_text
10
10
  'Security group rules without a description obscure their purpose and may '\
11
- 'lead to bad practices in ensuring they only allow traffic from the ports '\
12
- 'and sources/destinations required.'
11
+ 'lead to bad practices in ensuring they only allow traffic from the ports '\
12
+ 'and sources/destinations required.'
13
13
  end
14
14
 
15
15
  def rule_type
@@ -19,9 +19,15 @@ class BaseRule
19
19
  logical_resource_ids = audit_impl(cfn_model)
20
20
  return if logical_resource_ids.empty?
21
21
 
22
+ violation(logical_resource_ids)
23
+ end
24
+
25
+ def violation(logical_resource_ids, line_numbers = [])
22
26
  Violation.new(id: rule_id,
27
+ name: self.class.name,
23
28
  type: rule_type,
24
29
  message: rule_text,
25
- logical_resource_ids: logical_resource_ids)
30
+ logical_resource_ids: logical_resource_ids,
31
+ line_numbers: line_numbers)
26
32
  end
27
33
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+
5
+ class DenyListLoader
6
+ def initialize(rules_registry)
7
+ @rules_registry = rules_registry
8
+ end
9
+
10
+ def load(deny_list_definition:)
11
+ raise 'Empty profile' if deny_list_definition.strip == ''
12
+
13
+ deny_list_ruleset = RuleIdSet.new
14
+
15
+ deny_list_hash = load_deny_list_yaml(deny_list_definition)
16
+ raise 'Deny list is malformed' unless deny_list_hash.is_a? Hash
17
+
18
+ rules_to_suppress = deny_list_hash.fetch('RulesToSuppress', {})
19
+ raise 'Missing RulesToSuppress key in deny list' if rules_to_suppress.empty?
20
+
21
+ rule_ids_to_suppress = rules_to_suppress.map { |rule| rule['id'] }
22
+ rule_ids_to_suppress.each do |rule_id|
23
+ check_valid_rule_id rule_id
24
+ deny_list_ruleset.add_rule rule_id
25
+ end
26
+
27
+ deny_list_ruleset
28
+ end
29
+
30
+ private
31
+
32
+ def load_deny_list_yaml(deny_list_definition)
33
+ YAML.safe_load(deny_list_definition)
34
+ rescue StandardError => yaml_parse_error
35
+ raise "YAML parse of deny list failed: #{yaml_parse_error}"
36
+ end
37
+
38
+ def check_valid_rule_id(rule_id)
39
+ return true unless @rules_registry.by_id(rule_id).nil?
40
+
41
+ raise "#{rule_id} is not a legal rule identifier from: #{@rules_registry.ids}"
42
+ end
43
+ end
@@ -11,8 +11,8 @@ class SPCM
11
11
  parameter_values_path: nil,
12
12
  condition_values_path: nil,
13
13
  template_pattern: DEFAULT_TEMPLATE_PATTERN)
14
- parameter_values_string = parameter_values_path.nil? ? nil : IO.read(parameter_values_path)
15
- condition_values_string = condition_values_path.nil? ? nil : IO.read(condition_values_path)
14
+ parameter_values_string = parameter_values_path.nil? ? nil : File.read(parameter_values_path)
15
+ condition_values_string = condition_values_path.nil? ? nil : File.read(condition_values_path)
16
16
 
17
17
  templates = TemplateDiscovery.new.discover_templates(input_json_path: input_path,
18
18
  template_pattern: template_pattern)
@@ -21,7 +21,7 @@ class SPCM
21
21
  aggregate_results << {
22
22
  filename: template,
23
23
  file_results: metric(
24
- cloudformation_string: IO.read(template),
24
+ cloudformation_string: File.read(template),
25
25
  parameter_values_string: parameter_values_string,
26
26
  condition_values_string: condition_values_string
27
27
  )
@@ -3,7 +3,7 @@
3
3
  require 'json'
4
4
 
5
5
  class JsonResults
6
- def render(results)
6
+ def render(results, _rule_registry)
7
7
  hashified_results = results.each do |result|
8
8
  result[:file_results][:violations] = result[:file_results][:violations].map(&:to_h)
9
9
  end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'pathname'
5
+
6
+ class SarifResults
7
+ def render(results, rule_registry)
8
+ sarif_results = []
9
+ results.each do |file|
10
+ # For each file in the results, review the violations
11
+ file[:file_results][:violations].each do |violation|
12
+ # For each violation, generate a sarif result for each logical resource id in the violation
13
+ violation.logical_resource_ids.each_with_index do |_logical_resource_id, index|
14
+ sarif_results << sarif_result(file_name: file[:filename], violation: violation, index: index)
15
+ end
16
+ end
17
+ end
18
+
19
+ sarif_report = {
20
+ version: '2.1.0',
21
+ '$schema': 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json',
22
+ runs: [
23
+ tool: {
24
+ driver: driver(rule_registry.rules)
25
+ },
26
+ results: sarif_results
27
+ ]
28
+ }
29
+
30
+ puts JSON.pretty_generate(sarif_report)
31
+ end
32
+
33
+ # Generates a SARIF driver object, which describes the tool and the rules used
34
+ def driver(rules)
35
+ {
36
+ name: 'cfn_nag',
37
+ informationUri: 'https://github.com/stelligent/cfn_nag',
38
+ semanticVersion: CfnNagVersion::VERSION,
39
+ rules: rules.map do |rule_definition|
40
+ {
41
+ id: "CFN_NAG_#{rule_definition.id}",
42
+ name: rule_definition.name,
43
+ fullDescription: {
44
+ text: rule_definition.message
45
+ }
46
+ }
47
+ end
48
+ }
49
+ end
50
+
51
+ # Given a cfn_nag Violation object, and index, generates a SARIF result object for the finding
52
+ def sarif_result(file_name:, violation:, index:)
53
+ {
54
+ ruleId: "CFN_NAG_#{violation.id}",
55
+ level: sarif_level(violation.type),
56
+ message: {
57
+ text: violation.message
58
+ },
59
+ locations: [
60
+ {
61
+ physicalLocation: {
62
+ artifactLocation: {
63
+ uri: relative_path(file_name),
64
+ uriBaseId: '%SRCROOT%'
65
+ },
66
+ region: {
67
+ startLine: sarif_line_number(violation.line_numbers[index])
68
+ }
69
+ },
70
+ logicalLocations: [
71
+ {
72
+ name: violation.logical_resource_ids[index]
73
+ }
74
+ ]
75
+ }
76
+ ]
77
+ }
78
+ end
79
+
80
+ # Line number defaults to 1 unless provided with valid number
81
+ def sarif_line_number(line_number)
82
+ line_number.nil? || line_number.to_i < 1 ? 1 : line_number.to_i
83
+ end
84
+
85
+ def sarif_level(violation_type)
86
+ case violation_type
87
+ when RuleDefinition::WARNING
88
+ 'warning'
89
+ else
90
+ 'error'
91
+ end
92
+ end
93
+
94
+ def relative_path(file_name)
95
+ file_pathname = Pathname.new(file_name)
96
+
97
+ if file_pathname.relative?
98
+ file_pathname.to_s
99
+ else
100
+ file_pathname.relative_path_from(Pathname.pwd).to_s
101
+ end
102
+ end
103
+ end
@@ -24,7 +24,7 @@ class StdoutResults
24
24
  puts "Warnings count: #{Violation.count_warnings(violations)}"
25
25
  end
26
26
 
27
- def render(results)
27
+ def render(results, _rule_definitions)
28
28
  results.each do |result|
29
29
  60.times { print '-' }
30
30
  puts "\n#{result[:filename]}"
@@ -4,27 +4,30 @@ class RuleDefinition
4
4
  WARNING = 'WARN'
5
5
  FAILING_VIOLATION = 'FAIL'
6
6
 
7
- attr_reader :id, :type, :message
7
+ attr_reader :id, :name, :type, :message
8
8
 
9
9
  def initialize(id:,
10
+ name:,
10
11
  type:,
11
12
  message:)
12
13
  @id = id
14
+ @name = name
13
15
  @type = type
14
16
  @message = message
15
17
 
16
- [@id, @type, @message].each do |required|
18
+ [@id, @type, @name, @message].each do |required|
17
19
  raise 'No parameters to Violation constructor can be nil' if required.nil?
18
20
  end
19
21
  end
20
22
 
21
23
  def to_s
22
- "#{@id} #{@type} #{@message}"
24
+ "#{@id} #{name} #{@type} #{@message}"
23
25
  end
24
26
 
25
27
  def to_h
26
28
  {
27
29
  id: @id,
30
+ name: @name,
28
31
  type: @type,
29
32
  message: @message
30
33
  }
@@ -43,6 +43,7 @@ class RuleRegistry
43
43
  if existing_def.nil?
44
44
  rule_definition = RuleDefinition.new(
45
45
  id: rule.rule_id,
46
+ name: rule_class.name,
46
47
  type: rule.rule_type,
47
48
  message: rule.rule_text
48
49
  )