Class: Sectest

Inherits:
Thor
  • Object
show all
Includes:
Thor::Actions
Defined in:
lib/norad_cli/cli/sectest.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Sectest

rubocop:enable Style/GuardClause



60
61
62
63
64
65
# File 'lib/norad_cli/cli/sectest.rb', line 60

def initialize(*args)
  super

  # Check if the command is being run from the repository root (all commands must be)
  root_dir?
end

Class Method Details

.load_manifest(sectest_name) ⇒ Object

Loads a manifest file depending on the command rubocop:disable Style/GuardClause



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/norad_cli/cli/sectest.rb', line 35

def self.load_manifest(sectest_name)
  @@sectest_manifest = {}

  # Set defaults just in case no manifest.yml to overwrite
  @@sectest_manifest['registry'] = 'norad-registry.cisco.com:5000'
  @@sectest_manifest['version'] = 'latest'

  # Dynamically add options and description based on the needs of the sectest container
  if %w[build build:all build:image build:specs execute].include?(ARGV[1]) && sectest_name && !sectest_name.start_with?('-', '--')
    # Read in the program arguments
    if File.exist?("sectests/#{sectest_name}/manifest.yml")
      @@sectest_manifest = YAML.safe_load(File.read("sectests/#{sectest_name}/manifest.yml"))

      # Precautionary, remove all leading and trailing whitespace
      @@sectest_manifest['registry'].strip!
      @@sectest_manifest['version'].strip!
    else
      puts Rainbow("Error: #{sectest_name} sectest does not exist or it is missing sectests/#{sectest_name}/manifest.yml").red
      puts Rainbow('Exiting...').red
      exit(1)
    end
  end
end

.source_rootObject



29
30
31
# File 'lib/norad_cli/cli/sectest.rb', line 29

def self.source_root
  File.join(File.dirname(File.expand_path(__FILE__)), '../templates/')
end

Instance Method Details

#buildObject



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/norad_cli/cli/sectest.rb', line 118

def build
  # Error check to ensure this is a plugin directory
  Dir.glob('sectests/*').select do |f|
    # Skip if the entry is not a directory
    next if !File.directory? f

    # Grab the name of the sectest
    sectest_name = f.split('/')[-1]

    # Load the manifest for the sectest
    Sectest.load_manifest(sectest_name)

    # Build all for the sectest
    send('build:all', sectest_name)
  end
end

#execute(sectest_name) ⇒ Object



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/norad_cli/cli/sectest.rb', line 222

def execute(sectest_name)
  # Warn users if debugging is enabled
  say('Warning: Debug enabled: containers must be removed manually', :yellow) && sleep(2) if options['debug']

  # Ensure the results server is built by building the images specs (code reuse)
  send('build:specs', sectest_name)

  # Build the sectest image if necessary
  send('build:image', sectest_name)

  # Allocate an instance of the sectest
  sectest_instance = NoradCli::SecTestContainer.new(ARGV[2], @@sectest_manifest['registry'],
                                                    @@sectest_manifest['version'], options)

  # Start the test
  sectest_instance.start

  # Print any debugging
  sectest_instance.output(options[:target]) if options[:debug]

  # Get the results
  results = sectest_instance.results

  say('Results are:', :green)
  formatted_results = options[:format] ? JSON.pretty_generate(JSON.parse(results)) : results
  puts formatted_results

  # Cleanup the sectest container
  sectest_instance.shutdown

  # Warn users if debugging is enabled
  say('Warning: Debug enabled: containers must be removed manually', :yellow) if options['debug']
end

#scaffold(sectest_name) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/norad_cli/cli/sectest.rb', line 80

def scaffold(sectest_name)
  # Grab the current directory
  repo_dir = Dir.pwd

  # Check for valid test types
  if !%w[authenticated web_application brute_force ssl_crypto ssh_crypto whole_host].include?(options[:test_type])
    say("#{options[:test_type]} is not a supported test type", :red)
    say('Exiting...', :red)
    exit(1)
  end

  # Set options for templates
  options[:name] = sectest_name
  options[:spec_class_name] = sectest_name.split('-').map { |t| t =~ /\d+/ ? t : t.capitalize! }.join

  # Error check to ensure this is a norad security test repository

  # Create the security tests standard files
  template('tool/Dockerfile.erb', "#{repo_dir}/sectests/#{sectest_name}/Dockerfile")
  template('tool/README.md.erb', "#{repo_dir}/sectests/#{sectest_name}/README.md")
  template('tool/manifest.yml.erb', "#{repo_dir}/sectests/#{sectest_name}/manifest.yml")

  # Create a starter wrapper script
  template('tool/wrapper.rb.erb', "#{repo_dir}/sectests/#{sectest_name}/#{sectest_name}-wrapper.rb")

  # Create the spec files
  template('tool/tool_spec.rb.erb', "#{repo_dir}/spec/#{sectest_name}/#{sectest_name}_spec.rb")
  if options[:test_type] == 'authenticated'
    template('tool/Dockerfile.auth.target.erb', "#{repo_dir}/spec/#{sectest_name}/targets/Dockerfile.secure")
    template('tool/Dockerfile.auth.target.erb', "#{repo_dir}/spec/#{sectest_name}/targets/Dockerfile.vulnerable")
  else
    template('tool/Dockerfile.unauth.target.erb', "#{repo_dir}/spec/#{sectest_name}/targets/Dockerfile.secure")
    template('tool/Dockerfile.unauth.target.erb', "#{repo_dir}/spec/#{sectest_name}/targets/Dockerfile.vulnerable")
  end
end

#seedObject



279
280
281
282
# File 'lib/norad_cli/cli/sectest.rb', line 279

def seed
  # Generate the seed file
  SeedGenerator.process_manifests(options[:seedfile], options[:docsite])
end

#specObject



266
267
268
269
270
271
272
273
274
# File 'lib/norad_cli/cli/sectest.rb', line 266

def spec
  # Error check to ensure this is a plugin directory
  specs = Dir.glob('sectests/*').map do |f|
    if File.directory? f
      f.split('/')[-1]
    end
  end.compact
  run_specs(*specs, thor_options: options)
end

#validateObject



297
298
299
300
301
302
303
304
305
# File 'lib/norad_cli/cli/sectest.rb', line 297

def validate
  # Error check to ensure this is a plugin directory
  files = Dir.glob('sectests/*').map do |f|
    if File.directory? f
      f.split('/')[-1]
    end
  end.compact
  run_validations(*files)
end