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.
- checksums.yaml +4 -4
- data/bin/cfn_nag +27 -11
- data/bin/cfn_nag_rules +5 -4
- data/bin/cfn_nag_scan +29 -0
- data/lib/cfn-nag.rb +3 -0
- data/lib/cfn-nag/cfn_nag.rb +115 -0
- data/lib/cfn-nag/custom_rule_loader.rb +72 -0
- data/lib/cfn-nag/custom_rules/CloudFormationAuthenticationRule.rb +28 -0
- data/lib/cfn-nag/custom_rules/CloudFrontDistributionAccessLoggingRule.rb +24 -0
- data/lib/cfn-nag/custom_rules/EbsVolumeHasSseRule.rb +24 -0
- data/lib/cfn-nag/custom_rules/ElasticLoadBalancerAccessLoggingRule.rb +24 -0
- data/lib/cfn-nag/custom_rules/IamManagedPolicyNotActionRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/IamManagedPolicyNotResourceRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/IamManagedPolicyWildcardActionRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/IamManagedPolicyWildcardResourceRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/IamPolicyNotActionRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/IamPolicyNotResourceRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/IamPolicyWildcardActionRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/IamPolicyWildcardResourceRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/IamRoleNotActionOnPermissionsPolicyRule.rb +28 -0
- data/lib/cfn-nag/custom_rules/IamRoleNotActionOnTrustPolicyRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/IamRoleNotPrincipalOnTrustPolicyRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/IamRoleNotResourceOnPermissionsPolicyRule.rb +28 -0
- data/lib/cfn-nag/custom_rules/IamRoleWildcardActionOnPermissionsPolicyRule.rb +28 -0
- data/lib/cfn-nag/custom_rules/IamRoleWildcardActionOnTrustPolicyRule.rb +27 -0
- data/lib/cfn-nag/custom_rules/IamRoleWildcardResourceOnPermissionsPolicyRule.rb +28 -0
- data/lib/cfn-nag/custom_rules/LambdaPermissionInvokeFunctionActionRule.rb +24 -0
- data/lib/cfn-nag/custom_rules/LambdaPermissionWildcardPrincipalRule.rb +24 -0
- data/lib/cfn-nag/custom_rules/ManagedPolicyOnUserRule.rb +24 -0
- data/lib/cfn-nag/custom_rules/PolicyOnUserRule.rb +24 -0
- data/lib/cfn-nag/custom_rules/S3BucketPolicyNotActionRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/S3BucketPolicyNotPrincipalRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/S3BucketPolicyWildcardActionRule.rb +30 -0
- data/lib/cfn-nag/custom_rules/S3BucketPolicyWildcardPrincipalRule.rb +29 -0
- data/lib/cfn-nag/custom_rules/S3BucketPublicReadAclRule.rb +29 -0
- data/lib/cfn-nag/custom_rules/S3BucketPublicReadWriteAclRule.rb +29 -0
- data/lib/cfn-nag/custom_rules/SecurityGroupEgressOpenToWorldRule.rb +39 -0
- data/lib/cfn-nag/custom_rules/SecurityGroupEgressPortRangeRule.rb +38 -0
- data/lib/cfn-nag/custom_rules/SecurityGroupIngressCidrNon32Rule.rb +40 -0
- data/lib/cfn-nag/custom_rules/SecurityGroupIngressOpenToWorldRule.rb +39 -0
- data/lib/cfn-nag/custom_rules/SecurityGroupIngressPortRangeRule.rb +38 -0
- data/lib/{custom_rules/security_group_missing_egress.rb → cfn-nag/custom_rules/SecurityGroupMissingEgressRule.rb} +6 -12
- data/lib/cfn-nag/custom_rules/SnsTopicPolicyNotActionRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/SnsTopicPolicyNotPrincipalRule.rb +26 -0
- data/lib/cfn-nag/custom_rules/SnsTopicPolicyWildcardPrincipalRule.rb +29 -0
- data/lib/cfn-nag/custom_rules/SqsQueuePolicyNotActionRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/SqsQueuePolicyNotPrincipalRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/SqsQueuePolicyWildcardActionRule.rb +30 -0
- data/lib/cfn-nag/custom_rules/SqsQueuePolicyWildcardPrincipalRule.rb +29 -0
- data/lib/cfn-nag/custom_rules/UserHasInlinePolicyRule.rb +25 -0
- data/lib/cfn-nag/custom_rules/UserMissingGroupRule.rb +28 -0
- data/lib/cfn-nag/custom_rules/WafWebAclDefaultActionRule.rb +34 -0
- data/lib/cfn-nag/custom_rules/base.rb +28 -0
- data/lib/cfn-nag/custom_rules/unencrypted_s3_put_allowed.rb +58 -0
- data/lib/{profile.rb → cfn-nag/profile.rb} +0 -1
- data/lib/{profile_loader.rb → cfn-nag/profile_loader.rb} +2 -2
- data/lib/{result_view → cfn-nag/result_view}/json_results.rb +0 -0
- data/lib/{result_view → cfn-nag/result_view}/rules_view.rb +0 -0
- data/lib/{result_view → cfn-nag/result_view}/simple_stdout_results.rb +5 -12
- data/lib/cfn-nag/rule_definition.rb +36 -0
- data/lib/cfn-nag/rule_dumper.rb +23 -0
- data/lib/cfn-nag/rule_registry.rb +43 -0
- data/lib/cfn-nag/template_discovery.rb +24 -0
- data/lib/cfn-nag/violation.rb +58 -0
- metadata +79 -36
- data/lib/cfn_nag.rb +0 -219
- data/lib/custom_rule_loader.rb +0 -64
- data/lib/custom_rules/unencrypted_s3_put_allowed.rb +0 -58
- data/lib/custom_rules/user_missing_group.rb +0 -34
- data/lib/json_rules/basic_rules.rb +0 -49
- data/lib/json_rules/cfn_rules.rb +0 -4
- data/lib/json_rules/cidr_rules.rb +0 -77
- data/lib/json_rules/cloudfront_rules.rb +0 -4
- data/lib/json_rules/ebs_rules.rb +0 -4
- data/lib/json_rules/iam_policy_rules.rb +0 -153
- data/lib/json_rules/iam_user_rules.rb +0 -15
- data/lib/json_rules/lambda_rules.rb +0 -9
- data/lib/json_rules/loadbalancer_rules.rb +0 -9
- data/lib/json_rules/port_rules.rb +0 -33
- data/lib/json_rules/s3_bucket_rules.rb +0 -51
- data/lib/json_rules/sns_rules.rb +0 -29
- data/lib/json_rules/sqs_rules.rb +0 -25
- data/lib/model/action_parser.rb +0 -27
- data/lib/model/cfn_model.rb +0 -182
- data/lib/model/iam_user_parser.rb +0 -34
- data/lib/model/parser_registry.rb +0 -31
- data/lib/model/s3_bucket_policy.rb +0 -25
- data/lib/model/s3_bucket_policy_parser.rb +0 -28
- data/lib/model/security_group_parser.rb +0 -59
- data/lib/rule.rb +0 -208
- data/lib/rule_registry.rb +0 -45
- data/lib/violation.rb +0 -41
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'cfn-nag/violation'
|
2
|
+
require_relative 'base'
|
3
|
+
|
4
|
+
class SnsTopicPolicyNotPrincipalRule < BaseRule
|
5
|
+
|
6
|
+
def rule_text
|
7
|
+
'SNS Topic policy should not allow Allow+NotPrincipal'
|
8
|
+
end
|
9
|
+
|
10
|
+
def rule_type
|
11
|
+
Violation::FAILING_VIOLATION
|
12
|
+
end
|
13
|
+
|
14
|
+
def rule_id
|
15
|
+
'F8'
|
16
|
+
end
|
17
|
+
|
18
|
+
def audit_impl(cfn_model)
|
19
|
+
violating_policies = cfn_model.resources_by_type('AWS::SNS::TopicPolicy').select do |policy|
|
20
|
+
!policy.policyDocument.allows_not_principal.empty?
|
21
|
+
end
|
22
|
+
|
23
|
+
violating_policies.map { |policy| policy.logical_resource_id }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'cfn-nag/violation'
|
2
|
+
require_relative 'base'
|
3
|
+
|
4
|
+
class SnsTopicPolicyWildcardPrincipalRule < BaseRule
|
5
|
+
|
6
|
+
def rule_text
|
7
|
+
'SNS topic policy should not allow * principal'
|
8
|
+
end
|
9
|
+
|
10
|
+
def rule_type
|
11
|
+
Violation::FAILING_VIOLATION
|
12
|
+
end
|
13
|
+
|
14
|
+
def rule_id
|
15
|
+
'F18'
|
16
|
+
end
|
17
|
+
|
18
|
+
def audit_impl(cfn_model)
|
19
|
+
logical_resource_ids = []
|
20
|
+
|
21
|
+
cfn_model.resources_by_type('AWS::SNS::TopicPolicy').each do |topic_policy|
|
22
|
+
if !topic_policy.policyDocument.wildcard_allowed_principals.empty?
|
23
|
+
logical_resource_ids << topic_policy.logical_resource_id
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
logical_resource_ids
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'cfn-nag/violation'
|
2
|
+
require_relative 'base'
|
3
|
+
|
4
|
+
class SqsQueuePolicyNotActionRule < BaseRule
|
5
|
+
|
6
|
+
def rule_text
|
7
|
+
'SQS Queue policy should not allow Allow+NotAction'
|
8
|
+
end
|
9
|
+
|
10
|
+
def rule_type
|
11
|
+
Violation::WARNING
|
12
|
+
end
|
13
|
+
|
14
|
+
def rule_id
|
15
|
+
'W18'
|
16
|
+
end
|
17
|
+
|
18
|
+
def audit_impl(cfn_model)
|
19
|
+
violating_policies = cfn_model.resources_by_type('AWS::SQS::QueuePolicy').select do |policy|
|
20
|
+
!policy.policyDocument.allows_not_action.empty?
|
21
|
+
end
|
22
|
+
|
23
|
+
violating_policies.map { |policy| policy.logical_resource_id }
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'cfn-nag/violation'
|
2
|
+
require_relative 'base'
|
3
|
+
|
4
|
+
class SqsQueuePolicyNotPrincipalRule < BaseRule
|
5
|
+
|
6
|
+
def rule_text
|
7
|
+
'SQS Queue policy should not allow Allow+NotPrincipal'
|
8
|
+
end
|
9
|
+
|
10
|
+
def rule_type
|
11
|
+
Violation::FAILING_VIOLATION
|
12
|
+
end
|
13
|
+
|
14
|
+
def rule_id
|
15
|
+
'F7'
|
16
|
+
end
|
17
|
+
|
18
|
+
def audit_impl(cfn_model)
|
19
|
+
violating_policies = cfn_model.resources_by_type('AWS::SQS::QueuePolicy').select do |policy|
|
20
|
+
!policy.policyDocument.allows_not_principal.empty?
|
21
|
+
end
|
22
|
+
|
23
|
+
violating_policies.map { |policy| policy.logical_resource_id }
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'cfn-nag/violation'
|
2
|
+
require_relative 'base'
|
3
|
+
|
4
|
+
class SqsQueuePolicyWildcardActionRule < BaseRule
|
5
|
+
|
6
|
+
def rule_text
|
7
|
+
'SQS Queue policy should not allow * action'
|
8
|
+
end
|
9
|
+
|
10
|
+
def rule_type
|
11
|
+
Violation::FAILING_VIOLATION
|
12
|
+
end
|
13
|
+
|
14
|
+
def rule_id
|
15
|
+
'F20'
|
16
|
+
end
|
17
|
+
|
18
|
+
def audit_impl(cfn_model)
|
19
|
+
logical_resource_ids = []
|
20
|
+
|
21
|
+
cfn_model.resources_by_type('AWS::SQS::QueuePolicy').each do |queue_policy|
|
22
|
+
|
23
|
+
if !queue_policy.policyDocument.wildcard_allowed_actions.empty?
|
24
|
+
logical_resource_ids << queue_policy.logical_resource_id
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
logical_resource_ids
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'cfn-nag/violation'
|
2
|
+
require_relative 'base'
|
3
|
+
|
4
|
+
class SqsQueuePolicyWildcardPrincipalRule < BaseRule
|
5
|
+
|
6
|
+
def rule_text
|
7
|
+
'SQS Queue policy should not allow * principal'
|
8
|
+
end
|
9
|
+
|
10
|
+
def rule_type
|
11
|
+
Violation::FAILING_VIOLATION
|
12
|
+
end
|
13
|
+
|
14
|
+
def rule_id
|
15
|
+
'F21'
|
16
|
+
end
|
17
|
+
|
18
|
+
def audit_impl(cfn_model)
|
19
|
+
logical_resource_ids = []
|
20
|
+
|
21
|
+
cfn_model.resources_by_type('AWS::SQS::QueuePolicy').each do |topic_policy|
|
22
|
+
if !topic_policy.policyDocument.wildcard_allowed_principals.empty?
|
23
|
+
logical_resource_ids << topic_policy.logical_resource_id
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
logical_resource_ids
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'cfn-nag/violation'
|
2
|
+
require_relative 'base'
|
3
|
+
|
4
|
+
class UserHasInlinePolicyRule < BaseRule
|
5
|
+
|
6
|
+
def rule_text
|
7
|
+
'IAM user should not have any inline policies. Should be centralized Policy object on group'
|
8
|
+
end
|
9
|
+
|
10
|
+
def rule_type
|
11
|
+
Violation::FAILING_VIOLATION
|
12
|
+
end
|
13
|
+
|
14
|
+
def rule_id
|
15
|
+
'F10'
|
16
|
+
end
|
17
|
+
|
18
|
+
def audit_impl(cfn_model)
|
19
|
+
violating_users = cfn_model.iam_users.select do |iam_user|
|
20
|
+
iam_user.policies.size > 0
|
21
|
+
end
|
22
|
+
|
23
|
+
violating_users.map { |violating_user| violating_user.logical_resource_id }
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'cfn-nag/violation'
|
2
|
+
require_relative 'base'
|
3
|
+
|
4
|
+
class UserMissingGroupRule < BaseRule
|
5
|
+
|
6
|
+
def rule_text
|
7
|
+
'User is not assigned to a group'
|
8
|
+
end
|
9
|
+
|
10
|
+
def rule_type
|
11
|
+
Violation::FAILING_VIOLATION
|
12
|
+
end
|
13
|
+
|
14
|
+
def rule_id
|
15
|
+
'F2000'
|
16
|
+
end
|
17
|
+
|
18
|
+
def audit_impl(cfn_model)
|
19
|
+
logical_resource_ids = []
|
20
|
+
cfn_model.iam_users.each do |iam_user|
|
21
|
+
if iam_user.groups.empty?
|
22
|
+
logical_resource_ids << iam_user.logical_resource_id
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
logical_resource_ids
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# Copy
|
2
|
+
# "MyWebACL": {
|
3
|
+
# "Type": "AWS::WAF::WebACL",
|
4
|
+
# "Properties": {
|
5
|
+
# "Name": "WebACL to with three rules",
|
6
|
+
# "DefaultAction": {
|
7
|
+
# "Type": "ALLOW"
|
8
|
+
# },
|
9
|
+
|
10
|
+
require 'cfn-nag/violation'
|
11
|
+
require_relative 'base'
|
12
|
+
|
13
|
+
class WafWebAclDefaultActionRule < BaseRule
|
14
|
+
|
15
|
+
def rule_text
|
16
|
+
'WebAcl DefaultAction should not be ALLOW'
|
17
|
+
end
|
18
|
+
|
19
|
+
def rule_type
|
20
|
+
Violation::FAILING_VIOLATION
|
21
|
+
end
|
22
|
+
|
23
|
+
def rule_id
|
24
|
+
'F665'
|
25
|
+
end
|
26
|
+
|
27
|
+
def audit_impl(cfn_model)
|
28
|
+
violating_web_acls = cfn_model.resources_by_type('AWS::WAF::WebACL').select do |web_acl|
|
29
|
+
web_acl.defaultAction['Type'] == 'ALLOW'
|
30
|
+
end
|
31
|
+
|
32
|
+
violating_web_acls.map { |web_acl| web_acl.logical_resource_id }
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'cfn-nag/violation'
|
2
|
+
|
3
|
+
class BaseRule
|
4
|
+
|
5
|
+
##
|
6
|
+
# Returns a collection of logical resource ids
|
7
|
+
#
|
8
|
+
def audit_impl(cfn_model)
|
9
|
+
raise 'must implement in subclass'
|
10
|
+
end
|
11
|
+
|
12
|
+
##
|
13
|
+
# Returns nil when there are no violations
|
14
|
+
# Returns a Violation object otherwise
|
15
|
+
#
|
16
|
+
def audit(cfn_model)
|
17
|
+
logical_resource_ids = audit_impl(cfn_model)
|
18
|
+
|
19
|
+
if !logical_resource_ids.empty?
|
20
|
+
Violation.new(id: rule_id,
|
21
|
+
type: rule_type,
|
22
|
+
message: rule_text,
|
23
|
+
logical_resource_ids: logical_resource_ids)
|
24
|
+
else
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# require 'cfn-nag/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
|
@@ -16,8 +16,8 @@ class ProfileLoader
|
|
16
16
|
|
17
17
|
profile_definition.each_line do |line|
|
18
18
|
rule_id = line.chomp
|
19
|
-
if @rules_registry.by_id(rule_id) ==
|
20
|
-
raise "#{rule_id} is not a legal rule identifier from: #{@rules_registry.rules}"
|
19
|
+
if @rules_registry.by_id(rule_id) == nil
|
20
|
+
raise "#{rule_id} is not a legal rule identifier from: #{@rules_registry.rules.map { |rule| rule.id }}"
|
21
21
|
else
|
22
22
|
new_profile.add_rule rule_id
|
23
23
|
end
|
File without changes
|
File without changes
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'cfn-nag/violation'
|
2
2
|
|
3
3
|
class SimpleStdoutResults
|
4
4
|
|
@@ -11,11 +11,10 @@ class SimpleStdoutResults
|
|
11
11
|
result[:file_results][:violations].each do |violation|
|
12
12
|
message message_type: "#{violation.type} #{violation.id}",
|
13
13
|
message: violation.message,
|
14
|
-
logical_resource_ids: violation.logical_resource_ids
|
15
|
-
violating_code: violation.violating_code
|
14
|
+
logical_resource_ids: violation.logical_resource_ids
|
16
15
|
end
|
17
|
-
puts "\nFailures count: #{
|
18
|
-
puts "Warnings count: #{
|
16
|
+
puts "\nFailures count: #{Violation.count_failures(result[:file_results][:violations])}"
|
17
|
+
puts "Warnings count: #{Violation.count_warnings(result[:file_results][:violations])}"
|
19
18
|
end
|
20
19
|
end
|
21
20
|
|
@@ -23,8 +22,7 @@ class SimpleStdoutResults
|
|
23
22
|
|
24
23
|
def message(message_type:,
|
25
24
|
message:,
|
26
|
-
logical_resource_ids: nil
|
27
|
-
violating_code: nil)
|
25
|
+
logical_resource_ids: nil)
|
28
26
|
|
29
27
|
if logical_resource_ids == []
|
30
28
|
logical_resource_ids = nil
|
@@ -37,11 +35,6 @@ class SimpleStdoutResults
|
|
37
35
|
puts "| Resources: #{logical_resource_ids}" unless logical_resource_ids.nil?
|
38
36
|
puts '|' unless logical_resource_ids.nil?
|
39
37
|
puts "| #{message}"
|
40
|
-
|
41
|
-
unless violating_code.nil?
|
42
|
-
puts '|'
|
43
|
-
puts indent_multiline_string_with_prefix('|', violating_code.to_s)
|
44
|
-
end
|
45
38
|
end
|
46
39
|
|
47
40
|
def indent_multiline_string_with_prefix(prefix, multiline_string)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class RuleDefinition
|
2
|
+
WARNING = 'WARN'
|
3
|
+
FAILING_VIOLATION = 'FAIL'
|
4
|
+
|
5
|
+
attr_reader :id, :type, :message
|
6
|
+
|
7
|
+
def initialize(id:,
|
8
|
+
type:,
|
9
|
+
message:)
|
10
|
+
@id = id
|
11
|
+
@type = type
|
12
|
+
@message = message
|
13
|
+
|
14
|
+
[@id, @type, @message].each do |required|
|
15
|
+
if required.nil?
|
16
|
+
raise 'No parameters to Violation constructor can be nil'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
"#{@id} #{@type} #{@message}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_h
|
26
|
+
{
|
27
|
+
id: @id,
|
28
|
+
type: @type,
|
29
|
+
message: @message
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
def ==(other_violation)
|
34
|
+
other_violation.class == self.class && other_violation.to_h == to_h
|
35
|
+
end
|
36
|
+
end
|