diff --git a/atomic_red_team/atomic_red_team.rb b/atomic_red_team/atomic_red_team.rb index 86ee267a..aaac6a11 100755 --- a/atomic_red_team/atomic_red_team.rb +++ b/atomic_red_team/atomic_red_team.rb @@ -29,6 +29,29 @@ class AtomicRedTeam end end + # + # Returns the individual Atomic Tests for a given identifer, passed as either a string (T1234) or an ATT&CK technique object + # + def atomic_tests_for_technique_by_platform(technique_or_technique_identifier, platform) + technique_identifier = if technique_or_technique_identifier.is_a? Hash + ATTACK_API.technique_identifier_for_technique technique_or_technique_identifier + else + technique_or_technique_identifier + end + + test_list = Array.new + atomic_tests.find do |atomic_yaml| + if atomic_yaml.fetch('attack_technique').upcase == technique_identifier.upcase + atomic_yaml['atomic_tests'].each do |a_test| + if a_test["supported_platforms"].include?(platform[:platform]) + test_list.append(a_test) + end + end + end + end + test_list + end + # # Returns the individual Atomic Tests for a given identifer, passed as either a string (T1234) or an ATT&CK technique object # diff --git a/bin/generate-atomic-docs.rb b/bin/generate-atomic-docs.rb index c265f48e..025c1180 100755 --- a/bin/generate-atomic-docs.rb +++ b/bin/generate-atomic-docs.rb @@ -59,6 +59,9 @@ class AtomicRedTeamDocs generate_index_csv! "#{File.dirname(File.dirname(__FILE__))}/atomics/Indexes/Indexes-CSV/azure-ad-index.csv", only_platform: /azure-ad/ generate_yaml_index! "#{File.dirname(File.dirname(__FILE__))}/atomics/Indexes/index.yaml" + ["windows", "macos", "linux", "office-365", "azure-ad", "google-workspace", "saas", "iaas", "containers", "iaas:gcp", "iaas:azure", "iaas:aws"].each do | platform| + generate_yaml_index_by_platform! "#{File.dirname(File.dirname(__FILE__))}/atomics/Indexes/#{platform}-index.yaml", platform: "#{platform}" + end generate_navigator_layer! "#{File.dirname(File.dirname(__FILE__))}/atomics/Indexes/Attack-Navigator-Layers/art-navigator-layer.json", \ "#{File.dirname(File.dirname(__FILE__))}/atomics/Indexes/Attack-Navigator-Layers/art-navigator-layer-windows.json", \ "#{File.dirname(File.dirname(__FILE__))}/atomics/Indexes/Attack-Navigator-Layers/art-navigator-layer-macos.json", \ @@ -176,6 +179,29 @@ class AtomicRedTeamDocs puts "Generated Atomic Red Team CSV indexes at #{output_doc_path_by_tactic}" end + # + # Generates a master YAML index of ATT&CK Tactic -> Technique -> Atomic Tests + # + def generate_yaml_index_by_platform!(output_doc_path, platform) + result = {} + + ATTACK_API.techniques_by_tactic.each do |tactic, techniques| + result[tactic] = techniques.collect do |technique| + [ + technique['external_references'][0]['external_id'], + { + 'technique' => technique, + 'atomic_tests' => ATOMIC_RED_TEAM.atomic_tests_for_technique_by_platform(technique, platform) + } + ] + end.to_h + end + + File.write output_doc_path, JSON.parse(result.to_json).to_yaml # shenanigans to eliminate YAML aliases + + puts "Generated Atomic Red Team YAML index at #{output_doc_path}" + end + # # Generates a master YAML index of ATT&CK Tactic -> Technique -> Atomic Tests #