inspec-core 3.7.1 → 3.7.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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