Class: HeimdallTools::SecurityHub
- Inherits:
-
Object
- Object
- HeimdallTools::SecurityHub
- Defined in:
- lib/heimdall_tools/asff_compatible_products/securityhub.rb
Class Method Summary collapse
- .finding_id(finding, encode:, controls: nil) ⇒ Object
- .finding_impact(finding, controls: nil) ⇒ Object
- .finding_nist_tag(finding, aws_config_mapping:) ⇒ Object
- .finding_title(finding, encode:, controls: nil) ⇒ Object
- .product_name(findings, encode:) ⇒ Object
- .supporting_docs(standards:) ⇒ Object
Class Method Details
.finding_id(finding, encode:, controls: nil) ⇒ Object
28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/heimdall_tools/asff_compatible_products/securityhub.rb', line 28 def self.finding_id(finding, *, encode:, controls: nil, **) ret = if !controls.nil? && !(control = corresponding_control(controls, finding)).nil? control['ControlId'] elsif finding['ProductFields'].member?('ControlId') # check if aws finding['ProductFields']['ControlId'] elsif finding['ProductFields'].member?('RuleId') # check if cis finding['ProductFields']['RuleId'] else finding['GeneratorId'].split('/')[-1] end encode.call(ret) end |
.finding_impact(finding, controls: nil) ⇒ Object
41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/heimdall_tools/asff_compatible_products/securityhub.rb', line 41 def self.finding_impact(finding, *, controls: nil, **) if !controls.nil? && !(control = corresponding_control(controls, finding)).nil? imp = control['SeverityRating'].to_sym else # severity is required, but can be either 'label' or 'normalized' internally with 'label' being preferred. other values can be in here too such as the original severity rating. imp = finding['Severity'].key?('Label') ? finding['Severity']['Label'].to_sym : finding['Severity']['Normalized']/100.0 # securityhub asff file does not contain accurate severity information by setting things that shouldn't be informational to informational: when additional context, i.e. standards, is not provided, set informational to medium. imp = :MEDIUM if imp.is_a?(Symbol) && imp == :INFORMATIONAL end imp end |
.finding_nist_tag(finding, aws_config_mapping:) ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/heimdall_tools/asff_compatible_products/securityhub.rb', line 53 def self.finding_nist_tag(finding, *, aws_config_mapping:, **) return {} unless finding['ProductFields']['RelatedAWSResources:0/type'] == 'AWS::Config::ConfigRule' entries = aws_config_mapping.select { |rule| finding['ProductFields']['RelatedAWSResources:0/name'].include? rule[:awsconfigrulename] } entries.map do |rule| = rule[:nistid].split('|') # subheadings are joined together in the csv file .map do |tag| if (i = tag.index('(')).nil? tag else tag[i..-1].scan(/\(.+?\)/).map { |subheading| "#{tag[0..i-1]}#{subheading}" } end end end.flatten.uniq end |
.finding_title(finding, encode:, controls: nil) ⇒ Object
69 70 71 72 73 74 75 76 |
# File 'lib/heimdall_tools/asff_compatible_products/securityhub.rb', line 69 def self.finding_title(finding, *, encode:, controls: nil, **) ret = if !controls.nil? && !(control = corresponding_control(controls, finding)).nil? control['Title'] else finding['Title'] end encode.call(ret) end |
.product_name(findings, encode:) ⇒ Object
78 79 80 81 82 83 84 85 86 87 |
# File 'lib/heimdall_tools/asff_compatible_products/securityhub.rb', line 78 def self.product_name(findings, *, encode:, **) # "#{findings[0]['ProductFields']['aws/securityhub/CompanyName']} #{findings[0]['ProductFields']['aws/securityhub/ProductName']}" # not using above due to wanting to provide the standard's name instead if findings[0]['Types'][0].split('/')[-1].gsub(/-/, ' ').downcase == findings[0]['ProductFields']['StandardsControlArn'].split('/')[-4].gsub(/-/, ' ').downcase standardname = findings[0]['Types'][0].split('/')[-1].gsub(/-/, ' ') else standardname = findings[0]['ProductFields']['StandardsControlArn'].split('/')[-4].gsub(/-/, ' ').split.map(&:capitalize).join(' ') end encode.call("#{standardname} v#{findings[0]['ProductFields']['StandardsControlArn'].split('/')[-2]}") end |
.supporting_docs(standards:) ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/heimdall_tools/asff_compatible_products/securityhub.rb', line 10 def self.supporting_docs(standards:) begin controls = standards.nil? ? nil : standards.map { |s| JSON.parse(s)['Controls'] }.flatten rescue StandardError => e raise "Invalid supporting docs for Security Hub:\nException: #{e}" end begin resource_dir = Pathname.new(__FILE__).join('../../../data') aws_config_mapping_file = File.join(resource_dir, 'aws-config-mapping.csv') aws_config_mapping = CSV.read(aws_config_mapping_file, { encoding: 'UTF-8', headers: true, header_converters: :symbol }).map(&:to_hash) rescue StandardError => e raise "Invalid AWS Config mapping file:\nException: #{e}" end { controls: controls, aws_config_mapping: aws_config_mapping } end |