#!/usr/bin/env ruby # frozen_string_literal: false require 'cgi' require 'optparse' require 'pwn' require 'yaml' opts = {} OptionParser.new do |options| options.banner = "USAGE: #{$PROGRAM_NAME} [opts] " options.on('-cCONFIG', '--config=CONFG', '') do |g| opts[:config] = g end options.on('-pNAME', '--parent-group=NAME', '') do |p| opts[:parent_group_name] = p end options.on('-sFILE', '--scan=FILE', '') do |f| opts[:target_file] = f end options.on('-rPATH', '--report=PATH', '') do |r| opts[:report_path] = r end options.on('-R', '--report-only', '') do |o| opts[:report_only] = o end options.on('-tTYPE', '--report-type=TYPE', '') do |t| opts[:report_type] = t end end.parse! if opts.empty? puts `#{$PROGRAM_NAME} --help` exit 1 end begin pwn_provider = 'ruby-gem' pwn_provider = ENV.fetch('PWN_PROVIDER') if ENV.keys.any? { |s| s == 'PWN_PROVIDER' } config = opts[:config] raise "ERROR: BDBA YAML Config File Not Found: #{config}" unless File.exist?(config) yaml_config = YAML.load_file(config, symbolize_names: true) token = yaml_config[:token] raise "ERROR: BDBA Token Not Found: #{token}" if token.nil? parent_group_name = opts[:parent_group_name] raise "ERROR: BDBA Parent Group Name Not Provided: #{parent_group_name}" if parent_group_name.nil? target_file = opts[:target_file] raise "ERROR: BDBA Target File Not Found: #{target_file}" unless File.exist?(target_file) report_path = opts[:report_path] raise "ERROR: BDBA Report Path Not Provided: #{report_path}" if report_path.nil? report_only = opts[:report_only] ||= false report_type_str = opts[:report_type] ||= 'csv_vulns' report_type = report_type_str.to_s.to_sym groups_resp = PWN::Plugins::BlackDuckBinaryAnalysis.get_groups( token: token ) parent_arr = groups_resp[:groups].select { |g| g[:name] == parent_group_name } raise "ERROR: BDBA Parent Group Not Found: #{parent_group_name}" if parent_arr.nil? sorted_parent_arr = parent_arr.sort_by { |g| g[:id] } parent_id = sorted_parent_arr.last[:id] unless report_only puts "Uploading/Scanning: #{target_file}" PWN::Plugins::BlackDuckBinaryAnalysis.upload_file( token: token, file: target_file, group_id: parent_id ) end scan_progress_resp = {} loop do scan_progress_resp = PWN::Plugins::BlackDuckBinaryAnalysis.get_apps_by_group( token: token, group_id: parent_id ) 30.times do print '.' sleep 1 end break if scan_progress_resp[:products].none? { |p| p[:status] == 'B' } end product_id = scan_progress_resp[:products].find { |p| p[:name] == CGI.escape(File.basename(target_file)) }[:product_id] scan_report_resp = PWN::Plugins::BlackDuckBinaryAnalysis.generate_product_report( token: token, product_id: product_id, type: report_type, output_path: report_path ) puts "\nReport Saved to: #{report_path}" rescue SystemExit, Interrupt puts "\nGoodbye." rescue StandardError => e raise e end