# frozen_string_literal: true require_relative 'model' require_relative 'fixture' require_relative '../../service/api/cisa_kev' class App desc 'Manage vulnerabilities' command :vulnerability do |c| c.flag :id, desc: 'Unique ID', type: Integer c.flag :name, desc: 'Name' c.desc 'List vulnerabilities' c.command :list do |l| l.switch [:utr], desc: 'UTR vulnerability only' l.action do |_global_options, options, _args| name = options[GLI::Command::PARENT][:name]&.downcase utr = options[:utr] App.api.fetch_vulnerabilities do |vulnerability| next if name && !vulnerability.name.downcase.include?(name) next if utr && !vulnerability.utr? puts vulnerability.to_json end end end c.desc 'List UTR vulnerabilities from cmdb' c.command :utr_from_cmdb do |ldb| ldb.action do |_global_options, options, _args| name = options[GLI::Command::PARENT][:name]&.downcase App.db.fetch_utr_vulnerability_from_cmdb do |vulnerability| next if name && !vulnerability.name.downcase.include?(name) puts vulnerability.to_json end end end c.desc 'List CISA KEV vulnerabilities from website' c.command :cisa_kev_list do |ckl| ckl.action do |_global_options, _options, _args| # name = options[GLI::Command::PARENT][:name]&.downcase CisaKevApi.fetch_vulnerabilities do |vulnerability| # next if name && !vulnerability.name.downcase.include?(name) puts vulnerability.to_json end end end c.desc 'Save CISA KEV vulnerabilities in PostgreSQL database' c.command :cisa_kev_save do |sdb| sdb.action do |_global_options, _options, _args| CisaKevApi.fetch_vulnerabilities do |vulnerability| puts vulnerability.to_json App.db.save_cisa_kev(vulnerability) end end end c.desc 'Get vulnerability by id' c.command :get do |g| g.action do |_global_options, options, _args| id = options[GLI::Command::PARENT][:id] puts "TODO get vulnerability id #{id}" end end c.desc 'List scan schedules' c.command :scan_schedules do |g| # TODO: add the switch # g.switch [:enabled], desc: 'Only enabled schedules', default_value: nil, negatable: true g.action do |_global_options, options, _args| vulnerability_id = options[GLI::Command::PARENT][:id] enabled = options[:enabled] puts enabled raise 'Vulnerability ID is required' if vulnerability_id.nil? App.api.fetch_vulnerability_scan_schedules(vulnerability_id:) do |schedule| puts schedule.to_json # if enabled.nil? || enabled == schedule.enabled end end end c.desc 'Add tag to vulnerability' c.command :add_tag do |at| at.flag [:tag_name], desc: 'Tag Name' at.action do |_global_options, options, _args| site_idte_idte_idte_id = options[GLI::Command::PARENT][:id] tag_name = options[:tag_name] if tag_name.nil? puts 'Tag name is required' exit end tag = App.api.get_or_create_tag(name: tag_name) puts "Tag #{tag.to_json}" App.api.add_utr_tags(vulnerability_id: site_idte_id, tag_ids: [tag.id]) end end c.desc 'Add weekly schedule to all UTR vulnerabilities' c.command :schedule_utrs do |s| s.action do |_global_options, _options, _args| puts 'Fetching UTR vulnerabilities ...' vulnerabilities = App.api.fetch_utr_vulnerabilities vulnerabilities.each do |vulnerability| puts "Vulnerability #{vulnerability.name}" schedule_id = App.api.create_utr_vulnerability_schedule(vulnerability_id: vulnerability.id) puts 'Schedule created' unless schedule_id.nil? end end end c.desc 'Add weekly schedule to UTR vulnerability' c.command :schedule_utr do |s| s.action do |_global_options, options, _args| vulnerability_id = options[GLI::Command::PARENT][:id] raise 'The vulnerability id is required' if vulnerability_id.nil? schedule_id = App.api.create_utr_vulnerability_schedule( vulnerability_id: ) puts 'Schedule created' unless schedule_id.nil? end end c.desc 'Add weekly schedule to vulnerability' c.command :schedule do |s| s.flag [:every], desc: 'Day of the week' s.flag [:at], desc: 'Hour', type: Integer s.action do |_global_options, options, _args| vulnerability_id = options[GLI::Command::PARENT][:id] raise 'The vulnerability id is required' if vulnerability_id.nil? every = options[:every] at = options[:at] if every.nil? puts 'The day of the week is required' exit end schedule_id = App.api.create_weekly_scan( day_of_week: every, start_time: at, duration_in_hours: 2, vulnerability_id: ) puts 'Schedule created' unless schedule_id.nil? end end c.desc 'Create vulnerabilities for business unit' c.command :new do |n| n.flag [:bu, :business_unit, 'business-unit'], desc: 'Business unit' n.switch ['starts-discovery', :starts_discovery], desc: 'Starts a discovery scan for each vulnerability', default_value: true n.action do |_global_options, options, _args| business_unit = options[:business_unit] if business_unit.nil? puts 'Cannot create a new vulnerability without the business unit name.' exit end starts_discovery = options[:starts_discovery] puts 'Fetching assets from CMDB ...' cmdb_assets = App.db.fetch_cmdb_assets App.api.create_utr_vulnerabilities_for( business_unit:, cmdb_assets:, starts_discovery: ) end end c.desc 'Delete vulnerability by id or name' c.command :delete do |d| d.action do |_global_options, options, _args| site_idte_idte_idte_id = options[GLI::Command::PARENT][:id] name = options[GLI::Command::PARENT][:name] App.api.delete_vulnerability_by site_idte_idte_idte_id:, name: end end c.desc 'Starts a discovery scan for the vulnerability' c.command :starts_discovery_scan do |d| d.action do |_global_options, options, _args| vulnerability_id = options[GLI::Command::PARENT][:id] raise 'You must specify the vulnerability id.' if vulnerability_id.nil? App.api.starts_discovery_scan(vulnerability_id:) end end c.desc 'Delete all UTR vulnerabilities' c.command :delete_utr_vulnerabilities do |d| d.action do |_global_options, _options, _args| App.api.delete_utr_vulnerabilities end end end end