#!/usr/bin/env ruby # encoding: utf-8 # Copyright 2015 Dominik Richter. All rights reserved. # author: Dominik Richter # author: Christoph Hartmann require 'thor' require 'json' require_relative '../lib/inspec' class InspecCLI < Thor def self.target_options option :target, aliases: :t, type: :string, default: nil, desc: 'Simple targeting option using URIs, e.g. ssh://user:pass@host:port' option :backend, aliases: :b, type: :string, default: nil, desc: 'Choose a backend: local, ssh, winrm, docker.' option :host, type: :string, desc: 'Specify a remote host which is tested.' option :port, type: :numeric, desc: 'Specify the login port for a remote scan.' option :user, type: :string, default: nil, desc: 'The login user for a remote scan.' option :password, type: :string, default: nil, desc: 'Login password for a remote scan, if required.' option :key_files, type: :array, default: nil, desc: 'Login key or certificate file for a remote scan.' option :path, type: :string, default: nil, <<<<<<< HEAD desc: 'Login path to use when connecting to the target.' option :sudo, type: :boolean, default: false, desc: 'Run scans with sudo. Only activates on Unix and non-root user.' ======= desc: 'Login path to use when connecting to the target (WinRM).' option :disable_sudo, type: :boolean, default: false, desc: 'To not run remote scans via sudo.' >>>>>>> update cli description of --path option :sudo_password, type: :string, default: nil, desc: 'Specify a sudo password, if it is required.' option :sudo_options, type: :string, default: '', desc: 'Additional sudo options for a remote scan.' option :ssl, type: :boolean, default: false, desc: 'Use SSL for transport layer encryption (WinRM).' option :self_signed, type: :boolean, default: false, desc: 'Allow remote scans with self-signed certificates (WinRM).' end desc 'json PATH', 'read all tests in PATH and generate a JSON profile' option :id, type: :string, desc: 'Attach a profile ID to all test results' option :output, aliases: :o, type: :string, desc: 'Save the created profile to a path' def json(path) profile = Inspec::Profile.from_path(path, options) dst = options[:output].to_s if dst.empty? puts JSON.pretty_generate(profile.info) else if File.exist? dst puts "----> updating #{dst}" else puts "----> creating #{dst}" end fdst = File.expand_path(dst) File.write(fdst, JSON.dump(profile.info)) end end desc 'check PATH', 'verify test structure in PATH' def check(path) o = options.dup o[:logger] = Logger.new(STDOUT) profile = Inspec::Profile.from_path(path, o) exit 1 unless profile.check end desc 'exec PATHS', 'run all test files' option :id, type: :string, desc: 'Attach a profile ID to all test results' target_options option :format, type: :string, default: 'progress' def exec(*tests) runner = Inspec::Runner.new(options) runner.add_tests(tests) runner.run rescue RuntimeError => e puts e.message end desc 'detect', 'detect the target OS' target_options def detect runner = Inspec::Runner.new(options) rel = File.join(File.dirname(__FILE__), *%w{.. lib utils detect.rb}) detect_util = File.expand_path(rel) runner.add_tests([detect_util]) runner.run rescue RuntimeError => e puts e.message end desc 'shell', 'open an interactive debugging shell' target_options def shell_func runner = Inspec::Runner.new(options) Inspec::Shell.new(runner).start rescue RuntimeError => e puts e.message end desc 'version', 'prints the version of this tool' def version puts Inspec::VERSION end end InspecCLI.start(ARGV)