cfn-nag 0.5.61 → 0.6.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/spcm_scan +69 -0
- data/lib/cfn-nag/cfn_nag.rb +1 -0
- data/lib/cfn-nag/cfn_nag_config.rb +4 -1
- data/lib/cfn-nag/cfn_nag_executor.rb +22 -1
- data/lib/cfn-nag/cli_options.rb +18 -0
- data/lib/cfn-nag/custom_rule_loader.rb +23 -72
- data/lib/cfn-nag/custom_rules/AmazonMQBrokerUsersPasswordRule.rb +2 -2
- data/lib/cfn-nag/custom_rules/AmplifyAppAccessTokenRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/AmplifyAppBasicAuthConfigPasswordRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/AmplifyAppOauthTokenRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/AmplifyBranchBasicAuthConfigPasswordRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/ApiGatewayV2AccessLoggingRule.rb +1 -1
- data/lib/cfn-nag/custom_rules/AppStreamDirectoryConfigServiceAccountCredentialsAccountPasswordRule.rb +3 -2
- data/lib/cfn-nag/custom_rules/CodePipelineWebhookAuthenticationConfigurationSecretTokenRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/DMSEndpointMongoDbSettingsPasswordRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/DMSEndpointPasswordRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/DirectoryServiceMicrosoftADPasswordRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/DirectoryServiceSimpleADPasswordRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/DocDBDBClusterMasterUserPasswordRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/EMRClusterKerberosAttributesADDomainJoinPasswordRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/EMRClusterKerberosAttributesCrossRealmTrustPrincipalPasswordRule.rb +3 -2
- data/lib/cfn-nag/custom_rules/EMRClusterKerberosAttributesKdcAdminPasswordRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/ElastiCacheReplicationGroupAuthTokenRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/IAMUserLoginProfilePasswordRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/KinesisFirehoseDeliveryStreamRedshiftDestinationConfigurationPasswordRule.rb +3 -2
- data/lib/cfn-nag/custom_rules/KinesisFirehoseDeliveryStreamSplunkDestinationConfigurationHECTokenRule.rb +3 -2
- data/lib/cfn-nag/custom_rules/LambdaPermissionEventSourceTokenRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/OpsWorksAppAppSourcePasswordRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/OpsWorksAppSslConfigurationPrivateKeyRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/OpsWorksStackCustomCookbooksSourcePasswordRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/OpsWorksStackRdsDbInstancesDbPasswordRule.rb +3 -2
- data/lib/cfn-nag/custom_rules/PinpointAPNSChannelPrivateKeyRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/PinpointAPNSChannelTokenKeyRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/PinpointAPNSSandboxChannelPrivateKeyRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/PinpointAPNSSandboxChannelTokenKeyRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/PinpointAPNSVoipChannelPrivateKeyRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/PinpointAPNSVoipChannelTokenKeyRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/PinpointAPNSVoipSandboxChannelPrivateKeyRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/PinpointAPNSVoipSandboxChannelTokenKeyRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/RDSDBClusterMasterUserPasswordRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/RDSDBInstanceMasterUserPasswordRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/RDSDBInstanceMasterUsernameRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/RedshiftClusterMasterUserPasswordRule.rb +2 -1
- data/lib/cfn-nag/custom_rules/SPCMRule.rb +66 -0
- data/lib/cfn-nag/custom_rules/SecretsManagerSecretKmsKeyIdRule.rb +4 -3
- data/lib/cfn-nag/iam_complexity_metric/condition_metric.rb +85 -0
- data/lib/cfn-nag/iam_complexity_metric/html_results_renderer.rb +45 -0
- data/lib/cfn-nag/iam_complexity_metric/policy_document_metric.rb +11 -0
- data/lib/cfn-nag/iam_complexity_metric/spcm.rb +79 -0
- data/lib/cfn-nag/iam_complexity_metric/statement_metric.rb +104 -0
- data/lib/cfn-nag/iam_complexity_metric/weights.rb +22 -0
- data/lib/cfn-nag/metadata.rb +78 -0
- metadata +15 -5
@@ -7,7 +7,8 @@ require_relative 'password_base_rule'
|
|
7
7
|
class DirectoryServiceSimpleADPasswordRule < PasswordBaseRule
|
8
8
|
def rule_text
|
9
9
|
'DirectoryService SimpleAD password must not be a plaintext string ' \
|
10
|
-
'or a Ref to a
|
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/ssm-secure value.'
|
11
12
|
end
|
12
13
|
|
13
14
|
def rule_type
|
@@ -6,7 +6,8 @@ require_relative 'password_base_rule'
|
|
6
6
|
class DocDBDBClusterMasterUserPasswordRule < PasswordBaseRule
|
7
7
|
def rule_text
|
8
8
|
'DocDB DB Cluster master user password must not be a plaintext string ' \
|
9
|
-
'or a Ref to a
|
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.'
|
10
11
|
end
|
11
12
|
|
12
13
|
def rule_type
|
@@ -6,7 +6,8 @@ require_relative 'password_base_rule'
|
|
6
6
|
class EMRClusterKerberosAttributesADDomainJoinPasswordRule < PasswordBaseRule
|
7
7
|
def rule_text
|
8
8
|
'EMR Cluster KerberosAttributes AD Domain JoinPassword must not be a ' \
|
9
|
-
'plaintext string or a Ref to a
|
9
|
+
'plaintext 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.'
|
10
11
|
end
|
11
12
|
|
12
13
|
def rule_type
|
data/lib/cfn-nag/custom_rules/EMRClusterKerberosAttributesCrossRealmTrustPrincipalPasswordRule.rb
CHANGED
@@ -6,8 +6,9 @@ require_relative 'password_base_rule'
|
|
6
6
|
class EMRClusterKerberosAttributesCrossRealmTrustPrincipalPasswordRule < PasswordBaseRule
|
7
7
|
def rule_text
|
8
8
|
'EMR Cluster KerberosAttributes CrossRealmTrustPrincipal Password must ' \
|
9
|
-
'not be a plaintext string or a Ref to a
|
10
|
-
'Default value.'
|
9
|
+
'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.'
|
11
12
|
end
|
12
13
|
|
13
14
|
def rule_type
|
@@ -6,7 +6,8 @@ require_relative 'password_base_rule'
|
|
6
6
|
class EMRClusterKerberosAttributesKdcAdminPasswordRule < PasswordBaseRule
|
7
7
|
def rule_text
|
8
8
|
'EMR Cluster KerberosAttributes KdcAdmin Password must not be a ' \
|
9
|
-
'plaintext string or a Ref to a
|
9
|
+
'plaintext 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.'
|
10
11
|
end
|
11
12
|
|
12
13
|
def rule_type
|
@@ -6,7 +6,8 @@ require_relative 'password_base_rule'
|
|
6
6
|
class ElastiCacheReplicationGroupAuthTokenRule < PasswordBaseRule
|
7
7
|
def rule_text
|
8
8
|
'ElastiCache ReplicationGroup AuthToken must not be a plaintext string ' \
|
9
|
-
'or a Ref to a
|
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.'
|
10
11
|
end
|
11
12
|
|
12
13
|
def rule_type
|
@@ -6,7 +6,8 @@ require_relative 'password_base_rule'
|
|
6
6
|
class IAMUserLoginProfilePasswordRule < PasswordBaseRule
|
7
7
|
def rule_text
|
8
8
|
'IAM User LoginProfile Password must not be a plaintext string or ' \
|
9
|
-
'a Ref to a
|
9
|
+
'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.'
|
10
11
|
end
|
11
12
|
|
12
13
|
def rule_type
|
@@ -6,8 +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
|
10
|
-
'Default 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.'
|
11
12
|
end
|
12
13
|
|
13
14
|
def rule_type
|
@@ -6,8 +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
|
10
|
-
'Default 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.'
|
11
12
|
end
|
12
13
|
|
13
14
|
def rule_type
|
@@ -6,7 +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
|
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.'
|
10
11
|
end
|
11
12
|
|
12
13
|
def rule_type
|
@@ -6,7 +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
|
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.'
|
10
11
|
end
|
11
12
|
|
12
13
|
def rule_type
|
@@ -6,7 +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
|
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.'
|
10
11
|
end
|
11
12
|
|
12
13
|
def rule_type
|
@@ -6,7 +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
|
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.'
|
10
11
|
end
|
11
12
|
|
12
13
|
def rule_type
|
@@ -5,8 +5,9 @@ require_relative 'sub_property_with_list_password_base_rule'
|
|
5
5
|
|
6
6
|
class OpsWorksStackRdsDbInstancesDbPasswordRule < SubPropertyWithListPasswordBaseRule
|
7
7
|
def rule_text
|
8
|
-
'OpsWorks Stack RDS DbInstance DbPassword must not be a plaintext '
|
9
|
-
'
|
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.'
|
10
11
|
end
|
11
12
|
|
12
13
|
def rule_type
|
@@ -6,7 +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
|
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.'
|
10
11
|
end
|
11
12
|
|
12
13
|
def rule_type
|
@@ -6,7 +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
|
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.'
|
10
11
|
end
|
11
12
|
|
12
13
|
def rule_type
|
@@ -6,7 +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
|
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.'
|
10
11
|
end
|
11
12
|
|
12
13
|
def rule_type
|
@@ -6,7 +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
|
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.'
|
10
11
|
end
|
11
12
|
|
12
13
|
def rule_type
|
@@ -6,7 +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
|
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.'
|
10
11
|
end
|
11
12
|
|
12
13
|
def rule_type
|
@@ -6,7 +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
|
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.'
|
10
11
|
end
|
11
12
|
|
12
13
|
def rule_type
|
@@ -6,7 +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
|
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.'
|
10
11
|
end
|
11
12
|
|
12
13
|
def rule_type
|
@@ -6,7 +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
|
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.'
|
10
11
|
end
|
11
12
|
|
12
13
|
def rule_type
|
@@ -6,7 +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
|
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.'
|
10
11
|
end
|
11
12
|
|
12
13
|
def rule_type
|
@@ -6,7 +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
|
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.'
|
10
11
|
end
|
11
12
|
|
12
13
|
def rule_type
|
@@ -7,7 +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
|
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.'
|
11
12
|
end
|
12
13
|
|
13
14
|
def rule_type
|
@@ -6,7 +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
|
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.'
|
10
11
|
end
|
11
12
|
|
12
13
|
def rule_type
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cfn-nag/violation'
|
4
|
+
require 'cfn-nag/iam_complexity_metric/spcm'
|
5
|
+
require_relative 'base'
|
6
|
+
|
7
|
+
class SPCMRule < BaseRule
|
8
|
+
attr_accessor :spcm_threshold
|
9
|
+
DEFAULT_THRESHOLD = 25
|
10
|
+
|
11
|
+
def rule_text
|
12
|
+
"SPCM for IAM policy document is higher than #{spcm_threshold || DEFAULT_THRESHOLD}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def rule_type
|
16
|
+
Violation::WARNING
|
17
|
+
end
|
18
|
+
|
19
|
+
def rule_id
|
20
|
+
'W76'
|
21
|
+
end
|
22
|
+
|
23
|
+
def audit_impl(cfn_model)
|
24
|
+
logical_resource_ids = []
|
25
|
+
begin
|
26
|
+
policy_documents = SPCM.new.metric_impl(cfn_model)
|
27
|
+
rescue StandardError => catch_all_exception
|
28
|
+
puts "Experimental SPCM rule is failing. Please report #{catch_all_exception} with the violating template"
|
29
|
+
policy_documents = {}
|
30
|
+
end
|
31
|
+
|
32
|
+
threshold = spcm_threshold.nil? ? DEFAULT_THRESHOLD : spcm_threshold.to_i
|
33
|
+
logical_resource_ids += violating_policy_resources(policy_documents, threshold)
|
34
|
+
logical_resource_ids += violating_role_resources(policy_documents, threshold)
|
35
|
+
|
36
|
+
logical_resource_ids
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def violating_role_resources(policy_documents, threshold)
|
42
|
+
logical_resource_ids = []
|
43
|
+
|
44
|
+
# unfortunately the line numbers will break if we don't return
|
45
|
+
# the logical resource id - so there isn't a good way to communicate
|
46
|
+
# the specific policy within the role that is offending
|
47
|
+
policy_documents['AWS::IAM::Role'].each do |logical_resource_id, policies|
|
48
|
+
policies.each do |_, metric|
|
49
|
+
if metric >= threshold
|
50
|
+
logical_resource_ids << logical_resource_id
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
logical_resource_ids
|
55
|
+
end
|
56
|
+
|
57
|
+
def violating_policy_resources(policy_documents, threshold)
|
58
|
+
logical_resource_ids = []
|
59
|
+
policy_documents['AWS::IAM::Policy'].each do |logical_resource_id, metric|
|
60
|
+
if metric >= threshold
|
61
|
+
logical_resource_ids << logical_resource_id
|
62
|
+
end
|
63
|
+
end
|
64
|
+
logical_resource_ids
|
65
|
+
end
|
66
|
+
end
|
@@ -5,15 +5,16 @@ require_relative 'boolean_base_rule'
|
|
5
5
|
|
6
6
|
class SecretsManagerSecretKmsKeyIdRule < BooleanBaseRule
|
7
7
|
def rule_text
|
8
|
-
'Secrets Manager Secret should explicitly specify KmsKeyId'
|
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
10
|
end
|
10
11
|
|
11
12
|
def rule_type
|
12
|
-
Violation::
|
13
|
+
Violation::WARNING
|
13
14
|
end
|
14
15
|
|
15
16
|
def rule_id
|
16
|
-
'
|
17
|
+
'W77'
|
17
18
|
end
|
18
19
|
|
19
20
|
def resource_type
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'weights'
|
4
|
+
require 'set'
|
5
|
+
|
6
|
+
class ConditionMetric
|
7
|
+
include Weights
|
8
|
+
|
9
|
+
# rubocop:disable Metrics/AbcSize
|
10
|
+
def metric(statement)
|
11
|
+
return 0 if statement.condition.nil?
|
12
|
+
|
13
|
+
aggregate = 0
|
14
|
+
aggregate += statement.condition.size * weights[:Condition]
|
15
|
+
aggregate += confusing_value_operators(statement.condition)
|
16
|
+
aggregate += if_exists_operators(statement.condition)
|
17
|
+
aggregate += weights[:Null] if null_operator?(statement.condition)
|
18
|
+
aggregate += values_with_policy_tags(statement.condition)
|
19
|
+
aggregate
|
20
|
+
end
|
21
|
+
# rubocop:enable Metrics/AbcSize
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def values_with_policy_tags(conditions)
|
26
|
+
all_values(conditions).reduce(0) do |aggregate, value|
|
27
|
+
aggregate + (contains_policy_tag?(value) ? weights[:PolicyVariables] : 0)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def contains_policy_tag?(value)
|
32
|
+
strip_special_characters(value).match(/.*\$\{.+\}.*/)
|
33
|
+
end
|
34
|
+
|
35
|
+
def strip_special_characters(value)
|
36
|
+
special_characters.each do |special_character|
|
37
|
+
value = value.gsub("${#{special_character}}", '')
|
38
|
+
end
|
39
|
+
value
|
40
|
+
end
|
41
|
+
|
42
|
+
def all_values(conditions)
|
43
|
+
result = []
|
44
|
+
conditions.each do |_, expression|
|
45
|
+
expression.each do |_, value|
|
46
|
+
if value.is_a? String
|
47
|
+
result << value
|
48
|
+
elsif value.is_a? Array
|
49
|
+
result += value
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
result
|
54
|
+
end
|
55
|
+
|
56
|
+
def special_characters
|
57
|
+
%w[$ * ?]
|
58
|
+
end
|
59
|
+
|
60
|
+
def null_operator?(conditions)
|
61
|
+
conditions.find { |operator, _| operator == 'Null' }
|
62
|
+
end
|
63
|
+
|
64
|
+
def if_exists_operators(conditions)
|
65
|
+
conditions.reduce(0) do |aggregate, condition|
|
66
|
+
operator = condition[0]
|
67
|
+
aggregate + (if_exists_operator?(operator) ? weights[:IfExists] : 0)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def if_exists_operator?(operator)
|
72
|
+
operator.end_with? 'IfExists'
|
73
|
+
end
|
74
|
+
|
75
|
+
def confusing_value_operators(conditions)
|
76
|
+
conditions.reduce(0) do |aggregate, condition|
|
77
|
+
operator = condition[0]
|
78
|
+
aggregate + (confusing_value_operator?(operator) ? weights[:Condition] : 0)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def confusing_value_operator?(operator)
|
83
|
+
%w[ForAllValues ForAnyValues].find { |prefix| operator.start_with? prefix }
|
84
|
+
end
|
85
|
+
end
|