inspec 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.
- checksums.yaml +4 -4
- data/Gemfile +7 -2
- data/lib/inspec/config.rb +12 -0
- data/lib/inspec/shell.rb +2 -15
- data/lib/inspec/version.rb +1 -1
- data/lib/plugins/inspec-habitat/Berksfile +5 -0
- data/lib/plugins/inspec-habitat/README.md +150 -0
- data/lib/plugins/inspec-habitat/kitchen.yml +28 -0
- data/lib/plugins/inspec-habitat/lib/inspec-habitat/cli.rb +9 -9
- data/lib/plugins/inspec-habitat/lib/inspec-habitat/profile.rb +164 -280
- data/lib/plugins/inspec-habitat/templates/habitat/config/inspec_exec_config.json.erb +25 -0
- data/lib/plugins/inspec-habitat/templates/habitat/default.toml.erb +9 -0
- data/lib/plugins/inspec-habitat/templates/habitat/hooks/run.erb +32 -0
- data/lib/plugins/inspec-habitat/templates/habitat/plan.sh.erb +85 -0
- data/lib/plugins/inspec-habitat/test/cookbooks/inspec_habitat_fixture/Berksfile +2 -0
- data/lib/plugins/inspec-habitat/test/cookbooks/inspec_habitat_fixture/README.md +3 -0
- data/lib/plugins/inspec-habitat/test/cookbooks/inspec_habitat_fixture/files/hab_setup.exp +28 -0
- data/lib/plugins/inspec-habitat/test/cookbooks/inspec_habitat_fixture/metadata.rb +9 -0
- data/lib/plugins/inspec-habitat/test/cookbooks/inspec_habitat_fixture/recipes/default.rb +61 -0
- data/lib/plugins/inspec-habitat/test/functional/inspec_habitat_test.rb +38 -0
- data/lib/plugins/inspec-habitat/test/integration/default/inspec_habitat/README.md +3 -0
- data/lib/plugins/inspec-habitat/test/integration/default/inspec_habitat/controls/inspec_habitat.rb +40 -0
- data/lib/plugins/inspec-habitat/test/integration/default/inspec_habitat/inspec.yml +10 -0
- data/lib/plugins/inspec-habitat/test/support/example_profile/README.md +3 -0
- data/lib/plugins/inspec-habitat/test/support/example_profile/controls/example.rb +7 -0
- data/lib/plugins/inspec-habitat/test/support/example_profile/inspec.yml +10 -0
- data/lib/plugins/inspec-habitat/test/unit/profile_test.rb +188 -132
- data/lib/plugins/inspec-init/templates/profiles/azure/README.md +56 -0
- data/lib/plugins/inspec-init/templates/profiles/azure/controls/example.rb +15 -0
- data/lib/plugins/inspec-init/templates/profiles/azure/inspec.yml +14 -0
- data/lib/plugins/inspec-init/templates/profiles/azure/libraries/.gitkeep +0 -0
- data/lib/plugins/inspec-init/test/functional/inspec_init_profile_test.rb +12 -0
- data/lib/resources/aide_conf.rb +2 -2
- data/lib/resources/apache.rb +2 -2
- data/lib/resources/apache_conf.rb +2 -2
- data/lib/resources/apt.rb +2 -2
- data/lib/resources/audit_policy.rb +2 -2
- data/lib/resources/auditd.rb +2 -2
- data/lib/resources/auditd_conf.rb +2 -2
- data/lib/resources/aws/aws_billing_report.rb +3 -2
- data/lib/resources/aws/aws_billing_reports.rb +11 -10
- data/lib/resources/aws/aws_cloudtrail_trail.rb +2 -2
- data/lib/resources/aws/aws_cloudtrail_trails.rb +2 -2
- data/lib/resources/aws/aws_cloudwatch_alarm.rb +9 -9
- data/lib/resources/aws/aws_cloudwatch_log_metric_filter.rb +18 -18
- data/lib/resources/aws/aws_config_delivery_channel.rb +2 -2
- data/lib/resources/aws/aws_config_recorder.rb +2 -2
- data/lib/resources/aws/aws_ebs_volume.rb +2 -2
- data/lib/resources/aws/aws_ebs_volumes.rb +2 -2
- data/lib/resources/aws/aws_ec2_instance.rb +2 -2
- data/lib/resources/aws/aws_ec2_instances.rb +2 -2
- data/lib/resources/aws/aws_ecs_cluster.rb +2 -2
- data/lib/resources/aws/aws_eks_cluster.rb +2 -2
- data/lib/resources/aws/aws_elb.rb +2 -2
- data/lib/resources/aws/aws_elbs.rb +2 -2
- data/lib/resources/aws/aws_flow_log.rb +2 -2
- data/lib/resources/aws/aws_iam_access_key.rb +2 -2
- data/lib/resources/aws/aws_iam_access_keys.rb +2 -2
- data/lib/resources/aws/aws_iam_group.rb +2 -2
- data/lib/resources/aws/aws_iam_groups.rb +2 -2
- data/lib/resources/aws/aws_iam_password_policy.rb +2 -2
- data/lib/resources/aws/aws_iam_policies.rb +2 -2
- data/lib/resources/aws/aws_iam_policy.rb +2 -2
- data/lib/resources/aws/aws_iam_role.rb +2 -2
- data/lib/resources/aws/aws_iam_root_user.rb +2 -2
- data/lib/resources/aws/aws_iam_user.rb +2 -2
- data/lib/resources/aws/aws_iam_users.rb +2 -2
- data/lib/resources/aws/aws_kms_key.rb +2 -2
- data/lib/resources/aws/aws_kms_keys.rb +2 -2
- data/lib/resources/aws/aws_rds_instance.rb +2 -2
- data/lib/resources/aws/aws_route_table.rb +2 -2
- data/lib/resources/aws/aws_route_tables.rb +2 -2
- data/lib/resources/aws/aws_s3_bucket.rb +2 -2
- data/lib/resources/aws/aws_s3_bucket_object.rb +2 -2
- data/lib/resources/aws/aws_s3_buckets.rb +2 -2
- data/lib/resources/aws/aws_security_group.rb +5 -5
- data/lib/resources/aws/aws_security_groups.rb +2 -2
- data/lib/resources/aws/aws_sns_subscription.rb +2 -2
- data/lib/resources/aws/aws_sns_topic.rb +2 -2
- data/lib/resources/aws/aws_sns_topics.rb +2 -2
- data/lib/resources/aws/aws_sqs_queue.rb +2 -2
- data/lib/resources/aws/aws_subnet.rb +2 -2
- data/lib/resources/aws/aws_subnets.rb +2 -2
- data/lib/resources/aws/aws_vpc.rb +2 -2
- data/lib/resources/aws/aws_vpcs.rb +2 -2
- data/lib/resources/bash.rb +2 -2
- data/lib/resources/bond.rb +2 -2
- data/lib/resources/bridge.rb +2 -2
- data/lib/resources/chocolatey_package.rb +2 -2
- data/lib/resources/command.rb +2 -2
- data/lib/resources/cpan.rb +2 -2
- data/lib/resources/cran.rb +2 -2
- data/lib/resources/crontab.rb +2 -2
- data/lib/resources/csv.rb +2 -2
- data/lib/resources/dh_params.rb +2 -2
- data/lib/resources/directory.rb +2 -2
- data/lib/resources/docker.rb +2 -2
- data/lib/resources/docker_container.rb +2 -2
- data/lib/resources/docker_image.rb +2 -2
- data/lib/resources/docker_plugin.rb +2 -2
- data/lib/resources/docker_service.rb +2 -2
- data/lib/resources/elasticsearch.rb +2 -2
- data/lib/resources/etc_fstab.rb +2 -2
- data/lib/resources/etc_group.rb +2 -2
- data/lib/resources/etc_hosts.rb +2 -2
- data/lib/resources/etc_hosts_allow_deny.rb +4 -4
- data/lib/resources/file.rb +2 -2
- data/lib/resources/filesystem.rb +2 -2
- data/lib/resources/firewalld.rb +2 -2
- data/lib/resources/gem.rb +2 -2
- data/lib/resources/groups.rb +4 -4
- data/lib/resources/grub_conf.rb +2 -2
- data/lib/resources/host.rb +2 -2
- data/lib/resources/http.rb +25 -5
- data/lib/resources/iis_app.rb +2 -2
- data/lib/resources/iis_app_pool.rb +6 -3
- data/lib/resources/iis_site.rb +4 -4
- data/lib/resources/inetd_conf.rb +2 -2
- data/lib/resources/ini.rb +2 -2
- data/lib/resources/interface.rb +2 -2
- data/lib/resources/iptables.rb +2 -2
- data/lib/resources/json.rb +2 -3
- data/lib/resources/kernel_module.rb +17 -18
- data/lib/resources/kernel_parameter.rb +2 -2
- data/lib/resources/key_rsa.rb +2 -2
- data/lib/resources/ksh.rb +2 -2
- data/lib/resources/limits_conf.rb +2 -2
- data/lib/resources/login_def.rb +2 -2
- data/lib/resources/mount.rb +2 -2
- data/lib/resources/mssql_session.rb +2 -2
- data/lib/resources/mysql_conf.rb +2 -2
- data/lib/resources/mysql_session.rb +2 -2
- data/lib/resources/nginx.rb +2 -2
- data/lib/resources/nginx_conf.rb +2 -2
- data/lib/resources/npm.rb +2 -2
- data/lib/resources/ntp_conf.rb +2 -2
- data/lib/resources/oneget.rb +2 -2
- data/lib/resources/oracledb_session.rb +2 -2
- data/lib/resources/os.rb +2 -2
- data/lib/resources/os_env.rb +2 -2
- data/lib/resources/package.rb +2 -2
- data/lib/resources/packages.rb +2 -2
- data/lib/resources/parse_config.rb +4 -4
- data/lib/resources/passwd.rb +2 -2
- data/lib/resources/pip.rb +2 -2
- data/lib/resources/platform.rb +2 -2
- data/lib/resources/port.rb +2 -2
- data/lib/resources/postgres_conf.rb +2 -2
- data/lib/resources/postgres_hba_conf.rb +2 -2
- data/lib/resources/postgres_ident_conf.rb +2 -2
- data/lib/resources/postgres_session.rb +2 -2
- data/lib/resources/powershell.rb +2 -2
- data/lib/resources/processes.rb +2 -2
- data/lib/resources/rabbitmq_conf.rb +2 -2
- data/lib/resources/registry_key.rb +2 -2
- data/lib/resources/security_identifier.rb +2 -2
- data/lib/resources/security_policy.rb +2 -2
- data/lib/resources/service.rb +14 -14
- data/lib/resources/shadow.rb +2 -2
- data/lib/resources/ssh_conf.rb +4 -4
- data/lib/resources/ssl.rb +2 -2
- data/lib/resources/sys_info.rb +2 -2
- data/lib/resources/toml.rb +2 -2
- data/lib/resources/users.rb +4 -4
- data/lib/resources/vbscript.rb +2 -2
- data/lib/resources/virtualization.rb +2 -2
- data/lib/resources/windows_feature.rb +2 -2
- data/lib/resources/windows_hotfix.rb +2 -2
- data/lib/resources/windows_task.rb +2 -2
- data/lib/resources/wmi.rb +2 -2
- data/lib/resources/x509_certificate.rb +2 -2
- data/lib/resources/xinetd.rb +2 -2
- data/lib/resources/xml.rb +2 -2
- data/lib/resources/yaml.rb +2 -2
- data/lib/resources/yum.rb +2 -2
- data/lib/resources/zfs_dataset.rb +2 -2
- data/lib/resources/zfs_pool.rb +2 -2
- metadata +26 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0cac247e4c431779ae6dde11e5d4a8ad35a0a06dcd98a267ccb6e8dad37bda98
|
|
4
|
+
data.tar.gz: 33924d693f865466f4ad6c97b8601a8b87f1e81a16877a6454c2a5749cac26be
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ed07328de84c51b24bcb45dd551dd3853baa7ac6b5de061782062e06bd41e3badc5262259e2d8ce8e887c6f26562712e1c65d8d1d2102d34f04cc189f7239add
|
|
7
|
+
data.tar.gz: 3270590d5506f73aca604f9bd9fb4618a4e478708925cac9cd558a400aeb745d511e7cd07e57b644c1c3d9dbb3876520755cd84886c3e4de873dd39b457f2fc7
|
data/Gemfile
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
source 'https://rubygems.org'
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
gem 'inspec', path: '.'
|
|
5
5
|
|
|
6
6
|
gem 'ffi', '>= 1.9.14'
|
|
7
7
|
gem 'aws-sdk', '~> 2'
|
|
8
8
|
|
|
9
|
+
group :omnibus do
|
|
10
|
+
gem 'rb-readline'
|
|
11
|
+
gem 'appbundler'
|
|
12
|
+
gem 'unf_ext', git: 'https://github.com/chef/ruby-unf_ext.git', ref: '55d872fb15f3a26e4ee8f8dbe7ba859c80d40383'
|
|
13
|
+
end
|
|
14
|
+
|
|
9
15
|
group :test do
|
|
10
16
|
gem 'minitest', '~> 5.5'
|
|
11
17
|
gem 'rake', '>= 10'
|
|
@@ -36,7 +42,6 @@ end
|
|
|
36
42
|
|
|
37
43
|
group :tools do
|
|
38
44
|
gem 'pry', '~> 0.10'
|
|
39
|
-
gem 'rb-readline'
|
|
40
45
|
gem 'license_finder'
|
|
41
46
|
gem 'git', '~> 1.4'
|
|
42
47
|
end
|
data/lib/inspec/config.rb
CHANGED
|
@@ -30,6 +30,17 @@ module Inspec
|
|
|
30
30
|
Inspec::Config.new({ backend: :mock }.merge(opts), StringIO.new('{}'))
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
+
# Use this to get a cached version of the config. This prevents you from
|
|
34
|
+
# being required to pass it around everywhere.
|
|
35
|
+
def self.cached
|
|
36
|
+
@cached_config
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def self.cached=(cfg)
|
|
40
|
+
@cached_config ||= cfg
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# This gets called when the first config is created.
|
|
33
44
|
def initialize(cli_opts = {}, cfg_io = nil, command_name = nil)
|
|
34
45
|
@command_name = command_name || (ARGV.empty? ? nil : ARGV[0].to_sym)
|
|
35
46
|
@defaults = Defaults.for_command(@command_name)
|
|
@@ -40,6 +51,7 @@ module Inspec
|
|
|
40
51
|
|
|
41
52
|
@merged_options = merge_options
|
|
42
53
|
@final_options = finalize_options
|
|
54
|
+
self.class.cached = self
|
|
43
55
|
end
|
|
44
56
|
|
|
45
57
|
def diagnose
|
data/lib/inspec/shell.rb
CHANGED
|
@@ -80,19 +80,6 @@ module Inspec
|
|
|
80
80
|
"\e[1m\e[39m#{x}\e[0m"
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
-
def print_example(example)
|
|
84
|
-
# determine min whitespace that can be removed
|
|
85
|
-
min = nil
|
|
86
|
-
example.lines.each do |line|
|
|
87
|
-
if !line.strip.empty? # ignore empty lines
|
|
88
|
-
line_whitespace = line.length - line.lstrip.length
|
|
89
|
-
min = line_whitespace if min.nil? || line_whitespace < min
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
# remove whitespace from each line
|
|
93
|
-
example.gsub(/\n\s{#{min}}/, "\n")
|
|
94
|
-
end
|
|
95
|
-
|
|
96
83
|
def intro
|
|
97
84
|
puts 'Welcome to the interactive InSpec Shell'
|
|
98
85
|
puts "To find out how to use it, type: #{mark 'help'}"
|
|
@@ -142,8 +129,8 @@ module Inspec
|
|
|
142
129
|
end
|
|
143
130
|
|
|
144
131
|
unless topic_info.example.nil?
|
|
145
|
-
info += "#{mark 'Example:'}\n"
|
|
146
|
-
info += "#{
|
|
132
|
+
info += "#{mark 'Example:'}\n\n"
|
|
133
|
+
info += "#{topic_info.example}\n\n"
|
|
147
134
|
end
|
|
148
135
|
|
|
149
136
|
info += "#{mark 'Web Reference:'}\n\n"
|
data/lib/inspec/version.rb
CHANGED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# InSpec Habitat Plugin
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
|
|
5
|
+
This plugin allows you to do the following:
|
|
6
|
+
1. Add Habitat configuration to a profile
|
|
7
|
+
2. Create/Upload a Habitat package from an InSpec profile
|
|
8
|
+
|
|
9
|
+
Creating a [Habitat](https://www.habitat.sh/) package from an InSpec profile
|
|
10
|
+
allows you to execute that profile as a service (via a Habitat Supervisor) on
|
|
11
|
+
any Linux based platform.
|
|
12
|
+
|
|
13
|
+
When running as a service, an InSpec report will be created in JSON format (by
|
|
14
|
+
default at `/hab/svc/YOUR_SERVICE/logs/inspec_last_run.json`). Additionally, a
|
|
15
|
+
log of the last run will be located at
|
|
16
|
+
`/hab/svc/YOUR_SERVICE/logs/inspec_log.txt` and CLI output is viewable in
|
|
17
|
+
the Supervisor logs by default. You can also configure this service to report
|
|
18
|
+
to [Chef Automate](https://www.chef.io/automate/).
|
|
19
|
+
|
|
20
|
+
See below for usage instructions.
|
|
21
|
+
|
|
22
|
+
## Plugin Usage
|
|
23
|
+
|
|
24
|
+
### Adding Habitat Configuration to an InSpec Profile
|
|
25
|
+
|
|
26
|
+
Run the following command:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
inspec habitat profile setup PATH
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
This will create the following files:
|
|
33
|
+
- habitat/plan.sh (Provides build time instructions to Habitat)
|
|
34
|
+
- habitat/default.toml (Used to configure the running Habitat service)
|
|
35
|
+
- habitat/hooks/run (Shell script to execute this profile as a service)
|
|
36
|
+
- habitat/config/inspec_exec_config.json (JSON for `inspec exec` CLI options)
|
|
37
|
+
|
|
38
|
+
### Creating a Habitat Package
|
|
39
|
+
|
|
40
|
+
> This command requires Habitat to be installed and configured. For instructions
|
|
41
|
+
on how to do that see [here](https://www.habitat.sh/docs/install-habitat/).
|
|
42
|
+
|
|
43
|
+
Run the following command:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
inspec habitat profile create PATH
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
This command will:
|
|
50
|
+
- Create a Habitat artifact (`.hart` file).
|
|
51
|
+
|
|
52
|
+
> NOTE: If you are fetching packages from Chef Automate see
|
|
53
|
+
[below](#Integrating-with-Chef-Automate).
|
|
54
|
+
|
|
55
|
+
### Uploading a Habitat Package
|
|
56
|
+
|
|
57
|
+
> This command requires Habitat to be installed and configured. For instructions
|
|
58
|
+
on how to do that see [here](https://www.habitat.sh/docs/install-habitat/).
|
|
59
|
+
|
|
60
|
+
Run the following command:
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
inspec habitat profile upload PATH
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
This command will:
|
|
67
|
+
- Create a Habitat artifact (`.hart` file).
|
|
68
|
+
- Upload the Habitat artifact to [bldr.habitat.sh](bldr.habitat.sh).
|
|
69
|
+
|
|
70
|
+
> NOTE: If you are fetching packages from Chef Automate see
|
|
71
|
+
[below](#Integrating-with-Chef-Automate).
|
|
72
|
+
|
|
73
|
+
## Habitat Package Usage
|
|
74
|
+
|
|
75
|
+
> This command requires Habitat to be installed and configured. For instructions
|
|
76
|
+
on how to do that see [here](https://www.habitat.sh/docs/install-habitat/).
|
|
77
|
+
|
|
78
|
+
General usage instructions for using Habitat packages can be found
|
|
79
|
+
[here](https://www.habitat.sh/docs/using-habitat/#Using-Habitat-Packages).
|
|
80
|
+
|
|
81
|
+
Installing the package from a HART file:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
# See Habitat docs for more info. The below is for testing only.
|
|
85
|
+
hab pkg install PATH_TO_CREATED_HART_FILE
|
|
86
|
+
hab sup run YOUR_ORIGIN/inspec-profile-YOUR_PROFILE_NAME
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Installing the package from the Public Builder Depot:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
# See Habitat docs for more info. The below is for testing only.
|
|
93
|
+
hab pkg install YOUR_ORIGIN/inspec-profile-YOUR_PROFILE_NAME
|
|
94
|
+
hab sup run YOUR_ORIGIN/inspec-profile-YOUR_PROFILE_NAME
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Integrating with Chef Automate
|
|
98
|
+
|
|
99
|
+
### Fetching Profiles from Chef Automate During Build
|
|
100
|
+
|
|
101
|
+
Fetching profiles from Chef Automate requires authentication.
|
|
102
|
+
|
|
103
|
+
Run the following commands prior to creating/uploading your Habitat package:
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
# Remove -k if you are not using a self-signed certificate
|
|
107
|
+
inspec compliance login -k --user USER --token API_TOKEN https://AUTOMATE_FQDN
|
|
108
|
+
export HAB_STUDIO_SECRET_COMPLIANCE_CREDS=$(cat ~/.inspec/compliance/config.json)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Sending InSpec Reports to Chef Automate
|
|
112
|
+
|
|
113
|
+
After running your Habitat package as a service you can configure it to report
|
|
114
|
+
to Chef Automate via a
|
|
115
|
+
[configuration update](https://www.habitat.sh/docs/using-habitat/#config-updates).
|
|
116
|
+
|
|
117
|
+
For example, create a TOML file (config.toml) that matches the below:
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
[automate]
|
|
121
|
+
url = 'https://chef-automate.test'
|
|
122
|
+
token = 'TOKEN'
|
|
123
|
+
user = 'admin'
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Then apply it like so:
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
# The '1' here is the config version (increment this with each change)
|
|
130
|
+
hab config apply inspec-profile-PROFILE_NAME.default 1 /path/to/config.toml
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
This will apply the configuration to all services in the service group. For
|
|
134
|
+
more info on service groups see the
|
|
135
|
+
[Habitat docs](https://www.habitat.sh/docs/using-habitat/#service-groups)
|
|
136
|
+
|
|
137
|
+
## Testing
|
|
138
|
+
|
|
139
|
+
Lint, unit, and functional tests are ran from the root of the InSpec source:
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
bundle exec rake test
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
To execute the integration tests (Test Kitchen + Vagrant + VirtualBox) run the
|
|
146
|
+
following from the directory containing this README.md:
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
bundle exec kitchen test
|
|
150
|
+
```
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
driver:
|
|
3
|
+
name: vagrant
|
|
4
|
+
|
|
5
|
+
provisioner:
|
|
6
|
+
name: chef_solo
|
|
7
|
+
sudo: true
|
|
8
|
+
|
|
9
|
+
verifier:
|
|
10
|
+
name: inspec
|
|
11
|
+
|
|
12
|
+
platforms:
|
|
13
|
+
- name: ubuntu-18.04
|
|
14
|
+
|
|
15
|
+
lifecycle:
|
|
16
|
+
# Build the InSpec gem so it is available to install during `kitchen converge`
|
|
17
|
+
pre_create:
|
|
18
|
+
- cd ../../../ && gem build inspec.gemspec
|
|
19
|
+
- mv ../../../inspec-*.gem test/cookbooks/inspec_habitat_fixture/files/inspec-local.gem
|
|
20
|
+
post_converge:
|
|
21
|
+
- local: sleep 10 # Wait for Habitat to load/run hab service before `verify`
|
|
22
|
+
|
|
23
|
+
suites:
|
|
24
|
+
- name: default
|
|
25
|
+
run_list:
|
|
26
|
+
- recipe[inspec_habitat_fixture]
|
|
27
|
+
attributes:
|
|
28
|
+
|
|
@@ -10,21 +10,21 @@ module InspecPlugins
|
|
|
10
10
|
"#{basename} habitat profile #{command.usage}"
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
desc 'create PATH', 'Create a
|
|
13
|
+
desc 'create PATH', 'Create a Habitat artifact for the profile found at PATH'
|
|
14
14
|
option :output_dir, type: :string, required: false,
|
|
15
|
-
desc: '
|
|
16
|
-
def create(path)
|
|
17
|
-
InspecPlugins::Habitat::Profile.
|
|
15
|
+
desc: 'Output directory for the Habitat artifact. Default: current directory'
|
|
16
|
+
def create(path = '.')
|
|
17
|
+
InspecPlugins::Habitat::Profile.new(path, options).create
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
desc 'setup PATH', 'Configure the profile at PATH for Habitat, including a plan and hooks'
|
|
21
|
-
def setup(path)
|
|
22
|
-
InspecPlugins::Habitat::Profile.
|
|
21
|
+
def setup(path = '.')
|
|
22
|
+
InspecPlugins::Habitat::Profile.new(path, options).setup
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
desc 'upload PATH', 'Create a
|
|
26
|
-
def upload(path)
|
|
27
|
-
InspecPlugins::Habitat::Profile.
|
|
25
|
+
desc 'upload PATH', 'Create then upload a Habitat artifact for the profile found at PATH to the Habitat Builder Depot'
|
|
26
|
+
def upload(path = '.')
|
|
27
|
+
InspecPlugins::Habitat::Profile.new(path, options).upload
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
|
|
@@ -1,238 +1,226 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
-
# author: Adam Leff
|
|
3
2
|
|
|
4
3
|
require 'inspec/profile_vendor'
|
|
5
4
|
require 'mixlib/shellout'
|
|
6
5
|
require 'tomlrb'
|
|
6
|
+
require 'ostruct'
|
|
7
7
|
|
|
8
8
|
module InspecPlugins
|
|
9
9
|
module Habitat
|
|
10
10
|
class Profile
|
|
11
|
-
attr_reader :
|
|
12
|
-
|
|
13
|
-
def self.create(path, options = {})
|
|
14
|
-
creator = new(path, options)
|
|
15
|
-
hart_file = creator.create
|
|
16
|
-
creator.copy(hart_file)
|
|
17
|
-
ensure
|
|
18
|
-
creator.delete_work_dir
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def self.setup(path)
|
|
22
|
-
new(path).setup
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def self.upload(path, options = {})
|
|
26
|
-
uploader = new(path, options)
|
|
27
|
-
uploader.upload
|
|
28
|
-
ensure
|
|
29
|
-
uploader.delete_work_dir
|
|
30
|
-
end
|
|
31
|
-
|
|
11
|
+
attr_reader :logger
|
|
32
12
|
def initialize(path, options = {})
|
|
33
13
|
@path = path
|
|
34
14
|
@options = options
|
|
35
|
-
@
|
|
36
|
-
|
|
37
|
-
log_level = options.fetch('log_level', 'info')
|
|
38
|
-
@log = Inspec::Log
|
|
39
|
-
@log.level(log_level.to_sym)
|
|
15
|
+
@logger = Inspec::Log
|
|
16
|
+
logger.level(options.fetch(:log_level, 'info').to_sym)
|
|
40
17
|
end
|
|
41
18
|
|
|
42
19
|
def create
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
20
|
+
logger.info("Creating a Habitat artifact for '#{@path}'...")
|
|
21
|
+
|
|
22
|
+
# Need to create working directory first so `ensure` doesn't error
|
|
23
|
+
working_dir = create_working_dir
|
|
24
|
+
|
|
25
|
+
habitat_config = read_habitat_config
|
|
26
|
+
verify_habitat_setup(habitat_config)
|
|
27
|
+
|
|
28
|
+
output_dir = @options[:output_dir] || Dir.pwd
|
|
29
|
+
unless File.directory?(output_dir)
|
|
30
|
+
exit_with_error("Output directory #{output_dir} is not a directory " \
|
|
31
|
+
'or does not exist.')
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
duplicated_profile = duplicate_profile(@path, working_dir)
|
|
35
|
+
prepare_profile!(duplicated_profile)
|
|
36
|
+
|
|
37
|
+
hart_file = build_hart(working_dir, habitat_config)
|
|
38
|
+
|
|
39
|
+
logger.debug("Copying artifact to #{output_dir}...")
|
|
40
|
+
destination = File.join(output_dir, File.basename(hart_file))
|
|
41
|
+
FileUtils.cp(hart_file, destination)
|
|
42
|
+
|
|
43
|
+
logger.info("Habitat artifact '#{@destination}' created.")
|
|
44
|
+
destination
|
|
58
45
|
rescue => e
|
|
59
|
-
|
|
60
|
-
exit_with_error(
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
46
|
+
logger.debug(e.backtrace.join("\n"))
|
|
47
|
+
exit_with_error('Unable to create Habitat artifact.')
|
|
48
|
+
ensure
|
|
49
|
+
if Dir.exist?(working_dir)
|
|
50
|
+
logger.debug("Deleting working directory #{working_dir}")
|
|
51
|
+
FileUtils.rm_rf(working_dir)
|
|
52
|
+
end
|
|
64
53
|
end
|
|
65
54
|
|
|
66
|
-
def
|
|
67
|
-
|
|
55
|
+
def setup(profile = profile_from_path(@path))
|
|
56
|
+
path = profile.root_path
|
|
57
|
+
logger.debug("Setting up #{path} for Habitat...")
|
|
58
|
+
|
|
59
|
+
plan_file = File.join(path, 'habitat', 'plan.sh')
|
|
60
|
+
logger.info("Generating Habitat plan at #{plan_file}...")
|
|
61
|
+
vars = {
|
|
62
|
+
profile: profile,
|
|
63
|
+
habitat_origin: read_habitat_config['origin'],
|
|
64
|
+
}
|
|
65
|
+
create_file_from_template(plan_file, 'plan.sh.erb', vars)
|
|
68
66
|
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
run_hook_file = File.join(path, 'habitat', 'hooks', 'run')
|
|
68
|
+
logger.info("Generating a Habitat run hook at #{run_hook_file}...")
|
|
69
|
+
create_file_from_template(run_hook_file, 'hooks/run.erb')
|
|
70
|
+
|
|
71
|
+
default_toml = File.join(path, 'habitat', 'default.toml')
|
|
72
|
+
logger.info("Generating a Habitat default.toml at #{default_toml}...")
|
|
73
|
+
create_file_from_template(default_toml, 'default.toml.erb')
|
|
74
|
+
|
|
75
|
+
config = File.join(path, 'habitat', 'config', 'inspec_exec_config.json')
|
|
76
|
+
logger.info("Generating #{config} for `inspec exec`...")
|
|
77
|
+
create_file_from_template(config, 'config/inspec_exec_config.json.erb')
|
|
71
78
|
end
|
|
72
79
|
|
|
73
80
|
def upload
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
81
|
+
habitat_config = read_habitat_config
|
|
82
|
+
|
|
83
|
+
if habitat_config['auth_token'].nil?
|
|
84
|
+
exit_with_error(
|
|
85
|
+
'Unable to determine Habitat auth token for uploading.',
|
|
86
|
+
'Run `hab setup` or set the HAB_AUTH_TOKEN environment variable.',
|
|
87
|
+
)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Run create command to create habitat artifact
|
|
91
|
+
hart = create
|
|
92
|
+
|
|
93
|
+
logger.info("Uploading Habitat artifact #{hart}...")
|
|
94
|
+
upload_hart(hart, habitat_config)
|
|
95
|
+
logger.info("Habitat artifact #{hart} uploaded.")
|
|
77
96
|
rescue => e
|
|
78
|
-
|
|
79
|
-
exit_with_error(
|
|
80
|
-
'Unable to upload Habitat artifact.',
|
|
81
|
-
"#{e.class} -- #{e.message}",
|
|
82
|
-
)
|
|
97
|
+
logger.debug(e.backtrace.join("\n"))
|
|
98
|
+
exit_with_error('Unable to upload Habitat artifact.')
|
|
83
99
|
end
|
|
84
100
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
101
|
+
private
|
|
102
|
+
|
|
103
|
+
def create_working_dir
|
|
104
|
+
working_dir = Dir.mktmpdir
|
|
105
|
+
logger.debug("Generated working directory #{working_dir}")
|
|
106
|
+
working_dir
|
|
88
107
|
end
|
|
89
108
|
|
|
90
|
-
def
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
vendor_profile_dependencies
|
|
95
|
-
create_habitat_directories(path)
|
|
96
|
-
create_plan(path)
|
|
97
|
-
create_run_hook(path)
|
|
98
|
-
create_default_config(path)
|
|
109
|
+
def duplicate_profile(path, working_dir)
|
|
110
|
+
profile = profile_from_path(path)
|
|
111
|
+
copy_profile_to_working_dir(profile, working_dir)
|
|
112
|
+
profile_from_path(working_dir)
|
|
99
113
|
end
|
|
100
114
|
|
|
101
|
-
|
|
115
|
+
def prepare_profile!(profile)
|
|
116
|
+
vendored_profile = vendor_profile_dependencies!(profile)
|
|
117
|
+
verify_profile(vendored_profile)
|
|
118
|
+
setup(vendored_profile)
|
|
119
|
+
end
|
|
102
120
|
|
|
103
|
-
def
|
|
104
|
-
|
|
121
|
+
def profile_from_path(path)
|
|
122
|
+
Inspec::Profile.for_target(
|
|
105
123
|
path,
|
|
106
124
|
backend: Inspec::Backend.create(Inspec::Config.mock),
|
|
107
125
|
)
|
|
108
126
|
end
|
|
109
127
|
|
|
110
|
-
def
|
|
111
|
-
|
|
128
|
+
def copy_profile_to_working_dir(profile, working_dir)
|
|
129
|
+
logger.debug('Copying profile contents to the working directory...')
|
|
130
|
+
profile.files.each do |profile_file|
|
|
131
|
+
next if File.extname(profile_file) == '.hart'
|
|
132
|
+
|
|
133
|
+
src = File.join(profile.root_path, profile_file)
|
|
134
|
+
dst = File.join(working_dir, profile_file)
|
|
135
|
+
if File.directory?(profile_file)
|
|
136
|
+
logger.debug("Creating directory #{dst}")
|
|
137
|
+
FileUtils.mkdir_p(dst)
|
|
138
|
+
else
|
|
139
|
+
logger.debug("Copying file #{src} to #{dst}")
|
|
140
|
+
FileUtils.cp_r(src, dst)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def verify_profile(profile)
|
|
146
|
+
logger.debug('Checking to see if the profile is valid...')
|
|
112
147
|
|
|
113
148
|
unless profile.check[:summary][:valid]
|
|
114
|
-
exit_with_error('Profile check failed. Please fix the profile
|
|
149
|
+
exit_with_error('Profile check failed. Please fix the profile ' \
|
|
150
|
+
'before creating a Habitat artifact.')
|
|
115
151
|
end
|
|
116
152
|
|
|
117
|
-
|
|
153
|
+
logger.debug('Profile is valid.')
|
|
118
154
|
end
|
|
119
155
|
|
|
120
|
-
def vendor_profile_dependencies
|
|
121
|
-
profile_vendor = Inspec::ProfileVendor.new(
|
|
156
|
+
def vendor_profile_dependencies!(profile)
|
|
157
|
+
profile_vendor = Inspec::ProfileVendor.new(profile.root_path)
|
|
122
158
|
if profile_vendor.lockfile.exist? && profile_vendor.cache_path.exist?
|
|
123
|
-
|
|
159
|
+
logger.debug("Profile's dependencies are already vendored, skipping " \
|
|
160
|
+
'vendor process.')
|
|
124
161
|
else
|
|
125
|
-
|
|
162
|
+
logger.debug("Vendoring the profile's dependencies...")
|
|
126
163
|
profile_vendor.vendor!
|
|
127
164
|
|
|
128
|
-
|
|
165
|
+
logger.debug('Ensuring all vendored content has read permissions...')
|
|
129
166
|
profile_vendor.make_readable
|
|
130
|
-
|
|
131
|
-
# refresh the profile object since the profile now has new files
|
|
132
|
-
create_profile_object
|
|
133
167
|
end
|
|
168
|
+
|
|
169
|
+
# Return new profile since it has changed
|
|
170
|
+
Inspec::Profile.for_target(
|
|
171
|
+
profile.root_path,
|
|
172
|
+
backend: Inspec::Backend.create(Inspec::Config.mock),
|
|
173
|
+
)
|
|
134
174
|
end
|
|
135
175
|
|
|
136
|
-
def
|
|
137
|
-
|
|
176
|
+
def verify_habitat_setup(habitat_config)
|
|
177
|
+
logger.debug('Checking to see if Habitat is installed...')
|
|
138
178
|
cmd = Mixlib::ShellOut.new('hab --version')
|
|
139
179
|
cmd.run_command
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
def validate_habitat_origin
|
|
144
|
-
exit_with_error(
|
|
145
|
-
'Unable to determine Habitat origin name.',
|
|
146
|
-
'Run `hab setup` or set the HAB_ORIGIN environment variable.',
|
|
147
|
-
) if habitat_origin.nil?
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
def validate_habitat_auth_token
|
|
151
|
-
exit_with_error(
|
|
152
|
-
'Unable to determine Habitat auth token for publishing.',
|
|
153
|
-
'Run `hab setup` or set the HAB_AUTH_TOKEN environment variable.',
|
|
154
|
-
) if habitat_auth_token.nil?
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
def validate_output_dir
|
|
158
|
-
exit_with_error("Output directory #{output_dir} is not a directory or does not exist.") unless
|
|
159
|
-
File.directory?(output_dir)
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
def work_dir
|
|
163
|
-
return @work_dir if @work_dir
|
|
164
|
-
|
|
165
|
-
@work_dir ||= Dir.mktmpdir('inspec-habitat-exporter')
|
|
166
|
-
@log.debug("Generated work directory #{@work_dir}")
|
|
167
|
-
|
|
168
|
-
@work_dir
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
def create_habitat_directories(parent_directory)
|
|
172
|
-
[
|
|
173
|
-
File.join(parent_directory, 'habitat'),
|
|
174
|
-
File.join(parent_directory, 'habitat', 'hooks'),
|
|
175
|
-
].each do |dir|
|
|
176
|
-
Dir.mkdir(dir) unless Dir.exist?(dir)
|
|
180
|
+
if cmd.error?
|
|
181
|
+
exit_with_error('Unable to run Habitat commands.', cmd.stderr)
|
|
177
182
|
end
|
|
178
|
-
end
|
|
179
183
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
if File.directory?(f)
|
|
186
|
-
@log.debug("Creating directory #{dst}")
|
|
187
|
-
FileUtils.mkdir_p(dst)
|
|
188
|
-
else
|
|
189
|
-
@log.debug("Copying file #{src} to #{dst}")
|
|
190
|
-
FileUtils.cp_r(src, dst)
|
|
191
|
-
end
|
|
184
|
+
if habitat_config['origin'].nil?
|
|
185
|
+
exit_with_error(
|
|
186
|
+
'Unable to determine Habitat origin name.',
|
|
187
|
+
'Run `hab setup` or set the HAB_ORIGIN environment variable.',
|
|
188
|
+
)
|
|
192
189
|
end
|
|
193
190
|
end
|
|
194
191
|
|
|
195
|
-
def
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
File.
|
|
192
|
+
def create_file_from_template(file, template, vars = {})
|
|
193
|
+
FileUtils.mkdir_p(File.dirname(file))
|
|
194
|
+
template_path = File.join(__dir__, '../../templates/habitat', template)
|
|
195
|
+
contents = ERB.new(File.read(template_path))
|
|
196
|
+
.result(OpenStruct.new(vars).instance_eval { binding })
|
|
197
|
+
File.write(file, contents)
|
|
199
198
|
end
|
|
200
199
|
|
|
201
|
-
def
|
|
202
|
-
|
|
203
|
-
@log.info("Generating a Habitat run hook at #{run_hook_file}...")
|
|
204
|
-
File.write(run_hook_file, run_hook_contents)
|
|
205
|
-
end
|
|
206
|
-
|
|
207
|
-
def create_default_config(directory)
|
|
208
|
-
default_toml = File.join(directory, 'habitat', 'default.toml')
|
|
209
|
-
@log.info("Generating Habitat's default.toml configuration...")
|
|
210
|
-
File.write(default_toml, 'sleep_time = 300')
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
def build_hart
|
|
214
|
-
@log.info('Building our Habitat artifact...')
|
|
200
|
+
def build_hart(working_dir, habitat_config)
|
|
201
|
+
logger.debug('Building our Habitat artifact...')
|
|
215
202
|
|
|
216
203
|
env = {
|
|
217
204
|
'TERM' => 'vt100',
|
|
218
|
-
'HAB_ORIGIN' =>
|
|
205
|
+
'HAB_ORIGIN' => habitat_config['origin'],
|
|
219
206
|
'HAB_NONINTERACTIVE' => 'true',
|
|
220
207
|
}
|
|
221
208
|
|
|
222
|
-
env['RUST_LOG'] = 'debug' if
|
|
209
|
+
env['RUST_LOG'] = 'debug' if logger.level == :debug
|
|
223
210
|
|
|
224
211
|
# TODO: Would love to use Mixlib::ShellOut here, but it doesn't
|
|
225
212
|
# seem to preserve the STDIN tty, and docker gets angry.
|
|
226
|
-
Dir.chdir(
|
|
213
|
+
Dir.chdir(working_dir) do
|
|
227
214
|
unless system(env, 'hab pkg build .')
|
|
228
215
|
exit_with_error('Unable to build the Habitat artifact.')
|
|
229
216
|
end
|
|
230
217
|
end
|
|
231
218
|
|
|
232
|
-
hart_files = Dir.glob(File.join(
|
|
219
|
+
hart_files = Dir.glob(File.join(working_dir, 'results', '*.hart'))
|
|
233
220
|
|
|
234
221
|
if hart_files.length > 1
|
|
235
|
-
exit_with_error('More than one Habitat artifact was created which
|
|
222
|
+
exit_with_error('More than one Habitat artifact was created which ' \
|
|
223
|
+
'was not expected.')
|
|
236
224
|
elsif hart_files.empty?
|
|
237
225
|
exit_with_error('No Habitat artifact was created.')
|
|
238
226
|
end
|
|
@@ -240,21 +228,16 @@ module InspecPlugins
|
|
|
240
228
|
hart_files.first
|
|
241
229
|
end
|
|
242
230
|
|
|
243
|
-
def
|
|
244
|
-
|
|
245
|
-
dst = File.join(output_dir, hart_basename)
|
|
246
|
-
FileUtils.cp(working_dir_hart, dst)
|
|
247
|
-
|
|
248
|
-
dst
|
|
249
|
-
end
|
|
231
|
+
def upload_hart(hart_file, habitat_config)
|
|
232
|
+
logger.debug("Uploading '#{hart_file}' to the Habitat Builder Depot...")
|
|
250
233
|
|
|
251
|
-
|
|
252
|
-
@log.info('Uploading the Habitat artifact to our Depot...')
|
|
234
|
+
config = habitat_config
|
|
253
235
|
|
|
254
236
|
env = {
|
|
255
|
-
'
|
|
256
|
-
'HAB_AUTH_TOKEN' => habitat_auth_token,
|
|
237
|
+
'HAB_AUTH_TOKEN' => config['auth_token'],
|
|
257
238
|
'HAB_NONINTERACTIVE' => 'true',
|
|
239
|
+
'HAB_ORIGIN' => config['origin'],
|
|
240
|
+
'TERM' => 'vt100',
|
|
258
241
|
}
|
|
259
242
|
|
|
260
243
|
env['HAB_DEPOT_URL'] = ENV['HAB_DEPOT_URL'] if ENV['HAB_DEPOT_URL']
|
|
@@ -269,124 +252,25 @@ module InspecPlugins
|
|
|
269
252
|
)
|
|
270
253
|
end
|
|
271
254
|
|
|
272
|
-
|
|
273
|
-
end
|
|
274
|
-
|
|
275
|
-
def habitat_origin
|
|
276
|
-
ENV['HAB_ORIGIN'] || habitat_cli_config['origin']
|
|
277
|
-
end
|
|
278
|
-
|
|
279
|
-
def habitat_auth_token
|
|
280
|
-
ENV['HAB_AUTH_TOKEN'] || habitat_cli_config['auth_token']
|
|
281
|
-
end
|
|
282
|
-
|
|
283
|
-
def habitat_cli_config
|
|
284
|
-
return @cli_config if @cli_config
|
|
285
|
-
|
|
286
|
-
config_file = File.join(ENV['HOME'], '.hab', 'etc', 'cli.toml')
|
|
287
|
-
return {} unless File.exist?(config_file)
|
|
288
|
-
|
|
289
|
-
@cli_config = Tomlrb.load_file(config_file)
|
|
255
|
+
logger.debug('Upload complete!')
|
|
290
256
|
end
|
|
291
257
|
|
|
292
|
-
def
|
|
293
|
-
|
|
258
|
+
def read_habitat_config
|
|
259
|
+
cli_toml = File.join(ENV['HOME'], '.hab', 'etc', 'cli.toml')
|
|
260
|
+
cli_toml = '/hab/etc/cli.toml' unless File.exist?(cli_toml)
|
|
261
|
+
cli_config = File.exist?(cli_toml) ? Tomlrb.load_file(cli_toml) : {}
|
|
262
|
+
cli_config['origin'] ||= ENV['HAB_ORIGIN']
|
|
263
|
+
cli_config['auth_token'] ||= ENV['HAB_AUTH_TOKEN']
|
|
264
|
+
cli_config
|
|
294
265
|
end
|
|
295
266
|
|
|
296
267
|
def exit_with_error(*errors)
|
|
297
268
|
errors.each do |error_msg|
|
|
298
|
-
|
|
269
|
+
logger.error(error_msg)
|
|
299
270
|
end
|
|
300
271
|
|
|
301
272
|
exit 1
|
|
302
273
|
end
|
|
303
|
-
|
|
304
|
-
def package_name
|
|
305
|
-
"inspec-profile-#{profile.name}"
|
|
306
|
-
end
|
|
307
|
-
|
|
308
|
-
def plan_contents
|
|
309
|
-
plan = <<~EOL
|
|
310
|
-
pkg_name=#{package_name}
|
|
311
|
-
pkg_version=#{profile.version}
|
|
312
|
-
pkg_origin=#{habitat_origin}
|
|
313
|
-
pkg_deps=(chef/inspec)
|
|
314
|
-
EOL
|
|
315
|
-
|
|
316
|
-
plan += "pkg_license='#{profile.metadata.params[:license]}'\n\n" if profile.metadata.params[:license]
|
|
317
|
-
|
|
318
|
-
plan += <<~EOL
|
|
319
|
-
do_setup_environment() {
|
|
320
|
-
ARCHIVE_PATH="$HAB_CACHE_SRC_PATH/$pkg_dirname/$pkg_name-$pkg_version.tar.gz"
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
do_build() {
|
|
324
|
-
if [ ! -f $PLAN_CONTEXT/../inspec.yml ]; then
|
|
325
|
-
exit_with 'Cannot find inspec.yml. Please build from profile root.' 1
|
|
326
|
-
fi
|
|
327
|
-
|
|
328
|
-
local profile_files=($(ls $PLAN_CONTEXT/../ -I habitat -I results))
|
|
329
|
-
local profile_location="$HAB_CACHE_SRC_PATH/$pkg_dirname/build"
|
|
330
|
-
mkdir -p $profile_location
|
|
331
|
-
|
|
332
|
-
build_line "Copying profile files to $profile_location"
|
|
333
|
-
cp -R ${profile_files[@]} $profile_location
|
|
334
|
-
|
|
335
|
-
build_line "Archiving $ARCHIVE_PATH"
|
|
336
|
-
inspec archive "$HAB_CACHE_SRC_PATH/$pkg_dirname/build" \
|
|
337
|
-
-o $ARCHIVE_PATH \
|
|
338
|
-
--overwrite
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
do_install() {
|
|
342
|
-
mkdir -p $pkg_prefix/profiles
|
|
343
|
-
cp $ARCHIVE_PATH $pkg_prefix/profiles
|
|
344
|
-
}
|
|
345
|
-
EOL
|
|
346
|
-
|
|
347
|
-
plan
|
|
348
|
-
end
|
|
349
|
-
|
|
350
|
-
def run_hook_contents
|
|
351
|
-
<<~EOL
|
|
352
|
-
#!{{pkgPathFor "core/bash"}}/bin/bash
|
|
353
|
-
|
|
354
|
-
# Redirect stderr to stdout
|
|
355
|
-
# This will be captured by Habitat and viewable via `journalctl`
|
|
356
|
-
# NOTE: We might want log to "{{pkg.svc_path}}/logs" and handle rotation
|
|
357
|
-
exec 2>&1
|
|
358
|
-
|
|
359
|
-
# InSpec will try to create a .cache directory in the user's home directory
|
|
360
|
-
# so this needs to be someplace writeable by the hab user
|
|
361
|
-
export HOME={{pkg.svc_var_path}}
|
|
362
|
-
|
|
363
|
-
RESULTS_DIR="{{pkg.svc_var_path}}/inspec_results"
|
|
364
|
-
RESULTS_FILE="${RESULTS_DIR}/{{pkg.name}}.json"
|
|
365
|
-
|
|
366
|
-
# Create a directory for InSpec reporter output
|
|
367
|
-
mkdir -p $(dirname $RESULTS_FILE)
|
|
368
|
-
|
|
369
|
-
while true; do
|
|
370
|
-
echo "Executing InSpec for {{pkg.ident}}"
|
|
371
|
-
inspec exec "{{pkg.path}}/profiles/*" --reporter=json > ${RESULTS_FILE}
|
|
372
|
-
|
|
373
|
-
EXIT_STATUS=$?
|
|
374
|
-
if [ $EXIT_STATUS -eq 0 ]; then
|
|
375
|
-
echo "InSpec run completed successfully."
|
|
376
|
-
elif [ $EXIT_STATUS -eq 100 ]; then
|
|
377
|
-
echo "InSpec run completed successfully, with at least 1 failed test"
|
|
378
|
-
elif [ $EXIT_STATUS -eq 101 ]; then
|
|
379
|
-
echo "InSpec run completed successfully, with skipped tests and no failures"
|
|
380
|
-
else
|
|
381
|
-
echo "InSpec run did not complete successfully. Exited with status: $?"
|
|
382
|
-
fi
|
|
383
|
-
echo "Results located here: ${RESULTS_FILE}"
|
|
384
|
-
|
|
385
|
-
echo "Sleeping for {{cfg.sleep_time}} seconds"
|
|
386
|
-
sleep {{cfg.sleep_time}}
|
|
387
|
-
done
|
|
388
|
-
EOL
|
|
389
|
-
end
|
|
390
274
|
end
|
|
391
275
|
end
|
|
392
276
|
end
|