inspec 2.2.102 → 2.2.112
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/.rubocop.yml +1 -0
- data/CHANGELOG.md +25 -7
- data/Rakefile +8 -2
- data/docs/profiles.md +9 -0
- data/docs/resources/aws_security_group.md.erb +19 -2
- data/docs/resources/gem.md.erb +24 -5
- data/docs/resources/mssql_session.md.erb +8 -0
- data/lib/inspec/plugin/v2/loader.rb +33 -7
- data/lib/inspec/reporters/json_automate.rb +1 -1
- data/lib/inspec/version.rb +1 -1
- data/lib/plugins/README.md +16 -0
- data/lib/plugins/inspec-artifact/lib/inspec-artifact.rb +12 -0
- data/lib/plugins/inspec-artifact/lib/inspec-artifact/base.rb +162 -0
- data/lib/plugins/inspec-artifact/lib/inspec-artifact/cli.rb +114 -0
- data/lib/plugins/inspec-artifact/test/functional/inspec_artifact_test.rb +46 -0
- data/lib/plugins/inspec-habitat/lib/inspec-habitat.rb +11 -0
- data/lib/plugins/inspec-habitat/lib/inspec-habitat/cli.rb +39 -0
- data/lib/plugins/inspec-habitat/lib/inspec-habitat/profile.rb +394 -0
- data/lib/plugins/inspec-habitat/test/unit/profile_test.rb +184 -0
- data/lib/{bundles → plugins}/inspec-init/README.md +0 -0
- data/lib/plugins/inspec-init/lib/inspec-init.rb +12 -0
- data/lib/plugins/inspec-init/lib/inspec-init/cli.rb +28 -0
- data/lib/plugins/inspec-init/lib/inspec-init/renderer.rb +81 -0
- data/lib/{bundles → plugins/inspec-init/lib}/inspec-init/templates/profile/README.md +0 -0
- data/lib/{bundles → plugins/inspec-init/lib}/inspec-init/templates/profile/controls/example.rb +0 -0
- data/lib/{bundles → plugins/inspec-init/lib}/inspec-init/templates/profile/inspec.yml +0 -0
- data/lib/{bundles → plugins/inspec-init/lib}/inspec-init/templates/profile/libraries/.gitkeep +0 -0
- data/lib/plugins/inspec-init/test/functional/inspec_init_test.rb +30 -0
- data/lib/plugins/shared/core_plugin_test_helper.rb +50 -0
- data/lib/resources/aws/aws_security_group.rb +38 -6
- data/lib/resources/gem.rb +7 -1
- data/lib/resources/mssql_session.rb +4 -2
- metadata +21 -17
- data/lib/bundles/inspec-artifact.rb +0 -7
- data/lib/bundles/inspec-artifact/README.md +0 -1
- data/lib/bundles/inspec-artifact/cli.rb +0 -278
- data/lib/bundles/inspec-habitat.rb +0 -12
- data/lib/bundles/inspec-habitat/cli.rb +0 -37
- data/lib/bundles/inspec-habitat/log.rb +0 -10
- data/lib/bundles/inspec-habitat/profile.rb +0 -391
- data/lib/bundles/inspec-init.rb +0 -12
- data/lib/bundles/inspec-init/cli.rb +0 -39
- data/lib/bundles/inspec-init/renderer.rb +0 -79
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed479c2bc17fad9ab4aefa69f119d6448332b4e2f5befac16f427fa589a8cef8
|
4
|
+
data.tar.gz: 6e055c297017f08684d15780060e2a9bf528f1f1579e0f8224a35202aad73c66
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b3be7a2eb3219f1ceabad6ce163ae24f644475a67a3825f9163c7a572be3a54db5dad11dc5765d28f5330fa5fea5ce7b535e887e56aa86749dcf3c6453c8b9e2
|
7
|
+
data.tar.gz: bab90ce890a5973fc24d8d02be94c88673553a0164dd0d6f5675247223244d232fd6f6a253ff0d3141549fb0f5f4857bdd984ab60ab03d2a5620f5325927f818
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,20 +1,39 @@
|
|
1
1
|
# Change Log
|
2
2
|
<!-- usage documentation: http://expeditor-docs.es.chef.io/configuration/changelog/ -->
|
3
|
-
<!-- latest_release 2.2.
|
4
|
-
## [v2.2.
|
3
|
+
<!-- latest_release 2.2.112 -->
|
4
|
+
## [v2.2.112](https://github.com/inspec/inspec/tree/v2.2.112) (2018-09-19)
|
5
5
|
|
6
6
|
#### Merged Pull Requests
|
7
|
-
-
|
7
|
+
- Move artifact to v2 plugin [#3406](https://github.com/inspec/inspec/pull/3406) ([jquick](https://github.com/jquick))
|
8
8
|
<!-- latest_release -->
|
9
9
|
|
10
|
-
<!-- release_rollup since=2.2.
|
11
|
-
### Changes since 2.2.
|
10
|
+
<!-- release_rollup since=2.2.102 -->
|
11
|
+
### Changes since 2.2.102 release
|
12
|
+
|
13
|
+
#### Enhancements
|
14
|
+
- adding `versions` to the `gem` resource [#3398](https://github.com/inspec/inspec/pull/3398) ([majormoses](https://github.com/majormoses)) <!-- 2.2.107 -->
|
15
|
+
- Plugins: Add support for 'bundles' migration [#3384](https://github.com/inspec/inspec/pull/3384) ([clintoncwolfe](https://github.com/clintoncwolfe)) <!-- 2.2.105 -->
|
16
|
+
|
17
|
+
#### New Features
|
18
|
+
- Update AWS Security Group to work with IPV6 rules. [#3394](https://github.com/inspec/inspec/pull/3394) ([MartinLogan](https://github.com/MartinLogan)) <!-- 2.2.111 -->
|
19
|
+
- Added db_name flag [#3383](https://github.com/inspec/inspec/pull/3383) ([kdoores](https://github.com/kdoores)) <!-- 2.2.104 -->
|
12
20
|
|
13
21
|
#### Merged Pull Requests
|
14
|
-
-
|
22
|
+
- Move artifact to v2 plugin [#3406](https://github.com/inspec/inspec/pull/3406) ([jquick](https://github.com/jquick)) <!-- 2.2.112 -->
|
23
|
+
- Move inspec init to v2 plugins [#3407](https://github.com/inspec/inspec/pull/3407) ([jquick](https://github.com/jquick)) <!-- 2.2.110 -->
|
24
|
+
- Fix gem tests from recent merge [#3409](https://github.com/inspec/inspec/pull/3409) ([jquick](https://github.com/jquick)) <!-- 2.2.109 -->
|
25
|
+
- Fix json automate tests and render call [#3408](https://github.com/inspec/inspec/pull/3408) ([jquick](https://github.com/jquick)) <!-- 2.2.108 -->
|
26
|
+
- Move habitat to v2 plugin [#3404](https://github.com/inspec/inspec/pull/3404) ([jquick](https://github.com/jquick)) <!-- 2.2.106 -->
|
27
|
+
- Fix rendering of profiles docs [#3393](https://github.com/inspec/inspec/pull/3393) ([jquick](https://github.com/jquick)) <!-- 2.2.103 -->
|
15
28
|
<!-- release_rollup -->
|
16
29
|
|
17
30
|
<!-- latest_stable_release -->
|
31
|
+
## [v2.2.102](https://github.com/inspec/inspec/tree/v2.2.102) (2018-09-17)
|
32
|
+
|
33
|
+
#### Merged Pull Requests
|
34
|
+
- Add json-automate to the report method [#3401](https://github.com/inspec/inspec/pull/3401) ([jquick](https://github.com/jquick))
|
35
|
+
<!-- latest_stable_release -->
|
36
|
+
|
18
37
|
## [v2.2.101](https://github.com/inspec/inspec/tree/v2.2.101) (2018-09-14)
|
19
38
|
|
20
39
|
#### New Features
|
@@ -44,7 +63,6 @@
|
|
44
63
|
- Bump omnibus ruby to 2.5.1 [#3390](https://github.com/inspec/inspec/pull/3390) ([jquick](https://github.com/jquick))
|
45
64
|
- Add platforms schema command [#3346](https://github.com/inspec/inspec/pull/3346) ([jquick](https://github.com/jquick))
|
46
65
|
- Fix profile vendoring on Windows [#3378](https://github.com/inspec/inspec/pull/3378) ([jerryaldrichiii](https://github.com/jerryaldrichiii))
|
47
|
-
<!-- latest_stable_release -->
|
48
66
|
|
49
67
|
## [v2.2.78](https://github.com/inspec/inspec/tree/v2.2.78) (2018-08-30)
|
50
68
|
|
data/Rakefile
CHANGED
@@ -54,7 +54,10 @@ task default: [:lint, :test]
|
|
54
54
|
|
55
55
|
Rake::TestTask.new do |t|
|
56
56
|
t.libs << 'test'
|
57
|
-
t.
|
57
|
+
t.test_files = Dir.glob([
|
58
|
+
'test/unit/**/*_test.rb',
|
59
|
+
'lib/plugins/inspec-*/test/unit/**/*_test.rb',
|
60
|
+
])
|
58
61
|
t.warning = true
|
59
62
|
t.verbose = true
|
60
63
|
t.ruby_opts = ['--dev'] if defined?(JRUBY_VERSION)
|
@@ -69,7 +72,10 @@ namespace :test do
|
|
69
72
|
|
70
73
|
Rake::TestTask.new(:functional) do |t|
|
71
74
|
t.libs << 'test'
|
72
|
-
t.
|
75
|
+
t.test_files = Dir.glob([
|
76
|
+
'test/functional/**/*_test.rb',
|
77
|
+
'lib/plugins/inspec-*/test/functional/**/*_test.rb',
|
78
|
+
])
|
73
79
|
t.warning = true
|
74
80
|
t.verbose = true
|
75
81
|
t.ruby_opts = ['--dev'] if defined?(JRUBY_VERSION)
|
data/docs/profiles.md
CHANGED
@@ -348,6 +348,7 @@ Attributes may contain the following options:
|
|
348
348
|
|
349
349
|
|
350
350
|
You can specify attributes in your `inspec.yml` using the `attributes` setting. For example, to add a `user` attribute for your profile:
|
351
|
+
|
351
352
|
```YAML
|
352
353
|
attributes:
|
353
354
|
- name: user
|
@@ -356,6 +357,7 @@ attributes:
|
|
356
357
|
```
|
357
358
|
|
358
359
|
Example of adding a array object of servers:
|
360
|
+
|
359
361
|
```YAML
|
360
362
|
attributes:
|
361
363
|
- name: servers
|
@@ -369,6 +371,7 @@ attributes:
|
|
369
371
|
To access an attribute you will use the `attribute` keyword. You can use this anywhere in your control code.
|
370
372
|
|
371
373
|
For example:
|
374
|
+
|
372
375
|
```Ruby
|
373
376
|
current_user = attribute('user')
|
374
377
|
|
@@ -386,6 +389,7 @@ end
|
|
386
389
|
For sensitive data it is recomended to use a secrets YAML file located on the local machine to populate the values of attributes. A secrets file will always overwrite a attributes default value. To use the secrets file run `inspec exec` and specify the path to that Yaml file using the `--attrs` attribute.
|
387
390
|
|
388
391
|
For example, a inspec.yml:
|
392
|
+
|
389
393
|
```YAML
|
390
394
|
attributes:
|
391
395
|
- name: username
|
@@ -432,6 +436,7 @@ $ inspec exec examples/profile-attribute --attrs examples/profile-attribute.yml
|
|
432
436
|
To change your attributes for platform specific cases you can setup multiple `--attrs` files.
|
433
437
|
|
434
438
|
For example, a inspec.yml:
|
439
|
+
|
435
440
|
```YAML
|
436
441
|
attributes:
|
437
442
|
- name: users
|
@@ -440,6 +445,7 @@ attributes:
|
|
440
445
|
```
|
441
446
|
|
442
447
|
A YAML file named `windows.yml`
|
448
|
+
|
443
449
|
```YAML
|
444
450
|
users:
|
445
451
|
- Administrator
|
@@ -448,6 +454,7 @@ users:
|
|
448
454
|
```
|
449
455
|
|
450
456
|
A YAML file named `linux.yml`
|
457
|
+
|
451
458
|
```YAML
|
452
459
|
users:
|
453
460
|
- root
|
@@ -456,6 +463,7 @@ users:
|
|
456
463
|
```
|
457
464
|
|
458
465
|
The control file:
|
466
|
+
|
459
467
|
```RUBY
|
460
468
|
control 'system-users' do
|
461
469
|
impact 0.8
|
@@ -468,6 +476,7 @@ end
|
|
468
476
|
```
|
469
477
|
|
470
478
|
The following command runs the tests and applies the attributes specified:
|
479
|
+
|
471
480
|
```bash
|
472
481
|
$ inspec exec examples/profile-attribute --attrs examples/windows.yml
|
473
482
|
$ inspec exec examples/profile-attribute --attrs examples/linux.yml
|
@@ -12,7 +12,6 @@ SGs are a networking construct which contain ingress and egress rules for networ
|
|
12
12
|
|
13
13
|
While this resource provides facilities for searching inbound and outbound rules on a variety of criteria, there is currently no support for performing matches based on:
|
14
14
|
|
15
|
-
* IPv6 ranges
|
16
15
|
* References to other Security Groups
|
17
16
|
* References to VPC peers or other AWS services (that is, no support for searches based on 'prefix lists').
|
18
17
|
|
@@ -143,7 +142,7 @@ A string identifying the VPC that contains the Security Group. Since VPCs common
|
|
143
142
|
<br>
|
144
143
|
## Properties
|
145
144
|
|
146
|
-
* [`description`](#description), [`group_id`](#group_id), [`group_name`](#group_name), [`inbound_rules`](#inbound_rules), [`outbound_rules`](#outbound_rules), [`vpc_id`](#vpc_id)
|
145
|
+
* [`description`](#description), [`group_id`](#group_id), [`group_name`](#group_name), [`inbound_rules`](#inbound_rules), [`inbound_rules_count`](#inbound_rules_count), [`outbound_rules`](#outbound_rules), [`outbound_rules_count`](#outbound_rules_count), [`vpc_id`](#vpc_id)
|
147
146
|
|
148
147
|
<br>
|
149
148
|
|
@@ -191,6 +190,14 @@ If the Security Group could not be found (that is, `exists` is false), `inbound_
|
|
191
190
|
its('inbound_rules.first') { should include(from_port: '22', ip_ranges: ['10.2.17.0/24']) }
|
192
191
|
end
|
193
192
|
|
193
|
+
### inbound\_rules\_count
|
194
|
+
|
195
|
+
A Number totalling the number of individual rules defined - It is a sum of the combinations of port, protocol, ipv4 rules, ipv6 rules and security group rules.
|
196
|
+
|
197
|
+
describe aws_security_group(group_name: linux_servers) do
|
198
|
+
its('inbound_rules_count'){ should eq 10 }
|
199
|
+
end
|
200
|
+
|
194
201
|
### outbound\_rules
|
195
202
|
|
196
203
|
A list of the rules that the Security Group applies to outgoing network traffic initiated by the AWS resource in the Security Group. This is a low-level property that is used by the [`allow_out`](#allow_out) matcher; see it for detailed examples. `outbound_rules` is provided here for those wishing to use Ruby code to inspect the rules directly, instead of using higher-level matchers.
|
@@ -203,6 +210,14 @@ If the Security Group could not be found (that is, `exists` is false), `outbound
|
|
203
210
|
its('outbound_rules.last') { should_not include(ip_ranges:['0.0.0.0/0']) }
|
204
211
|
end
|
205
212
|
|
213
|
+
### outbound\_rules\_count
|
214
|
+
|
215
|
+
A Number totalling the number of individual rules defined - It is a sum of the combinations of port, protocol, ipv4 rules, ipv6 rules and security group rules.
|
216
|
+
|
217
|
+
describe aws_security_group(group_name: linux_servers) do
|
218
|
+
its('outbound_rules_count'){ should eq 2 }
|
219
|
+
end
|
220
|
+
|
206
221
|
### vpc\_id
|
207
222
|
|
208
223
|
A String in the format 'vpc-' followed by 8 hexadecimal characters reflecting VPC that contains the Security Group.
|
@@ -240,6 +255,7 @@ The matchers accept a key-value list of search criteria. For a rule to match, i
|
|
240
255
|
|
241
256
|
* from_port - Determines if a rule exists whose port range begins at the specified number. The word 'from_' does *not* relate to inbound/outbound directionality; it relates to the port range ("counting _from_"). `from_port` is an exact criterion; so if the rule allows 1000-2000 and you specify a `from_port` of 1001, it does not match.
|
242
257
|
* ipv4_range - Specifies an IPv4 address or subnet as a CIDR, or a list of them, to be checked as a permissible origin (for `allow_in`) or destination (for `allow_out`) for traffic. Each AWS Security Group rule may have multiple allowed source IP ranges.
|
258
|
+
* ipv6_range - Specifies an IPv6 address or subnet as a CIDR, or a list of them, to be checked as a permissible origin (for `allow_in`) or destination (for `allow_out`) for traffic. Each AWS Security Group rule may have multiple allowed source IP ranges.
|
243
259
|
* port - Determines if a particular TCP/IP port is reachable. allow_in and allow_out examine whether the specified port is included in the port range of a rule, while allow_in. You may specify the port as a string (`'22'`) or as a number.
|
244
260
|
* position - A one-based index into the list of rules. If provided, this restricts the evaluation to the rule at that position. You may also use the special values `:first` and `:last`. `position` may also be used to enable `allow_in_only` and `allow_out_only` to work with multi-rule Security Groups.
|
245
261
|
* protocol - Specifies the IP protocol. 'tcp', 'udp', and 'icmp' are some typical values. The string "-1" or 'any' is used to indicate any protocol.
|
@@ -248,6 +264,7 @@ The matchers accept a key-value list of search criteria. For a rule to match, i
|
|
248
264
|
describe aws_security_group(group_name: 'mixed-functionality-group') do
|
249
265
|
# Allow RDP from defined range
|
250
266
|
it { should allow_in(port: 3389, ipv4_range: '10.5.0.0/16') }
|
267
|
+
it { should allow_in(port: 3389, ipv6_range: '2001:db8::/122') }
|
251
268
|
|
252
269
|
# Allow SSH from two ranges
|
253
270
|
it { should allow_in(port: 22, ipv4_range: ['10.5.0.0/16', '10.2.3.0/24']) }
|
data/docs/resources/gem.md.erb
CHANGED
@@ -46,6 +46,15 @@ The following examples show how to use this InSpec audit resource.
|
|
46
46
|
its('version') { should eq '0.33.0' }
|
47
47
|
end
|
48
48
|
|
49
|
+
### Verify that a particular version is installed when there are multiple versions installed
|
50
|
+
|
51
|
+
describe gem('rubocop') do
|
52
|
+
it { should be_installed }
|
53
|
+
its('versions') { should include /0.51.0/ }
|
54
|
+
its('versions.count') { should_not be > 3 }
|
55
|
+
end
|
56
|
+
|
57
|
+
|
49
58
|
### Verify that a gem package is not installed
|
50
59
|
|
51
60
|
describe gem('rubocop') do
|
@@ -72,6 +81,21 @@ The following examples show how to use this InSpec audit resource.
|
|
72
81
|
|
73
82
|
<br>
|
74
83
|
|
84
|
+
## Properties
|
85
|
+
|
86
|
+
### version (String)
|
87
|
+
|
88
|
+
The `version` property returns a string of the default version on the system:
|
89
|
+
|
90
|
+
its('version') { should eq '0.33.0' }
|
91
|
+
|
92
|
+
### versions
|
93
|
+
|
94
|
+
The `versions` property returns an array of strings of all the versions of the gem installed on the system:
|
95
|
+
|
96
|
+
its('versions') { should include /0.33/ }
|
97
|
+
|
98
|
+
|
75
99
|
## Matchers
|
76
100
|
|
77
101
|
For a full list of available matchers, please visit our [matchers page](https://www.inspec.io/docs/reference/matchers/).
|
@@ -82,8 +106,3 @@ The `be_installed` matcher tests if the named Gem package is installed:
|
|
82
106
|
|
83
107
|
it { should be_installed }
|
84
108
|
|
85
|
-
### version
|
86
|
-
|
87
|
-
The `version` matcher tests if the named package version is on the system:
|
88
|
-
|
89
|
-
its('version') { should eq '0.33.0' }
|
@@ -62,6 +62,14 @@ The following examples show how to use this InSpec audit resource.
|
|
62
62
|
describe sql.query("SELECT SERVERPROPERTY('ProductVersion') as result").row(0).column('result') do
|
63
63
|
its("value") { should cmp > '12.00.4457' }
|
64
64
|
end
|
65
|
+
|
66
|
+
### Test a specific database
|
67
|
+
|
68
|
+
sql = mssql_session(user: 'my_user', password: 'password', db_name: 'test')
|
69
|
+
|
70
|
+
describe sql.query("SELECT Name AS result FROM Product WHERE ProductID == 1").row(0).column('result') do
|
71
|
+
its("value") { should eq 'foo' }
|
72
|
+
end
|
65
73
|
|
66
74
|
<br>
|
67
75
|
|
@@ -17,7 +17,14 @@ module Inspec::Plugin::V2
|
|
17
17
|
determine_plugin_conf_file
|
18
18
|
read_conf_file
|
19
19
|
unpack_conf_file
|
20
|
+
|
21
|
+
# Old-style (v0, v1) co-distributed plugins were called 'bundles'
|
22
|
+
# and were located in lib/bundles
|
20
23
|
detect_bundled_plugins unless options[:omit_bundles]
|
24
|
+
|
25
|
+
# New-style (v2) co-distributed plugins are in lib/plugins,
|
26
|
+
# and may be safely loaded
|
27
|
+
detect_core_plugins unless options[:omit_core_plugins]
|
21
28
|
end
|
22
29
|
|
23
30
|
def load_all
|
@@ -26,17 +33,20 @@ module Inspec::Plugin::V2
|
|
26
33
|
# rubocop: disable Lint/RescueException
|
27
34
|
begin
|
28
35
|
# We could use require, but under testing, we need to repeatedly reload the same
|
29
|
-
# plugin.
|
30
|
-
if plugin_details.
|
31
|
-
|
32
|
-
else
|
36
|
+
# plugin. However, gems only work with require (rubygems dooes not overload `load`)
|
37
|
+
if plugin_details.installation_type == :gem
|
38
|
+
activate_managed_gems_for_plugin(plugin_name)
|
33
39
|
require plugin_details.entry_point
|
40
|
+
else
|
41
|
+
load_path = plugin_details.entry_point
|
42
|
+
load_path += '.rb' unless plugin_details.entry_point.end_with?('.rb')
|
43
|
+
load load_path
|
34
44
|
end
|
35
45
|
plugin_details.loaded = true
|
36
46
|
annotate_status_after_loading(plugin_name)
|
37
47
|
rescue ::Exception => ex
|
38
48
|
plugin_details.load_exception = ex
|
39
|
-
Inspec::Log.error "Could not load plugin #{plugin_name}"
|
49
|
+
Inspec::Log.error "Could not load plugin #{plugin_name}: #{ex.message}"
|
40
50
|
end
|
41
51
|
# rubocop: enable Lint/RescueException
|
42
52
|
end
|
@@ -60,7 +70,7 @@ module Inspec::Plugin::V2
|
|
60
70
|
end
|
61
71
|
|
62
72
|
def activate(plugin_type, hook_name)
|
63
|
-
activator = registry.find_activators(plugin_type: plugin_type,
|
73
|
+
activator = registry.find_activators(plugin_type: plugin_type, activator_name: hook_name).first
|
64
74
|
# We want to capture literally any possible exception here, since we are storing them.
|
65
75
|
# rubocop: disable Lint/RescueException
|
66
76
|
begin
|
@@ -80,7 +90,7 @@ module Inspec::Plugin::V2
|
|
80
90
|
next if act.activated
|
81
91
|
# If there is anything in the CLI args with the same name, activate it
|
82
92
|
# If the word 'help' appears in the first position, load all CLI plugins
|
83
|
-
if cli_args.include?(act.activator_name.to_s) || cli_args[0] == 'help'
|
93
|
+
if cli_args.include?(act.activator_name.to_s) || cli_args[0] == 'help' || cli_args.size.zero?
|
84
94
|
activate(:cli_command, act.activator_name)
|
85
95
|
act.implementation_class.register_with_thor
|
86
96
|
end
|
@@ -138,6 +148,22 @@ module Inspec::Plugin::V2
|
|
138
148
|
@plugin_conf_file_path = File.join(@plugin_conf_file_path, 'plugins.json')
|
139
149
|
end
|
140
150
|
|
151
|
+
def detect_core_plugins
|
152
|
+
core_plugins_dir = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'plugins'))
|
153
|
+
# These are expected to be organized as proper separate projects,
|
154
|
+
# with lib/ dirs, etc.
|
155
|
+
Dir.glob(File.join(core_plugins_dir, 'inspec-*')).each do |plugin_dir|
|
156
|
+
status = Inspec::Plugin::V2::Status.new
|
157
|
+
status.name = File.basename(plugin_dir)
|
158
|
+
status.entry_point = File.join(plugin_dir, 'lib', status.name + '.rb')
|
159
|
+
status.installation_type = :path
|
160
|
+
status.loaded = false
|
161
|
+
registry[status.name.to_sym] = status
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# TODO: DRY up re: Installer read_or_init_config_file
|
166
|
+
# TODO: refactor the plugin.json file to have its own class, which Loader consumes
|
141
167
|
def read_conf_file
|
142
168
|
if File.exist?(@plugin_conf_file_path)
|
143
169
|
@plugin_file_contents = JSON.parse(File.read(@plugin_conf_file_path))
|
data/lib/inspec/version.rb
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
# Core Plugins of InSpec
|
2
|
+
|
3
|
+
This area contains the plugins that ship with InSpec. They are automatically detected by the plugin loader.
|
4
|
+
|
5
|
+
## inspec-* directories
|
6
|
+
|
7
|
+
Each subdirectory here that begins with `inspec-` is intended to be a self-contained plugin project,
|
8
|
+
with code, docs, and tests.
|
9
|
+
|
10
|
+
## shared directory
|
11
|
+
|
12
|
+
This directory contains material that is reusable for core plugins, such as a test helper tuned to assisting
|
13
|
+
core plugin testing.
|
14
|
+
|
15
|
+
|
16
|
+
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'openssl'
|
3
|
+
require 'pathname'
|
4
|
+
require 'set'
|
5
|
+
require 'tempfile'
|
6
|
+
require 'yaml'
|
7
|
+
|
8
|
+
module InspecPlugins
|
9
|
+
module Artifact
|
10
|
+
class Base
|
11
|
+
KEY_BITS=2048
|
12
|
+
KEY_ALG=OpenSSL::PKey::RSA
|
13
|
+
|
14
|
+
INSPEC_PROFILE_VERSION_1='INSPEC-PROFILE-1'.freeze
|
15
|
+
INSPEC_REPORT_VERSION_1='INSPEC-REPORT-1'.freeze
|
16
|
+
|
17
|
+
ARTIFACT_DIGEST=OpenSSL::Digest::SHA512
|
18
|
+
ARTIFACT_DIGEST_NAME='SHA512'.freeze
|
19
|
+
|
20
|
+
VALID_PROFILE_VERSIONS=Set.new [INSPEC_PROFILE_VERSION_1]
|
21
|
+
VALID_PROFILE_DIGESTS=Set.new [ARTIFACT_DIGEST_NAME]
|
22
|
+
|
23
|
+
SIGNED_PROFILE_SUFFIX='iaf'.freeze
|
24
|
+
SIGNED_REPORT_SUFFIX='iar'.freeze
|
25
|
+
|
26
|
+
def self.keygen(options)
|
27
|
+
key = KEY_ALG.new KEY_BITS
|
28
|
+
puts 'Generating private key'
|
29
|
+
open "#{options['keyname']}.pem.key", 'w' do |io| io.write key.to_pem end
|
30
|
+
puts 'Generating public key'
|
31
|
+
open "#{options['keyname']}.pem.pub", 'w' do |io| io.write key.public_key.to_pem end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.profile_sign(options)
|
35
|
+
artifact = new
|
36
|
+
Dir.mktmpdir do |workdir|
|
37
|
+
puts "Signing #{options['profile']} with key #{options['keyname']}"
|
38
|
+
path_to_profile = options['profile']
|
39
|
+
profile_md = artifact.read_profile_metadata(path_to_profile)
|
40
|
+
artifact_filename = "#{profile_md['name']}-#{profile_md['version']}.#{SIGNED_PROFILE_SUFFIX}"
|
41
|
+
tarfile = artifact.profile_compress(path_to_profile, profile_md, workdir)
|
42
|
+
content = IO.binread(tarfile)
|
43
|
+
signing_key = KEY_ALG.new File.read "#{options['keyname']}.pem.key"
|
44
|
+
sha = ARTIFACT_DIGEST.new
|
45
|
+
signature = signing_key.sign sha, content
|
46
|
+
# convert the signature to Base64
|
47
|
+
signature_base64 = Base64.encode64(signature)
|
48
|
+
tar_content = IO.binread(tarfile)
|
49
|
+
File.open(artifact_filename, 'wb') do |f|
|
50
|
+
f.puts(INSPEC_PROFILE_VERSION_1)
|
51
|
+
f.puts(options['keyname'])
|
52
|
+
f.puts(ARTIFACT_DIGEST_NAME)
|
53
|
+
f.puts(signature_base64)
|
54
|
+
f.puts('') # newline separates artifact header with body
|
55
|
+
f.write(tar_content)
|
56
|
+
end
|
57
|
+
puts "Successfully generated #{artifact_filename}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.profile_verify(options)
|
62
|
+
artifact = new
|
63
|
+
file_to_verifiy = options['infile']
|
64
|
+
puts "Verifying #{file_to_verifiy}"
|
65
|
+
artifact.verify(file_to_verifiy) do ||
|
66
|
+
puts 'Artifact is valid'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.profile_install(options)
|
71
|
+
artifact = new
|
72
|
+
puts 'Installing profile'
|
73
|
+
file_to_verifiy = options['infile']
|
74
|
+
dest_dir = options['destdir']
|
75
|
+
artifact.verify(file_to_verifiy) do |content|
|
76
|
+
Dir.mktmpdir do |workdir|
|
77
|
+
tmpfile = Pathname.new(workdir).join('artifact_to_install.tar.gz')
|
78
|
+
File.write(tmpfile, content)
|
79
|
+
puts "Installing to #{dest_dir}"
|
80
|
+
`tar xzf #{tmpfile} -C #{dest_dir}`
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def read_profile_metadata(path_to_profile)
|
86
|
+
begin
|
87
|
+
p = Pathname.new(path_to_profile)
|
88
|
+
p = p.join('inspec.yml')
|
89
|
+
if not p.exist?
|
90
|
+
raise "#{path_to_profile} doesn't appear to be a valid Inspec profile"
|
91
|
+
end
|
92
|
+
yaml = YAML.load_file(p.to_s)
|
93
|
+
yaml = yaml.to_hash
|
94
|
+
|
95
|
+
if not yaml.key? 'name'
|
96
|
+
raise 'Profile is invalid, name is not defined'
|
97
|
+
end
|
98
|
+
|
99
|
+
if not yaml.key? 'version'
|
100
|
+
raise 'Profile is invalid, version is not defined'
|
101
|
+
end
|
102
|
+
rescue => e
|
103
|
+
# rewrap it and pass it up to the CLI
|
104
|
+
raise "Error reading Inspec profile metadata: #{e}"
|
105
|
+
end
|
106
|
+
|
107
|
+
yaml
|
108
|
+
end
|
109
|
+
|
110
|
+
def profile_compress(path_to_profile, profile_md, workdir)
|
111
|
+
profile_name = profile_md['name']
|
112
|
+
profile_version = profile_md['version']
|
113
|
+
outfile_name = "#{workdir}/#{profile_name}-#{profile_version}.tar.gz"
|
114
|
+
`tar czf #{outfile_name} -C #{path_to_profile} .`
|
115
|
+
outfile_name
|
116
|
+
end
|
117
|
+
|
118
|
+
def valid_header?(file_alg, file_version, file_keyname)
|
119
|
+
public_keyfile = "#{file_keyname}.pem.pub"
|
120
|
+
puts "Looking for #{public_keyfile} to verify artifact"
|
121
|
+
if !File.exist? public_keyfile
|
122
|
+
raise "Can't find #{public_keyfile}"
|
123
|
+
end
|
124
|
+
|
125
|
+
raise 'Invalid artifact digest algorithm detected' if !VALID_PROFILE_DIGESTS.member?(file_alg)
|
126
|
+
raise 'Invalid artifact version detected' if !VALID_PROFILE_VERSIONS.member?(file_version)
|
127
|
+
end
|
128
|
+
|
129
|
+
def verify(file_to_verifiy, &content_block)
|
130
|
+
f = File.open(file_to_verifiy, 'r')
|
131
|
+
file_version = f.readline.strip!
|
132
|
+
file_keyname = f.readline.strip!
|
133
|
+
file_alg = f.readline.strip!
|
134
|
+
|
135
|
+
file_sig = ''
|
136
|
+
# the signature is multi-line
|
137
|
+
while (line = f.readline) != "\n"
|
138
|
+
file_sig += line
|
139
|
+
end
|
140
|
+
file_sig.strip!
|
141
|
+
f.close
|
142
|
+
|
143
|
+
valid_header?(file_alg, file_version, file_keyname)
|
144
|
+
|
145
|
+
public_keyfile = "#{file_keyname}.pem.pub"
|
146
|
+
verification_key = KEY_ALG.new File.read public_keyfile
|
147
|
+
|
148
|
+
f = File.open(file_to_verifiy, 'r')
|
149
|
+
while f.readline != "\n" do end
|
150
|
+
content = f.read
|
151
|
+
|
152
|
+
signature = Base64.decode64(file_sig)
|
153
|
+
digest = ARTIFACT_DIGEST.new
|
154
|
+
if verification_key.verify digest, signature, content
|
155
|
+
content_block.yield(content)
|
156
|
+
else
|
157
|
+
puts 'Artifact is invalid'
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|