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



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

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



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

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



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

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

Instance Method Details

#buildObject



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

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



221
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
# File 'lib/norad_cli/cli/sectest.rb', line 221

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



79
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
# File 'lib/norad_cli/cli/sectest.rb', line 79

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



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

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

#specObject



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

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



289
290
291
292
293
294
295
296
297
# File 'lib/norad_cli/cli/sectest.rb', line 289

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