inspec-core 3.7.1 → 3.7.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/lib/inspec/config.rb +12 -0
  3. data/lib/inspec/shell.rb +2 -15
  4. data/lib/inspec/version.rb +1 -1
  5. data/lib/plugins/inspec-habitat/Berksfile +5 -0
  6. data/lib/plugins/inspec-habitat/README.md +150 -0
  7. data/lib/plugins/inspec-habitat/kitchen.yml +28 -0
  8. data/lib/plugins/inspec-habitat/lib/inspec-habitat/cli.rb +9 -9
  9. data/lib/plugins/inspec-habitat/lib/inspec-habitat/profile.rb +164 -280
  10. data/lib/plugins/inspec-habitat/templates/habitat/config/inspec_exec_config.json.erb +25 -0
  11. data/lib/plugins/inspec-habitat/templates/habitat/default.toml.erb +9 -0
  12. data/lib/plugins/inspec-habitat/templates/habitat/hooks/run.erb +32 -0
  13. data/lib/plugins/inspec-habitat/templates/habitat/plan.sh.erb +85 -0
  14. data/lib/plugins/inspec-habitat/test/cookbooks/inspec_habitat_fixture/Berksfile +2 -0
  15. data/lib/plugins/inspec-habitat/test/cookbooks/inspec_habitat_fixture/README.md +3 -0
  16. data/lib/plugins/inspec-habitat/test/cookbooks/inspec_habitat_fixture/files/hab_setup.exp +28 -0
  17. data/lib/plugins/inspec-habitat/test/cookbooks/inspec_habitat_fixture/metadata.rb +9 -0
  18. data/lib/plugins/inspec-habitat/test/cookbooks/inspec_habitat_fixture/recipes/default.rb +61 -0
  19. data/lib/plugins/inspec-habitat/test/functional/inspec_habitat_test.rb +38 -0
  20. data/lib/plugins/inspec-habitat/test/integration/default/inspec_habitat/README.md +3 -0
  21. data/lib/plugins/inspec-habitat/test/integration/default/inspec_habitat/controls/inspec_habitat.rb +40 -0
  22. data/lib/plugins/inspec-habitat/test/integration/default/inspec_habitat/inspec.yml +10 -0
  23. data/lib/plugins/inspec-habitat/test/support/example_profile/README.md +3 -0
  24. data/lib/plugins/inspec-habitat/test/support/example_profile/controls/example.rb +7 -0
  25. data/lib/plugins/inspec-habitat/test/support/example_profile/inspec.yml +10 -0
  26. data/lib/plugins/inspec-habitat/test/unit/profile_test.rb +188 -132
  27. data/lib/plugins/inspec-init/test/functional/inspec_init_profile_test.rb +12 -0
  28. data/lib/resources/aide_conf.rb +2 -2
  29. data/lib/resources/apache.rb +2 -2
  30. data/lib/resources/apache_conf.rb +2 -2
  31. data/lib/resources/apt.rb +2 -2
  32. data/lib/resources/audit_policy.rb +2 -2
  33. data/lib/resources/auditd.rb +2 -2
  34. data/lib/resources/auditd_conf.rb +2 -2
  35. data/lib/resources/bash.rb +2 -2
  36. data/lib/resources/bond.rb +2 -2
  37. data/lib/resources/bridge.rb +2 -2
  38. data/lib/resources/chocolatey_package.rb +2 -2
  39. data/lib/resources/command.rb +2 -2
  40. data/lib/resources/cpan.rb +2 -2
  41. data/lib/resources/cran.rb +2 -2
  42. data/lib/resources/crontab.rb +2 -2
  43. data/lib/resources/csv.rb +2 -2
  44. data/lib/resources/dh_params.rb +2 -2
  45. data/lib/resources/directory.rb +2 -2
  46. data/lib/resources/docker.rb +2 -2
  47. data/lib/resources/docker_container.rb +2 -2
  48. data/lib/resources/docker_image.rb +2 -2
  49. data/lib/resources/docker_plugin.rb +2 -2
  50. data/lib/resources/docker_service.rb +2 -2
  51. data/lib/resources/elasticsearch.rb +2 -2
  52. data/lib/resources/etc_fstab.rb +2 -2
  53. data/lib/resources/etc_group.rb +2 -2
  54. data/lib/resources/etc_hosts.rb +2 -2
  55. data/lib/resources/etc_hosts_allow_deny.rb +4 -4
  56. data/lib/resources/file.rb +2 -2
  57. data/lib/resources/filesystem.rb +2 -2
  58. data/lib/resources/firewalld.rb +2 -2
  59. data/lib/resources/gem.rb +2 -2
  60. data/lib/resources/groups.rb +4 -4
  61. data/lib/resources/grub_conf.rb +2 -2
  62. data/lib/resources/host.rb +2 -2
  63. data/lib/resources/http.rb +25 -5
  64. data/lib/resources/iis_app.rb +2 -2
  65. data/lib/resources/iis_app_pool.rb +6 -3
  66. data/lib/resources/iis_site.rb +4 -4
  67. data/lib/resources/inetd_conf.rb +2 -2
  68. data/lib/resources/ini.rb +2 -2
  69. data/lib/resources/interface.rb +2 -2
  70. data/lib/resources/iptables.rb +2 -2
  71. data/lib/resources/json.rb +2 -3
  72. data/lib/resources/kernel_module.rb +17 -18
  73. data/lib/resources/kernel_parameter.rb +2 -2
  74. data/lib/resources/key_rsa.rb +2 -2
  75. data/lib/resources/ksh.rb +2 -2
  76. data/lib/resources/limits_conf.rb +2 -2
  77. data/lib/resources/login_def.rb +2 -2
  78. data/lib/resources/mount.rb +2 -2
  79. data/lib/resources/mssql_session.rb +2 -2
  80. data/lib/resources/mysql_conf.rb +2 -2
  81. data/lib/resources/mysql_session.rb +2 -2
  82. data/lib/resources/nginx.rb +2 -2
  83. data/lib/resources/nginx_conf.rb +2 -2
  84. data/lib/resources/npm.rb +2 -2
  85. data/lib/resources/ntp_conf.rb +2 -2
  86. data/lib/resources/oneget.rb +2 -2
  87. data/lib/resources/oracledb_session.rb +2 -2
  88. data/lib/resources/os.rb +2 -2
  89. data/lib/resources/os_env.rb +2 -2
  90. data/lib/resources/package.rb +2 -2
  91. data/lib/resources/packages.rb +2 -2
  92. data/lib/resources/parse_config.rb +4 -4
  93. data/lib/resources/passwd.rb +2 -2
  94. data/lib/resources/pip.rb +2 -2
  95. data/lib/resources/platform.rb +2 -2
  96. data/lib/resources/port.rb +2 -2
  97. data/lib/resources/postgres_conf.rb +2 -2
  98. data/lib/resources/postgres_hba_conf.rb +2 -2
  99. data/lib/resources/postgres_ident_conf.rb +2 -2
  100. data/lib/resources/postgres_session.rb +2 -2
  101. data/lib/resources/powershell.rb +2 -2
  102. data/lib/resources/processes.rb +2 -2
  103. data/lib/resources/rabbitmq_conf.rb +2 -2
  104. data/lib/resources/registry_key.rb +2 -2
  105. data/lib/resources/security_identifier.rb +2 -2
  106. data/lib/resources/security_policy.rb +2 -2
  107. data/lib/resources/service.rb +14 -14
  108. data/lib/resources/shadow.rb +2 -2
  109. data/lib/resources/ssh_conf.rb +4 -4
  110. data/lib/resources/ssl.rb +2 -2
  111. data/lib/resources/sys_info.rb +2 -2
  112. data/lib/resources/toml.rb +2 -2
  113. data/lib/resources/users.rb +4 -4
  114. data/lib/resources/vbscript.rb +2 -2
  115. data/lib/resources/virtualization.rb +2 -2
  116. data/lib/resources/windows_feature.rb +2 -2
  117. data/lib/resources/windows_hotfix.rb +2 -2
  118. data/lib/resources/windows_task.rb +2 -2
  119. data/lib/resources/wmi.rb +2 -2
  120. data/lib/resources/x509_certificate.rb +2 -2
  121. data/lib/resources/xinetd.rb +2 -2
  122. data/lib/resources/xml.rb +2 -2
  123. data/lib/resources/yaml.rb +2 -2
  124. data/lib/resources/yum.rb +2 -2
  125. data/lib/resources/zfs_dataset.rb +2 -2
  126. data/lib/resources/zfs_pool.rb +2 -2
  127. metadata +36 -4
@@ -0,0 +1,25 @@
1
+ {
2
+ "target_id": "{{ sys.member_id }}",
3
+ "reporter": {
4
+ "cli": {
5
+ "stdout": {{cfg.report_to_stdout}}
6
+ },
7
+ "json": {
8
+ "file": "{{pkg.svc_path}}/logs/inspec_last_run.json"
9
+ }{{#if cfg.automate.token ~}},
10
+ "automate" : {
11
+ "url": "{{cfg.automate.url}}/data-collector/v0/",
12
+ "token": "{{cfg.automate.token}}",
13
+ "node_name": "{{ sys.hostname }}",
14
+ "verify_ssl": false
15
+ }{{/if ~}}
16
+ }
17
+ {{#if cfg.automate.token }},
18
+ "compliance": {
19
+ "server" : "{{cfg.automate.url}}",
20
+ "token" : "{{cfg.automate.token}}",
21
+ "user" : "{{cfg.automate.user}}",
22
+ "insecure" : true,
23
+ "ent" : "automate"
24
+ }{{/if }}
25
+ }
@@ -0,0 +1,9 @@
1
+ interval = 300
2
+ report_to_stdout = true
3
+
4
+ # Uncomment and replace values to report to Automate.
5
+ # This can also be applied at runtime via `hab config apply`
6
+ #[automate]
7
+ #url = 'https://chef-automate.test'
8
+ #token = 'TOKEN'
9
+ #user = 'admin'
@@ -0,0 +1,32 @@
1
+ #!/bin/sh
2
+
3
+ exec 2>&1
4
+
5
+ CONFIG="{{pkg.svc_config_path}}/inspec_exec_config.json"
6
+ INTERVAL="{{cfg.interval}}"
7
+ LOG_FILE="{{pkg.svc_path}}/logs/inspec_log.txt"
8
+ PROFILE_IDENT="{{pkg.origin}}/{{pkg.name}}"
9
+ PROFILE_PATH="{{pkg.path}}/{{pkg.name}}-{{pkg.version}}.tar.gz"
10
+
11
+ while true; do
12
+ echo "Executing ${PROFILE_IDENT}"
13
+ exec inspec exec ${PROFILE_PATH} --json-config ${CONFIG} 2>&1 | tee ${LOG_FILE}
14
+
15
+ exit_code=$?
16
+ if [ $exit_code -eq 1 ]; then
17
+ echo "InSpec run failed."
18
+ else
19
+ echo "InSpec run completed successfully."
20
+ if [ $exit_code -eq 0 ]; then
21
+ echo "No controls failed or were skipped."
22
+ elif [ $exit_code -eq 100 ]; then
23
+ echo "At least 1 control failed."
24
+ elif [ $exit_code -eq 101 ]; then
25
+ echo "No controls failed but at least 1 skipped."
26
+ fi
27
+ fi
28
+ echo "Results are logged here: ${LOG_FILE}"
29
+
30
+ echo "Sleeping for ${INTERVAL} seconds"
31
+ sleep ${INTERVAL}
32
+ done
@@ -0,0 +1,85 @@
1
+ pkg_name=<%= "inspec-profile-#{profile.name}" %>
2
+ pkg_version=<%= profile.version %>
3
+ pkg_origin=<%= habitat_origin %>
4
+ pkg_deps=(chef/inspec)
5
+ pkg_build_deps=(chef/inspec core/jq-static)
6
+ pkg_svc_user=root
7
+ <%= "pkg_license='#{profile.metadata.params[:license]}'" if profile.metadata.params[:license]%>
8
+
9
+ do_before() {
10
+ # Exit with error if not in the directory with 'inspec.yml'.
11
+ # This can happen if someone does 'hab studio enter' from within the
12
+ # 'habitat/' directory.
13
+ if [ ! -f "$PLAN_CONTEXT/../inspec.yml" ]; then
14
+ message="ERROR: Cannot find inspec.yml."
15
+ message="$message Please build from the profile root"
16
+ build_line "$message"
17
+
18
+ return 1
19
+ fi
20
+
21
+ # Execute an 'inspec compliance login' if a profile needs to be fetched from
22
+ # the Automate server
23
+ if [ "$(grep "compliance: " "$PLAN_CONTEXT/../inspec.yml")" ]; then
24
+ _do_compliance_login;
25
+ fi
26
+ }
27
+
28
+ do_setup_environment() {
29
+ set_buildtime_env PROFILE_CACHE_DIR "$HAB_CACHE_SRC_PATH/$pkg_dirname"
30
+ set_buildtime_env ARCHIVE_NAME "$pkg_name-$pkg_version.tar.gz"
31
+
32
+ # InSpec loads `pry` which tries to expand `~`. This fails if HOME isn't set.
33
+ set_runtime_env HOME "$pkg_svc_var_path"
34
+
35
+ # InSpec will create a `.inspec` directory in the user's home directory.
36
+ # This overrides that to write to a place within the running service's path.
37
+ # NOTE: Setting HOME does the same currently. This is here to be explicit.
38
+ set_runtime_env INSPEC_CONFIG_DIR "$pkg_svc_var_path"
39
+ }
40
+
41
+ do_unpack() {
42
+ # Change directory to where the profile files are
43
+ pushd "$PLAN_CONTEXT/../" > /dev/null
44
+
45
+ # Get a list of all files in the profile except those that are Habitat related
46
+ profile_files=($(ls -I habitat -I results -I "*.hart"))
47
+
48
+ mkdir -p "$PROFILE_CACHE_DIR" > /dev/null
49
+
50
+ # Copy just the profile files to the profile cache directory
51
+ cp -r ${profile_files[@]} "$PROFILE_CACHE_DIR"
52
+ }
53
+
54
+ do_build() {
55
+ inspec archive "$PROFILE_CACHE_DIR" \
56
+ --overwrite \
57
+ -o "$PROFILE_CACHE_DIR/$ARCHIVE_NAME"
58
+ }
59
+
60
+ do_install() {
61
+ cp "$PROFILE_CACHE_DIR/$ARCHIVE_NAME" "$pkg_prefix"
62
+ }
63
+
64
+ _do_compliance_login() {
65
+ if [ -z $COMPLIANCE_CREDS ]; then
66
+ message="ERROR: Please perform an 'inspec compliance login' and set"
67
+ message="$message \$HAB_STUDIO_SECRET_COMPLIANCE_CREDS to the contents of"
68
+ message="$message '~/.inspec/compliance/config.json'"
69
+ build_line "$message"
70
+ return 1
71
+ fi
72
+
73
+ user=$(echo $COMPLIANCE_CREDS | jq .user | sed 's/"//g')
74
+ token=$(echo $COMPLIANCE_CREDS | jq .token | sed 's/"//g')
75
+ automate_server=$(echo $COMPLIANCE_CREDS | \
76
+ jq .server | \
77
+ sed 's/\/api\/v0//' | \
78
+ sed 's/"//g'
79
+ )
80
+ insecure=$(echo $COMPLIANCE_CREDS | jq .insecure)
81
+ inspec compliance login --insecure $insecure \
82
+ --user $user \
83
+ --token $token \
84
+ $automate_server
85
+ }
@@ -0,0 +1,2 @@
1
+ source 'https://supermarket.chef.io'
2
+ metadata
@@ -0,0 +1,3 @@
1
+ # InSpec Habitat Fixture
2
+
3
+ Used to setup a server for testing the `inspec-habitat` plugin
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/expect -f
2
+
3
+ set timeout -1
4
+
5
+ spawn hab setup
6
+
7
+ expect "Connect to an on-premises bldr instance?"
8
+ send -- "No\r"
9
+
10
+ expect "Set up a default origin?"
11
+ send -- "Yes\r"
12
+
13
+ expect "Default origin name"
14
+ send -- "vagrant\r"
15
+
16
+ expect "Create an origin key for `vagrant'?"
17
+ send -- "Yes\r"
18
+
19
+ expect "Set up a default Habitat personal access token?"
20
+ send -- "No\r"
21
+
22
+ expect "Set up a default Habitat Supervisor CtlGateway secret?"
23
+ send -- "No\r"
24
+
25
+ expect "Enable analytics?"
26
+ send -- "No\r"
27
+
28
+ expect eof
@@ -0,0 +1,9 @@
1
+ name 'inspec_habitat_fixture'
2
+ maintainer 'The Authors'
3
+ maintainer_email 'you@example.com'
4
+ license 'All Rights Reserved'
5
+ description 'Used for testing the inspec-habitat plugin'
6
+ version '0.1.0'
7
+ chef_version '>= 13.0'
8
+
9
+ depends 'habitat'
@@ -0,0 +1,61 @@
1
+ #
2
+ # Cookbook:: kitchen_setup_cookbook
3
+ # Recipe:: default
4
+ #
5
+ # Copyright:: 2019, The Authors, All Rights Reserved.
6
+
7
+ package %w(ruby ruby-dev gcc g++ make expect)
8
+
9
+ base_dir = '/home/vagrant'
10
+
11
+ cookbook_file "#{base_dir}/inspec-local.gem" do
12
+ source 'inspec-local.gem'
13
+ action :create
14
+ end
15
+
16
+ gem_package 'inspec' do
17
+ source "#{base_dir}/inspec-local.gem"
18
+ subscribes :install, "cookbook_file[#{base_dir}/inspec-local.gem]", :immediately
19
+ end
20
+
21
+ cookbook_file "#{base_dir}/hab_setup.exp" do
22
+ source 'hab_setup.exp'
23
+ mode '0755'
24
+ action :create
25
+ end
26
+
27
+ hab_install 'install habitat'
28
+ hab_sup 'setup hab supervisor'
29
+
30
+ execute 'setup hab cli' do
31
+ command "#{base_dir}/hab_setup.exp"
32
+ live_stream true
33
+ not_if { ::File.exist?('/hab/etc/cli.toml') }
34
+ not_if { ::File.exist?('~/.hab/etc/cli.toml') }
35
+ end
36
+
37
+ execute 'create inspec profile for testing' do
38
+ command "inspec init profile #{base_dir}/hab_test_profile"
39
+ live_stream true
40
+ creates "#{base_dir}/hab_test_profile"
41
+ end
42
+
43
+ directory "#{base_dir}/output"
44
+
45
+ execute 'create hart file from profile' do
46
+ command "inspec habitat profile create #{base_dir}/hab_test_profile --output_dir '#{base_dir}/output'"
47
+ live_stream true
48
+ not_if "find #{base_dir}/output | grep vagrant-inspec-profile-hab_test_profile-0.1.0-.*.hart"
49
+ end
50
+
51
+ execute 'install vagrant/inspec-profile-hab_test_profile' do
52
+ command "hab pkg install #{base_dir}/output/*.hart"
53
+ live_stream true
54
+ not_if 'hab pkg list --origin vagrant | grep inspec-profile'
55
+ end
56
+
57
+ execute 'load vagrant/inspec-profile-hab_test_profile into supervisor' do
58
+ command 'hab svc load vagrant/inspec-profile-hab_test_profile'
59
+ live_stream true
60
+ not_if 'sudo hab svc status | grep "vagrant/inspec-profile-hab_test_profile"'
61
+ end
@@ -0,0 +1,38 @@
1
+ require_relative '../../../shared/core_plugin_test_helper.rb'
2
+ require 'fileutils'
3
+
4
+ class ProfileCli < MiniTest::Test
5
+ include CorePluginFunctionalHelper
6
+
7
+ def setup
8
+ @tmpdir = Dir.mktmpdir
9
+ @habitat_profile = File.join(@tmpdir, 'habitat-profile')
10
+ run_inspec_process('init profile ' + @habitat_profile)
11
+ end
12
+
13
+ def teardown
14
+ FileUtils.remove_entry_secure(@tmpdir)
15
+ end
16
+
17
+ def test_setup_subcommand
18
+ result = run_inspec_process('habitat profile setup ' + @habitat_profile + ' --log-level debug')
19
+
20
+ # Command runs without error
21
+ assert_empty result.stderr
22
+ assert_equal 0, result.exit_status
23
+
24
+ # Command creates only expected files
25
+ base_dir = File.join(@tmpdir, 'habitat-profile', 'habitat')
26
+ files = %w{
27
+ default.toml
28
+ plan.sh
29
+ config
30
+ config/inspec_exec_config.json
31
+ hooks
32
+ hooks/run
33
+ }
34
+ actual_files = Dir.glob(File.join(base_dir, '**/*'))
35
+ expected_files = files.map { |x| File.join(base_dir, x) }
36
+ assert_equal actual_files.sort, expected_files.sort
37
+ end
38
+ end
@@ -0,0 +1,3 @@
1
+ # Habitat InSpec Test Profile
2
+
3
+ This profile is used to test `inspec habitat profile` commands
@@ -0,0 +1,40 @@
1
+ control 'inspec-habitat-create' do
2
+ title 'Create command'
3
+
4
+ output_hart_dir = '/home/vagrant/output'
5
+ find_hart_output = command("find #{output_hart_dir} -name '*.hart'").stdout
6
+ hart_files = find_hart_output.split("\n")
7
+
8
+ hab_profile_path = '/home/vagrant/hab_test_profile'
9
+ find_profile_files_command = "find #{hab_profile_path} -type f -printf '%f\n'"
10
+ profile_files = command(find_profile_files_command).stdout.split("\n").sort
11
+ expected_files = %w{
12
+ .gitkeep
13
+ README.md
14
+ example.rb
15
+ inspec.yml
16
+ }
17
+
18
+ describe '`inspec habitat profile create`' do
19
+ it 'should create exactly 1 hart file' do
20
+ expect(hart_files.length).to eq(1)
21
+ end
22
+ it 'does not add any extra files to a default generated profile' do
23
+ expect(profile_files).to eq(expected_files)
24
+ end
25
+ end
26
+ end
27
+
28
+ control 'inspec-habitat-service' do
29
+ title 'inspec-profile-hab_test_profile service'
30
+ describe 'The running service' do
31
+ it 'should create a log file' do
32
+ log = '/hab/svc/inspec-profile-hab_test_profile/logs/inspec_log.txt'
33
+ expect(file(log).exist?).to be(true)
34
+ end
35
+ it 'should create a JSON file for the last run' do
36
+ log = '/hab/svc/inspec-profile-hab_test_profile/logs/inspec_last_run.json'
37
+ JSON.parse(file(log).content)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,10 @@
1
+ name: inspec_habitat
2
+ title: InSpec Profile
3
+ maintainer: The Authors
4
+ copyright: The Authors
5
+ copyright_email: you@example.com
6
+ license: Apache-2.0
7
+ summary: An InSpec Compliance Profile
8
+ version: 0.1.0
9
+ supports:
10
+ platform: os
@@ -0,0 +1,3 @@
1
+ # Example InSpec Profile
2
+
3
+ This profile is used for unit testing the `inspec-habitat` profile
@@ -0,0 +1,7 @@
1
+ control 'example' do
2
+ impact 0.7
3
+ title 'Example control'
4
+ describe 'example' do
5
+ it { should cmp 'example' }
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ name: example_profile
2
+ title: InSpec Profile
3
+ maintainer: The Authors
4
+ copyright: The Authors
5
+ copyright_email: you@example.com
6
+ license: Apache-2.0
7
+ summary: An InSpec Compliance Profile
8
+ version: 0.1.0
9
+ supports:
10
+ platform: os
@@ -1,184 +1,240 @@
1
1
  require 'mixlib/log'
2
- require 'ostruct'
2
+ require 'fileutils'
3
3
  require 'minitest/autorun'
4
- require 'mocha/setup'
5
4
  require_relative '../../lib/inspec-habitat/profile.rb'
6
5
 
7
- describe InspecPlugins::Habitat::Profile do
8
- let(:profile) do
9
- OpenStruct.new(
10
- name: 'my_profile',
11
- version: '1.2.3',
12
- files: %w(file1 file2)
6
+ class InspecPlugins::Habitat::ProfileTest < MiniTest::Unit::TestCase
7
+ def setup
8
+ @tmpdir = Dir.mktmpdir
9
+
10
+ @output_dir = File.join(@tmpdir, 'output')
11
+ FileUtils.mkdir(@output_dir)
12
+
13
+ @fake_hart_file = FileUtils.touch(File.join(@tmpdir, 'fake-hart.hart'))[0]
14
+
15
+ # Path from `__FILE__` needed to support running tests in `inspec/inspec`
16
+ @test_profile_path = File.join(
17
+ File.expand_path(File.dirname(__FILE__)),
18
+ '../',
19
+ 'support',
20
+ 'example_profile'
21
+ )
22
+ @test_profile = Inspec::Profile.for_target(
23
+ @test_profile_path,
24
+ backend: Inspec::Backend.create(Inspec::Config.mock),
13
25
  )
14
- end
15
26
 
16
- let(:subject) { InspecPlugins::Habitat::Profile.new('/path/to/profile', { 'log_level' => 'fatal' }) }
27
+ @hab_profile = InspecPlugins::Habitat::Profile.new(
28
+ @test_profile_path,
29
+ { output_dir: @output_dir },
30
+ )
31
+
32
+ @mock_hab_config = {
33
+ 'auth_token' => 'FAKETOKEN',
34
+ 'origin' => 'fake_origin',
35
+ }
17
36
 
18
- before do
19
37
  Inspec::Log.level(:fatal)
20
38
  end
21
39
 
22
- describe '#verify_profile' do
23
- it 'exits if the profile is not valid' do
24
- profile = mock
25
- profile.stubs(:check).returns(summary: { valid: false })
26
- subject.expects(:profile).returns(profile)
27
- proc { subject.send(:verify_profile) }.must_raise SystemExit
28
- end
29
-
30
- it 'does not exist if the profile is valid' do
31
- profile = mock
32
- profile.stubs(:check).returns(summary: { valid: true })
33
- subject.expects(:profile).returns(profile)
34
- subject.send(:verify_profile)
35
- end
40
+ def after_run
41
+ FileUtils.remove_entry_secure(@tmpdir)
36
42
  end
37
43
 
38
- describe '#vendor_profile_dependencies' do
39
- let(:profile_vendor) do
40
- profile_vendor = mock
41
- profile_vendor.stubs(:lockfile).returns(lockfile)
42
- profile_vendor.stubs(:cache_path).returns(cache_path)
43
- profile_vendor
44
- end
45
- let(:lockfile) { mock }
46
- let(:cache_path) { mock }
44
+ def test_create_raises_if_output_dir_does_not_exist
45
+ profile = InspecPlugins::Habitat::Profile.new(
46
+ @test_profile_path,
47
+ {
48
+ output_dir: '/not/a/real/path',
49
+ log_level: 'fatal',
50
+ },
51
+ )
47
52
 
48
- before do
49
- Inspec::ProfileVendor.expects(:new).returns(profile_vendor)
50
- end
53
+ assert_raises(SystemExit) { profile.create }
54
+ # TODO: Figure out how to capture and validate `Inspec::Log.error`
55
+ end
51
56
 
52
- describe 'when lockfile exists and cache dir exists' do
53
- it 'does not vendor the dependencies' do
54
- lockfile.expects(:exist?).returns(true)
55
- cache_path.expects(:exist?).returns(true)
56
- profile_vendor.expects(:vendor!).never
57
- profile_vendor.expects(:make_readable).never
58
- subject.send(:vendor_profile_dependencies)
57
+ def test_create
58
+ file_count = Dir.glob(File.join(@test_profile_path, '**/*')).count
59
+
60
+ @hab_profile.stub :read_habitat_config, @mock_hab_config do
61
+ @hab_profile.stub :verify_habitat_setup, nil do
62
+ @hab_profile.stub :build_hart, @fake_hart_file do
63
+ @hab_profile.create
64
+ end
59
65
  end
60
66
  end
61
67
 
62
- describe 'when the lockfile exists but the cache dir does not' do
63
- it 'vendors the dependencies and refreshes the profile object' do
64
- lockfile.expects(:exist?).returns(true)
65
- cache_path.expects(:exist?).returns(false)
66
- profile_vendor.expects(:vendor!)
67
- profile_vendor.expects(:make_readable)
68
- subject.expects(:create_profile_object)
68
+ # It should not modify target profile
69
+ new_file_count = Dir.glob(File.join(@test_profile_path, '**/*')).count
70
+ assert_equal new_file_count, file_count
69
71
 
70
- subject.send(:vendor_profile_dependencies)
71
- end
72
+ # It should create 1 Habitat artifact
73
+ output_files = Dir.glob(File.join(@output_dir, '**/*'))
74
+ assert_equal 1, output_files.count
75
+ assert_equal 'fake-hart.hart', File.basename(output_files.first)
76
+ end
77
+
78
+ def test_create_rasies_if_habitat_is_not_installed
79
+ cmd = MiniTest::Mock.new
80
+ cmd.expect(:error?, true)
81
+ cmd.expect(:run_command, nil)
82
+
83
+ Mixlib::ShellOut.stub :new, cmd, 'hab --version' do
84
+ assert_raises(SystemExit) { @hab_profile.create }
85
+ # TODO: Figure out how to capture and validate `Inspec::Log.error`
72
86
  end
73
87
 
74
- describe 'when the lockfile does not exist' do
75
- it 'vendors the dependencies and refreshes the profile object' do
76
- lockfile.expects(:exist?).returns(false)
77
- profile_vendor.expects(:vendor!)
78
- profile_vendor.expects(:make_readable)
79
- subject.expects(:create_profile_object)
88
+ cmd.verify
89
+ end
80
90
 
81
- subject.send(:vendor_profile_dependencies)
91
+ def test_upload
92
+ @hab_profile.stub :read_habitat_config, @mock_hab_config do
93
+ @hab_profile.stub :create, @fake_hart_file do
94
+ @hab_profile.stub :upload_hart, nil do
95
+ @hab_profile.upload
96
+ # TODO: Figure out how to capture and validate `Inspec::Log.error`
97
+ end
82
98
  end
83
99
  end
84
100
  end
85
101
 
86
- describe '#validate_habitat_installed' do
87
- it 'exits if hab --version fails' do
88
- cmd = mock
89
- cmd.stubs(:error?).returns(true)
90
- cmd.stubs(:run_command)
91
- cmd.stubs(:stdout)
92
- cmd.stubs(:stderr)
93
- Mixlib::ShellOut.expects(:new).with('hab --version').returns(cmd)
94
- proc { subject.send(:validate_habitat_installed) }.must_raise SystemExit
102
+ def test_upload_raises_if_no_habitat_auth_token_is_found
103
+ @hab_profile.stub :read_habitat_config, {} do
104
+ assert_raises(SystemExit) { @hab_profile.upload }
105
+ # TODO: Figure out how to capture and validate `Inspec::Log.error`
95
106
  end
96
107
  end
97
108
 
98
- describe '#validate_habitat_origin' do
99
- it 'does not exit if the origin key exists' do
100
- subject.expects(:habitat_origin).returns('12345')
101
- subject.send(:validate_habitat_origin)
109
+ def test_create_working_dir
110
+ Dir.stub :mktmpdir, '/tmp/fakedir' do
111
+ assert_equal '/tmp/fakedir', @hab_profile.send(:create_working_dir)
102
112
  end
113
+ end
103
114
 
104
- it 'exits if no origin key exists' do
105
- subject.expects(:habitat_origin).returns(nil)
106
- proc { subject.send(:validate_habitat_origin) }.must_raise SystemExit
107
- end
115
+ def test_duplicate_profile
116
+ current_profile = @test_profile
117
+ duplicated_profile = @hab_profile.send(:duplicate_profile,
118
+ @test_profile_path,
119
+ @tmpdir)
120
+ assert duplicated_profile.is_a?(Inspec::Profile)
121
+ assert duplicated_profile.sha256 == current_profile.sha256.to_s
122
+ refute_same duplicated_profile.root_path, current_profile.root_path
108
123
  end
109
124
 
110
- describe '#validate_habitat_auth_token' do
111
- it 'does not exit if the auth_token exists' do
112
- subject.expects(:habitat_auth_token).returns('12345')
113
- subject.send(:validate_habitat_auth_token)
114
- end
125
+ def test_profile_from_path
126
+ profile = @hab_profile.send(:profile_from_path, @test_profile_path)
127
+ assert profile.is_a?(Inspec::Profile)
128
+ end
115
129
 
116
- it 'exits if no auth_token exists' do
117
- subject.expects(:habitat_auth_token).returns(nil)
118
- proc { subject.send(:validate_habitat_auth_token) }.must_raise SystemExit
119
- end
130
+ def test_copy_profile_to_working_dir
131
+ duplicated_profile = @hab_profile.send(:duplicate_profile,
132
+ @test_profile_path,
133
+ @tmpdir)
134
+
135
+ dst = File.join(@tmpdir, 'working_dir')
136
+ FileUtils.mkdir_p(dst)
137
+ @hab_profile.send(:copy_profile_to_working_dir, duplicated_profile, dst)
138
+
139
+ expected_files = %w{
140
+ README.md
141
+ inspec.yml
142
+ example.rb
143
+ }
144
+
145
+ actual_files = Dir.glob(File.join(dst, '**/*')).map do |path|
146
+ next unless File.file?(path)
147
+ File.basename(path)
148
+ end.compact
149
+
150
+ assert(actual_files.sort == expected_files.sort)
120
151
  end
121
152
 
122
- describe '#build_hart' do
123
- before do
124
- subject.expects(:work_dir).at_least_once.returns(Dir.tmpdir)
125
- end
153
+ def test_verify_profile_raises_if_profile_is_not_valid
154
+ bad_profile_path = File.join(@tmpdir, 'bad_profile')
155
+ FileUtils.mkdir_p(File.join(bad_profile_path))
156
+ FileUtils.touch(File.join(bad_profile_path, 'inspec.yml'))
157
+ bad_profile = Inspec::Profile.for_target(
158
+ bad_profile_path,
159
+ backend: Inspec::Backend.create(Inspec::Config.mock),
160
+ )
161
+ assert_raises(SystemExit) { @hab_profile.send(:verify_profile, bad_profile) }
162
+ # TODO: Figure out how to capture and validate `Inspec::Log.error`
163
+ end
126
164
 
127
- it 'exits if the build fails' do
128
- subject.expects(:system).returns(false)
129
- proc { subject.send(:build_hart) }.must_raise SystemExit
130
- end
165
+ def test_vendor_profile_dependencies_does_not_vendor_if_already_vendored
166
+ mock_lock_file = MiniTest::Mock.new
167
+ mock_lock_file.expect(:exist?, true)
168
+ mock_cache_path = MiniTest::Mock.new
169
+ mock_cache_path.expect(:exist?, true)
131
170
 
132
- it 'exits if more than one hart is created' do
133
- subject.expects(:system).returns(true)
134
- Dir.expects(:glob).returns(%w(hart1 hart2))
135
- proc { subject.send(:build_hart) }.must_raise SystemExit
136
- end
171
+ mock = MiniTest::Mock.new
172
+ mock.expect(:lockfile, mock_lock_file)
173
+ mock.expect(:cache_path, mock_cache_path)
137
174
 
138
- it 'exits if more than no hart is created' do
139
- subject.expects(:system).returns(true)
140
- Dir.expects(:glob).returns([])
141
- proc { subject.send(:build_hart) }.must_raise SystemExit
175
+ Inspec::ProfileVendor.stub :new, mock do
176
+ new_profile = @hab_profile.send(:vendor_profile_dependencies!,
177
+ @test_profile)
178
+ assert new_profile.is_a?(Inspec::Profile)
142
179
  end
180
+ end
181
+
182
+ def test_vendor_profile_dependencies
183
+ mock_lock_file = MiniTest::Mock.new
184
+ mock_lock_file.expect(:exist?, false)
185
+
186
+ mock = MiniTest::Mock.new
187
+ mock.expect(:lockfile, mock_lock_file)
188
+ mock.expect(:vendor!, nil)
189
+ mock.expect(:make_readable, nil)
143
190
 
144
- it 'returns the hart filename' do
145
- subject.expects(:system).returns(true)
146
- Dir.expects(:glob).returns(%w(hart1))
147
- subject.send(:build_hart).must_equal('hart1')
191
+ Inspec::ProfileVendor.stub :new, mock do
192
+ new_profile = @hab_profile.send(:vendor_profile_dependencies!,
193
+ @test_profile)
194
+ assert new_profile.is_a?(Inspec::Profile)
148
195
  end
196
+ mock.verify
149
197
  end
150
198
 
151
- describe '#upload_hart' do
152
- it 'exits if the upload failed' do
153
- env = {
154
- 'TERM' => 'vt100',
155
- 'HAB_AUTH_TOKEN' => 'my_token',
156
- 'HAB_NONINTERACTIVE' => 'true',
157
- }
199
+ def test_verify_habitat_setup_raises_if_hab_version_errors
200
+ mock = MiniTest::Mock.new
201
+ mock.expect(:run_command, nil)
202
+ mock.expect(:error?, true)
203
+ mock.expect(:stderr, 'This would be an error message')
158
204
 
159
- cmd = mock
160
- cmd.stubs(:run_command)
161
- cmd.stubs(:error?).returns(true)
162
- cmd.stubs(:stdout)
163
- cmd.stubs(:stderr)
164
-
165
- subject.expects(:habitat_auth_token).returns('my_token')
166
- Mixlib::ShellOut.expects(:new).with("hab pkg upload my_hart", env: env).returns(cmd)
167
- proc { subject.send(:upload_hart, 'my_hart') }.must_raise SystemExit
205
+ Mixlib::ShellOut.stub(:new, mock) do
206
+ assert_raises(SystemExit) { @hab_profile.send(:verify_habitat_setup, {}) }
207
+ # TODO: Figure out how to capture and validate `Inspec::Log.error`
168
208
  end
209
+ mock.verify
169
210
  end
170
211
 
171
- describe '#habitat_cli_config' do
172
- it 'returns an empty hash if the CLI config does not exist' do
173
- File.expects(:exist?).with(File.join(ENV['HOME'], '.hab', 'etc', 'cli.toml')).returns(false)
174
- subject.send(:habitat_cli_config).must_equal({})
212
+ def test_verify_habitat_setup_raises_if_not_habitat_origin
213
+ mock = MiniTest::Mock.new
214
+ mock.expect(:run_command, nil)
215
+ mock.expect(:error?, false)
216
+
217
+ Mixlib::ShellOut.stub(:new, mock) do
218
+ assert_raises(SystemExit) { @hab_profile.send(:verify_habitat_setup, {}) }
219
+ # TODO: Figure out how to capture and validate `Inspec::Log.error`
175
220
  end
221
+ mock.verify
222
+ end
223
+
224
+ # TODO: Figure out how to stub system()
225
+ # def test_build_hart
226
+ # end
227
+
228
+ def test_upload_hart_raises_if_hab_pkg_upload_fails
229
+ mock = MiniTest::Mock.new
230
+ mock.expect(:run_command, nil)
231
+ mock.expect(:error?, true)
232
+ mock.expect(:stdout, 'This would contain output from `hab`')
233
+ mock.expect(:stderr, 'This would be an error message')
176
234
 
177
- it 'returns parsed TOML from the hab config file' do
178
- config_file = File.join(ENV['HOME'], '.hab', 'etc', 'cli.toml')
179
- File.expects(:exist?).with(config_file).returns(true)
180
- Tomlrb.expects(:load_file).with(config_file).returns(foo: 1)
181
- subject.send(:habitat_cli_config).must_equal(foo: 1)
235
+ Mixlib::ShellOut.stub(:new, mock) do
236
+ assert_raises(SystemExit) { @hab_profile.send(:upload_hart, @fake_hart_file, {}) }
237
+ # TODO: Figure out how to capture and validate `Inspec::Log.error`
182
238
  end
183
239
  end
184
240
  end