inspec 1.41.0 → 1.42.3
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/CHANGELOG.md +38 -21
- data/docs/resources/etc_fstab.md.erb +1 -1
- data/docs/resources/os_env.md.erb +3 -9
- data/lib/bundles/inspec-habitat/cli.rb +7 -2
- data/lib/bundles/inspec-habitat/profile.rb +42 -18
- data/lib/bundles/inspec-init/templates/profile/README.md +1 -1
- data/lib/bundles/inspec-init/templates/profile/controls/example.rb +1 -1
- data/lib/inspec/cli.rb +1 -1
- data/lib/inspec/control_eval_context.rb +16 -6
- data/lib/inspec/file_provider.rb +23 -3
- data/lib/inspec/profile_context.rb +2 -0
- data/lib/inspec/rule.rb +4 -0
- data/lib/inspec/shell.rb +4 -4
- data/lib/inspec/version.rb +1 -1
- data/lib/resources/etc_fstab.rb +79 -84
- data/lib/resources/file.rb +81 -10
- data/lib/resources/port.rb +145 -8
- data/lib/resources/postgres.rb +1 -1
- data/lib/resources/windows_hotfix.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6253ad47423d8b2a7bfc56409b61d31c0065aa6e
|
|
4
|
+
data.tar.gz: 7e3e02b74a6a6af95e62c09b62e949bf95eea242
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 85007c9bc4574c090be7315dc133d21a364afd72af9115ea470fe026aeed18443d50271523ce2ea64d5c729315a0f0dd4433b807b23f4285ce3b8a1537174274
|
|
7
|
+
data.tar.gz: 8a1cc9ab25dd32116be49e3a05c67234040cb47d7db36629ff2fe38bfdb85684b3a9a9846900ea997054c8ac2ce140f4e27e0f4b5998980714382446e6d0a6de
|
data/CHANGELOG.md
CHANGED
|
@@ -1,41 +1,58 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
<!-- usage documentation: http://expeditor-docs.es.chef.io/configuration/changelog/ -->
|
|
3
|
-
<!-- latest_release 1.
|
|
4
|
-
## [v1.
|
|
3
|
+
<!-- latest_release 1.42.3 -->
|
|
4
|
+
## [v1.42.3](https://github.com/chef/inspec/tree/v1.42.3) (2017-10-18)
|
|
5
5
|
|
|
6
6
|
#### Enhancements
|
|
7
|
-
-
|
|
7
|
+
- windows_hotfix resource: Replace WMI query with PowerShell cmdlet "get-hotfix" [#2252](https://github.com/chef/inspec/pull/2252) ([mattray](https://github.com/mattray))
|
|
8
8
|
<!-- latest_release -->
|
|
9
9
|
|
|
10
|
-
<!-- release_rollup since=1.
|
|
11
|
-
### Changes since 1.
|
|
10
|
+
<!-- release_rollup since=1.41.0 -->
|
|
11
|
+
### Changes since 1.41.0 release
|
|
12
|
+
|
|
13
|
+
#### Merged Pull Requests
|
|
14
|
+
- Squashed some unit test warnings [#2242](https://github.com/chef/inspec/pull/2242) ([username-is-already-taken2](https://github.com/username-is-already-taken2)) <!-- 1.41.9 -->
|
|
15
|
+
- Fix documentation of `split` matcher [#2240](https://github.com/chef/inspec/pull/2240) ([eramoto](https://github.com/eramoto)) <!-- 1.41.4 -->
|
|
16
|
+
- Update the profile tempate [#2238](https://github.com/chef/inspec/pull/2238) ([nathenharvey](https://github.com/nathenharvey)) <!-- 1.41.3 -->
|
|
12
17
|
|
|
13
18
|
#### Bug Fixes
|
|
14
|
-
-
|
|
15
|
-
- Fix
|
|
16
|
-
- Support
|
|
17
|
-
-
|
|
19
|
+
- Fix `only_if` behavior when used outside controls [#2216](https://github.com/chef/inspec/pull/2216) ([jerryaldrichiii](https://github.com/jerryaldrichiii)) <!-- 1.41.8 -->
|
|
20
|
+
- Fix port ressource ss line parsing [#2243](https://github.com/chef/inspec/pull/2243) ([narkaTee](https://github.com/narkaTee)) <!-- 1.41.7 -->
|
|
21
|
+
- Support PAX-formatted tar files, standardize file lists [#2225](https://github.com/chef/inspec/pull/2225) ([adamleff](https://github.com/adamleff)) <!-- 1.41.2 -->
|
|
22
|
+
- Fix typo in error message in postgres resource [#2248](https://github.com/chef/inspec/pull/2248) ([rndmh3ro](https://github.com/rndmh3ro)) <!-- 1.42.2 -->
|
|
23
|
+
- Resolve the weird encoding issue within inspec shell [#2234](https://github.com/chef/inspec/pull/2234) ([username-is-already-taken2](https://github.com/username-is-already-taken2)) <!-- 1.41.10 -->
|
|
18
24
|
|
|
19
25
|
#### Enhancements
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
- Add
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
- Add Segment tag to enable Google Analytics [#2220](https://github.com/chef/inspec/pull/2220) ([hamburglar](https://github.com/hamburglar)) <!-- 1.40.6 -->
|
|
27
|
-
- http resource: properly execute tests on remote target [#2209](https://github.com/chef/inspec/pull/2209) ([adamleff](https://github.com/adamleff)) <!-- 1.40.5 -->
|
|
28
|
-
- Adding examples of using expect syntax [#2213](https://github.com/chef/inspec/pull/2213) ([adamleff](https://github.com/adamleff)) <!-- 1.40.4 -->
|
|
29
|
-
- Add bsd platform family to etc_hosts resource [#2192](https://github.com/chef/inspec/pull/2192) ([ctbarrett](https://github.com/ctbarrett)) <!-- 1.40.2 -->
|
|
30
|
-
- Clean-up kitchen-inspec reference doc [#2208](https://github.com/chef/inspec/pull/2208) ([nathenharvey](https://github.com/nathenharvey)) <!-- 1.40.1 -->
|
|
26
|
+
- windows_hotfix resource: Replace WMI query with PowerShell cmdlet "get-hotfix" [#2252](https://github.com/chef/inspec/pull/2252) ([mattray](https://github.com/mattray)) <!-- 1.42.3 -->
|
|
27
|
+
- Extend Windows ACL matchers [#1744](https://github.com/chef/inspec/pull/1744) ([TheLonelyGhost](https://github.com/TheLonelyGhost)) <!-- 1.42.1 -->
|
|
28
|
+
- Add inspec habitat profile setup command [#2239](https://github.com/chef/inspec/pull/2239) ([adamleff](https://github.com/adamleff)) <!-- 1.42.0 -->
|
|
29
|
+
- Add missed 'html' to 'format' option explanation and arrange formatters in alphabetical order [#2244](https://github.com/chef/inspec/pull/2244) ([strangeman](https://github.com/strangeman)) <!-- 1.41.6 -->
|
|
30
|
+
- Uses netstat to detect open ports on AIX [#2210](https://github.com/chef/inspec/pull/2210) ([cattywampus](https://github.com/cattywampus)) <!-- 1.41.1 -->
|
|
31
|
+
- etc_fstab resource: properly namespace the resource, add nfs_file_systems documentation [#2190](https://github.com/chef/inspec/pull/2190) ([jburns12](https://github.com/jburns12)) <!-- 1.41.5 -->
|
|
31
32
|
<!-- release_rollup -->
|
|
32
33
|
|
|
33
34
|
<!-- latest_stable_release -->
|
|
35
|
+
## [v1.41.0](https://github.com/chef/inspec/tree/v1.41.0) (2017-10-09)
|
|
36
|
+
|
|
37
|
+
#### Enhancements
|
|
38
|
+
- Add bsd platform family to etc_hosts resource [#2192](https://github.com/chef/inspec/pull/2192) ([ctbarrett](https://github.com/ctbarrett))
|
|
39
|
+
- http resource: properly execute tests on remote target [#2209](https://github.com/chef/inspec/pull/2209) ([adamleff](https://github.com/adamleff))
|
|
40
|
+
- Add output for port/protocol for host resource. [#2202](https://github.com/chef/inspec/pull/2202) ([jquick](https://github.com/jquick))
|
|
41
|
+
- Update shell resource help to return what is defined [#2219](https://github.com/chef/inspec/pull/2219) ([jquick](https://github.com/jquick))
|
|
42
|
+
- processes resource: support busybox ps [#2222](https://github.com/chef/inspec/pull/2222) ([adamleff](https://github.com/adamleff))
|
|
43
|
+
- Enhance cmp matcher to work with symbols, fix file documentation [#2224](https://github.com/chef/inspec/pull/2224) ([adamleff](https://github.com/adamleff))
|
|
44
|
+
|
|
45
|
+
#### Bug Fixes
|
|
46
|
+
- Add nil check for sshd config file [#2217](https://github.com/chef/inspec/pull/2217) ([jquick](https://github.com/jquick))
|
|
47
|
+
- Support symbol keys in ObjectTraverser [#2221](https://github.com/chef/inspec/pull/2221) ([adamleff](https://github.com/adamleff))
|
|
48
|
+
- Fix loading profile files when executing multiple profiles [#2223](https://github.com/chef/inspec/pull/2223) ([adamleff](https://github.com/adamleff))
|
|
49
|
+
- ssl resource: properly raise error when unable to determine if port is enabled [#2205](https://github.com/chef/inspec/pull/2205) ([jquick](https://github.com/jquick))
|
|
50
|
+
<!-- latest_stable_release -->
|
|
51
|
+
|
|
34
52
|
## [v1.40.0](https://github.com/chef/inspec/tree/v1.40.0) (2017-09-28)
|
|
35
53
|
|
|
36
54
|
#### New Resources
|
|
37
55
|
- firewalld resource: inspect the status and configuration of firewalld [#2074](https://github.com/chef/inspec/pull/2074) ([dromazmj](https://github.com/dromazmj))
|
|
38
|
-
<!-- latest_stable_release -->
|
|
39
56
|
|
|
40
57
|
## [v1.39.0](https://github.com/chef/inspec/tree/v1.39.0) (2017-09-25)
|
|
41
58
|
|
|
@@ -100,7 +100,7 @@ The following examples show how to use this InSpec resource.
|
|
|
100
100
|
|
|
101
101
|
### Check all partitions that have type of 'nfs'.
|
|
102
102
|
|
|
103
|
-
nfs_systems = etc_fstab.nfs_file_systems
|
|
103
|
+
nfs_systems = etc_fstab.nfs_file_systems.entries
|
|
104
104
|
nfs_systems.each do |partition|
|
|
105
105
|
describe partition do
|
|
106
106
|
its('mount_options') { should include 'nosuid' }
|
|
@@ -70,14 +70,8 @@ The `content` matcher return the value of the environment variable:
|
|
|
70
70
|
|
|
71
71
|
### split
|
|
72
72
|
|
|
73
|
-
The `split` splits the
|
|
73
|
+
The `split` matcher splits the value of the environment variable with the `:` deliminator (use the `;` deliminator if Windows):
|
|
74
74
|
|
|
75
|
-
its('split') { should include ('
|
|
75
|
+
its('split') { should include ('/usr/bin') }
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
its('split') { should_not include ('.') }
|
|
80
|
-
|
|
81
|
-
Use `-1` to test for cases where there is a trailing colon (`:`), such as `dir1::dir2:`:
|
|
82
|
-
|
|
83
|
-
its('split') { should include ('-1') }
|
|
77
|
+
Note: the `split` matcher returns an array including `""` for cases where there is a trailing colon (`:`), such as `dir1::dir2:`
|
|
@@ -7,14 +7,19 @@ module Habitat
|
|
|
7
7
|
class HabitatProfileCLI < Thor
|
|
8
8
|
namespace 'habitat profile'
|
|
9
9
|
|
|
10
|
-
desc 'create PATH', 'Create a Habitat artifact for the profile found at PATH'
|
|
10
|
+
desc 'create PATH', 'Create a one-time Habitat artifact for the profile found at PATH'
|
|
11
11
|
option :output_dir, type: :string, required: false,
|
|
12
12
|
desc: 'Directory in which to save the generated Habitat artifact. Default: current directory'
|
|
13
13
|
def create(path)
|
|
14
14
|
Habitat::Profile.create(path, options)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
desc '
|
|
17
|
+
desc 'setup PATH', 'Configure the profile at PATH for Habitat, including a plan and hooks'
|
|
18
|
+
def setup(path)
|
|
19
|
+
Habitat::Profile.setup(path)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
desc 'upload PATH', 'Create a one-time Habitat artifact for the profile found at PATH, and upload it to a Habitat Depot'
|
|
18
23
|
def upload(path)
|
|
19
24
|
Habitat::Profile.upload(path, options)
|
|
20
25
|
end
|
|
@@ -17,6 +17,10 @@ module Habitat
|
|
|
17
17
|
creator.delete_work_dir
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
def self.setup(path)
|
|
21
|
+
new(path).setup
|
|
22
|
+
end
|
|
23
|
+
|
|
20
24
|
def self.upload(path, options = {})
|
|
21
25
|
uploader = new(path, options)
|
|
22
26
|
uploader.upload
|
|
@@ -41,10 +45,11 @@ module Habitat
|
|
|
41
45
|
verify_profile
|
|
42
46
|
vendor_profile_dependencies
|
|
43
47
|
copy_profile_to_work_dir
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
create_habitat_directories(work_dir)
|
|
49
|
+
create_plan(work_dir)
|
|
50
|
+
create_run_hook(work_dir)
|
|
51
|
+
create_settings_file(work_dir)
|
|
52
|
+
create_default_config(work_dir)
|
|
48
53
|
|
|
49
54
|
# returns the path to the .hart file in the work directory
|
|
50
55
|
build_hart
|
|
@@ -80,6 +85,18 @@ module Habitat
|
|
|
80
85
|
FileUtils.rm_rf(work_dir) if Dir.exist?(work_dir)
|
|
81
86
|
end
|
|
82
87
|
|
|
88
|
+
def setup
|
|
89
|
+
Habitat::Log.info("Setting up profile at #{path} for Habitat...")
|
|
90
|
+
create_profile_object
|
|
91
|
+
verify_profile
|
|
92
|
+
vendor_profile_dependencies
|
|
93
|
+
create_habitat_directories(path)
|
|
94
|
+
create_plan(path)
|
|
95
|
+
create_run_hook(path)
|
|
96
|
+
create_settings_file(path)
|
|
97
|
+
create_default_config(path)
|
|
98
|
+
end
|
|
99
|
+
|
|
83
100
|
private
|
|
84
101
|
|
|
85
102
|
def create_profile_object
|
|
@@ -151,20 +168,26 @@ module Habitat
|
|
|
151
168
|
return @work_dir if @work_dir
|
|
152
169
|
|
|
153
170
|
@work_dir ||= Dir.mktmpdir('inspec-habitat-exporter')
|
|
154
|
-
Dir.mkdir(File.join(@work_dir, 'src'))
|
|
155
|
-
Dir.mkdir(File.join(@work_dir, 'habitat'))
|
|
156
|
-
Dir.mkdir(File.join(@work_dir, 'habitat', 'config'))
|
|
157
|
-
Dir.mkdir(File.join(@work_dir, 'habitat', 'hooks'))
|
|
158
171
|
Habitat::Log.debug("Generated work directory #{@work_dir}")
|
|
159
172
|
|
|
160
173
|
@work_dir
|
|
161
174
|
end
|
|
162
175
|
|
|
176
|
+
def create_habitat_directories(parent_directory)
|
|
177
|
+
[
|
|
178
|
+
File.join(parent_directory, 'habitat'),
|
|
179
|
+
File.join(parent_directory, 'habitat', 'config'),
|
|
180
|
+
File.join(parent_directory, 'habitat', 'hooks'),
|
|
181
|
+
].each do |dir|
|
|
182
|
+
Dir.mkdir(dir) unless Dir.exist?(dir)
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
163
186
|
def copy_profile_to_work_dir
|
|
164
187
|
Habitat::Log.info('Copying profile contents to the work directory...')
|
|
165
188
|
profile.files.each do |f|
|
|
166
189
|
src = File.join(profile.root_path, f)
|
|
167
|
-
dst = File.join(work_dir,
|
|
190
|
+
dst = File.join(work_dir, f)
|
|
168
191
|
if File.directory?(f)
|
|
169
192
|
Habitat::Log.debug("Creating directory #{dst}")
|
|
170
193
|
FileUtils.mkdir_p(dst)
|
|
@@ -175,26 +198,26 @@ module Habitat
|
|
|
175
198
|
end
|
|
176
199
|
end
|
|
177
200
|
|
|
178
|
-
def create_plan
|
|
179
|
-
plan_file = File.join(
|
|
201
|
+
def create_plan(directory)
|
|
202
|
+
plan_file = File.join(directory, 'habitat', 'plan.sh')
|
|
180
203
|
Habitat::Log.info("Generating Habitat plan at #{plan_file}...")
|
|
181
204
|
File.write(plan_file, plan_contents)
|
|
182
205
|
end
|
|
183
206
|
|
|
184
|
-
def create_run_hook
|
|
185
|
-
run_hook_file = File.join(
|
|
207
|
+
def create_run_hook(directory)
|
|
208
|
+
run_hook_file = File.join(directory, 'habitat', 'hooks', 'run')
|
|
186
209
|
Habitat::Log.info("Generating a Habitat run hook at #{run_hook_file}...")
|
|
187
210
|
File.write(run_hook_file, run_hook_contents)
|
|
188
211
|
end
|
|
189
212
|
|
|
190
|
-
def create_settings_file
|
|
191
|
-
settings_file = File.join(
|
|
213
|
+
def create_settings_file(directory)
|
|
214
|
+
settings_file = File.join(directory, 'habitat', 'config', 'settings.sh')
|
|
192
215
|
Habitat::Log.info("Generating a settings file at #{settings_file}...")
|
|
193
216
|
File.write(settings_file, "SLEEP_TIME={{cfg.sleep_time}}\n")
|
|
194
217
|
end
|
|
195
218
|
|
|
196
|
-
def create_default_config
|
|
197
|
-
default_toml = File.join(
|
|
219
|
+
def create_default_config(directory)
|
|
220
|
+
default_toml = File.join(directory, 'habitat', 'default.toml')
|
|
198
221
|
Habitat::Log.info("Generating Habitat's default.toml configuration...")
|
|
199
222
|
File.write(default_toml, 'sleep_time = 300')
|
|
200
223
|
end
|
|
@@ -308,7 +331,7 @@ EOL
|
|
|
308
331
|
plan += <<-EOL
|
|
309
332
|
|
|
310
333
|
do_build() {
|
|
311
|
-
cp -vr $PLAN_CONTEXT
|
|
334
|
+
cp -vr $PLAN_CONTEXT/../* $HAB_CACHE_SRC_PATH/$pkg_dirname
|
|
312
335
|
}
|
|
313
336
|
|
|
314
337
|
do_install() {
|
|
@@ -321,6 +344,7 @@ do_install() {
|
|
|
321
344
|
profile_contents=(${profile_contents[@]/$item/})
|
|
322
345
|
done
|
|
323
346
|
|
|
347
|
+
mkdir ${pkg_prefix}/dist
|
|
324
348
|
cp -r ${profile_contents[@]} ${pkg_prefix}/dist/
|
|
325
349
|
}
|
|
326
350
|
EOL
|
data/lib/inspec/cli.rb
CHANGED
|
@@ -186,7 +186,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
|
|
186
186
|
option :command, aliases: :c,
|
|
187
187
|
desc: 'A single command string to run instead of launching the shell'
|
|
188
188
|
option :format, type: :string, default: nil, hide: true,
|
|
189
|
-
desc: 'Which formatter to use: cli,
|
|
189
|
+
desc: 'Which formatter to use: cli, documentation, html, json, json-min, junit, progress'
|
|
190
190
|
def shell_func
|
|
191
191
|
diagnose
|
|
192
192
|
o = opts.dup
|
|
@@ -35,7 +35,7 @@ module Inspec
|
|
|
35
35
|
# @param profile_context [Inspec::ProfileContext]
|
|
36
36
|
# @param outer_dsl [OuterDSLClass]
|
|
37
37
|
# @return [ProfileContextClass]
|
|
38
|
-
def self.create(profile_context, resources_dsl) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
38
|
+
def self.create(profile_context, resources_dsl) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
39
39
|
rule_class = rule_context(resources_dsl)
|
|
40
40
|
profile_context_owner = profile_context
|
|
41
41
|
profile_id = profile_context.profile_id
|
|
@@ -45,12 +45,14 @@ module Inspec
|
|
|
45
45
|
include Inspec::DSL::RequireOverride
|
|
46
46
|
include resources_dsl
|
|
47
47
|
|
|
48
|
+
attr_accessor :skip_file
|
|
49
|
+
|
|
48
50
|
def initialize(backend, conf, dependencies, require_loader)
|
|
49
51
|
@backend = backend
|
|
50
52
|
@conf = conf
|
|
51
53
|
@dependencies = dependencies
|
|
52
54
|
@require_loader = require_loader
|
|
53
|
-
@
|
|
55
|
+
@skip_file = false
|
|
54
56
|
end
|
|
55
57
|
|
|
56
58
|
define_method :title do |arg|
|
|
@@ -113,7 +115,7 @@ module Inspec
|
|
|
113
115
|
end
|
|
114
116
|
|
|
115
117
|
define_method :register_control do |control, &block|
|
|
116
|
-
if @
|
|
118
|
+
if @skip_file || !profile_context_owner.profile_supports_os?
|
|
117
119
|
::Inspec::Rule.set_skip_rule(control, true)
|
|
118
120
|
end
|
|
119
121
|
|
|
@@ -129,9 +131,17 @@ module Inspec
|
|
|
129
131
|
profile_context_owner.unregister_rule(id)
|
|
130
132
|
end
|
|
131
133
|
|
|
132
|
-
|
|
133
|
-
return unless
|
|
134
|
-
@
|
|
134
|
+
define_method :only_if do |&block|
|
|
135
|
+
return unless block
|
|
136
|
+
return if @skip_file == true || block.yield == true
|
|
137
|
+
|
|
138
|
+
# Apply `set_skip_rule` for other rules in the same file
|
|
139
|
+
profile_context_owner.rules.values.each do |r|
|
|
140
|
+
sources_match = r.source_file == block.source_location[0]
|
|
141
|
+
Inspec::Rule.set_skip_rule(r, true) if sources_match
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
@skip_file = true
|
|
135
145
|
end
|
|
136
146
|
|
|
137
147
|
alias_method :rule, :control
|
data/lib/inspec/file_provider.rb
CHANGED
|
@@ -137,7 +137,16 @@ module Inspec
|
|
|
137
137
|
@contents = {}
|
|
138
138
|
@files = []
|
|
139
139
|
walk_tar(@path) do |tar|
|
|
140
|
-
@files = tar.
|
|
140
|
+
@files = tar.find_all(&:file?)
|
|
141
|
+
|
|
142
|
+
# delete all entries with no name
|
|
143
|
+
@files = @files.find_all { |x| !x.full_name.empty? }
|
|
144
|
+
|
|
145
|
+
# delete all entries that have a PaxHeader
|
|
146
|
+
@files = @files.delete_if { |x| x.full_name.include?('PaxHeader/') }
|
|
147
|
+
|
|
148
|
+
# replace all items of the array simply with the relative filename of the file
|
|
149
|
+
@files.map! { |x| Pathname.new(x.full_name).relative_path_from(Pathname.new('.')).to_s }
|
|
141
150
|
end
|
|
142
151
|
end
|
|
143
152
|
|
|
@@ -157,7 +166,7 @@ module Inspec
|
|
|
157
166
|
# NB `TarReader` includes `Enumerable` beginning with Ruby 2.x
|
|
158
167
|
walk_tar(@path) do |tar|
|
|
159
168
|
tar.each do |entry|
|
|
160
|
-
next unless entry.file? && file
|
|
169
|
+
next unless entry.file? && [file, "./#{file}"].include?(entry.full_name)
|
|
161
170
|
res = entry.read
|
|
162
171
|
break
|
|
163
172
|
end
|
|
@@ -182,8 +191,19 @@ module Inspec
|
|
|
182
191
|
if @prefix.nil?
|
|
183
192
|
raise "Could not determine path prefix for #{parent}"
|
|
184
193
|
end
|
|
185
|
-
|
|
194
|
+
|
|
195
|
+
# select all files that begin with the prefix, and strip off the prefix from the file.
|
|
196
|
+
#
|
|
197
|
+
# strip off any leading top-level relative path (./) which is common in
|
|
198
|
+
# PAX-formatted tar files. Do not do any translation of the path if the
|
|
199
|
+
# path is an absolute path.
|
|
200
|
+
@files = parent.files
|
|
201
|
+
.find_all { |x| x.start_with?(prefix) && x != prefix }
|
|
186
202
|
.map { |x| x[prefix.length..-1] }
|
|
203
|
+
.map do |x|
|
|
204
|
+
path = Pathname.new(x)
|
|
205
|
+
path.absolute? ? path.to_s : path.relative_path_from(Pathname.new('.')).to_s
|
|
206
|
+
end
|
|
187
207
|
end
|
|
188
208
|
|
|
189
209
|
def abs_path(file)
|
|
@@ -127,6 +127,8 @@ module Inspec
|
|
|
127
127
|
end
|
|
128
128
|
|
|
129
129
|
def load_control_file(*args)
|
|
130
|
+
# Set `skip_file` to `false` between file loads to prevent skips from spanning multiple control files
|
|
131
|
+
control_eval_context.skip_file = false
|
|
130
132
|
load_with_context(control_eval_context, *args)
|
|
131
133
|
end
|
|
132
134
|
alias load load_control_file
|
data/lib/inspec/rule.rb
CHANGED
data/lib/inspec/shell.rb
CHANGED
|
@@ -42,7 +42,7 @@ module Inspec
|
|
|
42
42
|
|
|
43
43
|
# configure pry shell prompt
|
|
44
44
|
Pry.config.prompt_name = 'inspec'
|
|
45
|
-
Pry.prompt = [proc { "#{readline_ignore("\e[
|
|
45
|
+
Pry.prompt = [proc { "#{readline_ignore("\e[1m\e[32m")}#{Pry.config.prompt_name}> #{readline_ignore("\e[0m")}" }]
|
|
46
46
|
|
|
47
47
|
# Add a help menu as the default intro
|
|
48
48
|
Pry.hooks.add_hook(:before_session, 'inspec_intro') do
|
|
@@ -79,7 +79,7 @@ module Inspec
|
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
def mark(x)
|
|
82
|
-
"
|
|
82
|
+
"\e[1m\e[39m#{x}\e[0m"
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
def print_example(example)
|
|
@@ -106,8 +106,8 @@ module Inspec
|
|
|
106
106
|
puts <<EOF
|
|
107
107
|
You are currently running on:
|
|
108
108
|
|
|
109
|
-
OS platform:
|
|
110
|
-
OS family:
|
|
109
|
+
OS platform: #{mark ctx.os[:name] || 'unknown'}
|
|
110
|
+
OS family: #{mark ctx.os[:family] || 'unknown'}
|
|
111
111
|
OS release: #{mark ctx.os[:release] || 'unknown'}
|
|
112
112
|
EOF
|
|
113
113
|
end
|
data/lib/inspec/version.rb
CHANGED
data/lib/resources/etc_fstab.rb
CHANGED
|
@@ -4,104 +4,99 @@
|
|
|
4
4
|
|
|
5
5
|
require 'utils/parser'
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
module Inspec::Resources
|
|
8
|
+
class EtcFstab < Inspec.resource(1)
|
|
9
|
+
name 'etc_fstab'
|
|
10
|
+
desc 'Use the etc_fstab InSpec audit resource to check the configuration of the etc/fstab file.'
|
|
11
|
+
example "
|
|
12
|
+
nfs_systems = etc_fstab.nfs_file_systems.entries
|
|
13
|
+
nfs_systems.each do |file_system|
|
|
14
|
+
describe file_system do
|
|
15
|
+
its ('mount_options') { should include 'nosuid' }
|
|
16
|
+
its ('mount_options') { should include 'noexec' }
|
|
17
|
+
its ('mount_options') { should include 'sec=krb5:krb5i:krb5p }
|
|
18
|
+
end
|
|
15
19
|
end
|
|
16
|
-
end
|
|
17
20
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
describe file_system do
|
|
21
|
-
its ('mount_options') { should include 'nosuid' }
|
|
22
|
-
its ('mount_options') { should include 'noexec' }
|
|
23
|
-
its ('mount_options') { should include '\'sec=krb5:krb5i:krb5p\'' }
|
|
21
|
+
describe etc_fstab do
|
|
22
|
+
its ('home_mount_options') { should include 'nosuid' }
|
|
24
23
|
end
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
describe etc_fstab do
|
|
28
|
-
its ('home_mount_options') { should include 'nosuid' }
|
|
29
|
-
end
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
attr_reader :params
|
|
24
|
+
"
|
|
33
25
|
|
|
34
|
-
|
|
26
|
+
attr_reader :params
|
|
35
27
|
|
|
36
|
-
|
|
37
|
-
return skip_resource 'The `etc_fstab` resource is not supported on your OS.' unless inspec.os.linux?
|
|
38
|
-
@conf_path = fstab_path || '/etc/fstab'
|
|
39
|
-
@files_contents = {}
|
|
40
|
-
@content = nil
|
|
41
|
-
@params = nil
|
|
42
|
-
read_content
|
|
43
|
-
end
|
|
28
|
+
include CommentParser
|
|
44
29
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
.add(:file_system_options, field: 'file_system_options')
|
|
54
|
-
.add(:configured?) { |x| x.entries.any? }
|
|
55
|
-
|
|
56
|
-
filter.connect(self, :params)
|
|
57
|
-
|
|
58
|
-
def nfs_file_systems
|
|
59
|
-
where { file_system_type.match(/nfs/) }
|
|
60
|
-
end
|
|
30
|
+
def initialize(fstab_path = nil)
|
|
31
|
+
return skip_resource 'The `etc_fstab` resource is not supported on your OS.' unless inspec.os.linux?
|
|
32
|
+
@conf_path = fstab_path || '/etc/fstab'
|
|
33
|
+
@files_contents = {}
|
|
34
|
+
@content = nil
|
|
35
|
+
@params = nil
|
|
36
|
+
read_content
|
|
37
|
+
end
|
|
61
38
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
39
|
+
filter = FilterTable.create
|
|
40
|
+
filter.add_accessor(:where)
|
|
41
|
+
.add_accessor(:entries)
|
|
42
|
+
.add(:device_name, field: 'device_name')
|
|
43
|
+
.add(:mount_point, field: 'mount_point')
|
|
44
|
+
.add(:file_system_type, field: 'file_system_type')
|
|
45
|
+
.add(:mount_options, field: 'mount_options')
|
|
46
|
+
.add(:dump_options, field: 'dump_options')
|
|
47
|
+
.add(:file_system_options, field: 'file_system_options')
|
|
48
|
+
.add(:configured?) { |x| x.entries.any? }
|
|
49
|
+
|
|
50
|
+
filter.connect(self, :params)
|
|
51
|
+
|
|
52
|
+
def nfs_file_systems
|
|
53
|
+
where { file_system_type.match(/nfs/) }
|
|
54
|
+
end
|
|
66
55
|
|
|
67
|
-
|
|
56
|
+
def home_mount_options
|
|
57
|
+
return nil unless where { mount_point == '/home' }.configured?
|
|
58
|
+
where { mount_point == '/home' }.entries[0].mount_options
|
|
59
|
+
end
|
|
68
60
|
|
|
69
|
-
|
|
70
|
-
@content = ''
|
|
71
|
-
@params = {}
|
|
72
|
-
@content = read_file(@conf_path)
|
|
73
|
-
@params = parse_conf(@content)
|
|
74
|
-
end
|
|
61
|
+
private
|
|
75
62
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
63
|
+
def read_content
|
|
64
|
+
@content = ''
|
|
65
|
+
@params = {}
|
|
66
|
+
@content = read_file(@conf_path)
|
|
67
|
+
@params = parse_conf(@content)
|
|
68
|
+
end
|
|
82
69
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
'mount_options' => attributes[3].split(','),
|
|
90
|
-
'dump_options' => attributes[4].to_i,
|
|
91
|
-
'file_system_options' => attributes[5].to_i,
|
|
92
|
-
}
|
|
93
|
-
end
|
|
70
|
+
def parse_conf(content)
|
|
71
|
+
content.map do |line|
|
|
72
|
+
data, = parse_comment_line(line, comment_char: '#', standalone_comments: false)
|
|
73
|
+
parse_line(data) unless data == ''
|
|
74
|
+
end.compact
|
|
75
|
+
end
|
|
94
76
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
77
|
+
def parse_line(line)
|
|
78
|
+
attributes = line.split
|
|
79
|
+
{
|
|
80
|
+
'device_name' => attributes[0],
|
|
81
|
+
'mount_point' => attributes[1],
|
|
82
|
+
'file_system_type' => attributes[2],
|
|
83
|
+
'mount_options' => attributes[3].split(','),
|
|
84
|
+
'dump_options' => attributes[4].to_i,
|
|
85
|
+
'file_system_options' => attributes[5].to_i,
|
|
86
|
+
}
|
|
99
87
|
end
|
|
100
88
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
89
|
+
def read_file(conf_path = @conf_path)
|
|
90
|
+
file = inspec.file(conf_path)
|
|
91
|
+
if !file.file?
|
|
92
|
+
return skip_resource "Can't find \"#{@conf_path}\""
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
raw_conf = file.content
|
|
96
|
+
if raw_conf.empty? && !file.empty?
|
|
97
|
+
return skip_resource("File is empty or unable to read file at path:\"#{@conf_path}\"")
|
|
98
|
+
end
|
|
99
|
+
raw_conf.lines
|
|
104
100
|
end
|
|
105
|
-
raw_conf.lines
|
|
106
101
|
end
|
|
107
102
|
end
|
data/lib/resources/file.rb
CHANGED
|
@@ -84,6 +84,13 @@ module Inspec::Resources
|
|
|
84
84
|
file_permission_granted?('execute', by_usergroup, by_specific_user)
|
|
85
85
|
end
|
|
86
86
|
|
|
87
|
+
def allowed?(permission, opts = {})
|
|
88
|
+
return false unless exist?
|
|
89
|
+
return skip_resource '`allowed?` is not supported on your OS yet.' if @perms_provider.nil?
|
|
90
|
+
|
|
91
|
+
file_permission_granted?(permission, opts[:by], opts[:by_user])
|
|
92
|
+
end
|
|
93
|
+
|
|
87
94
|
def mounted?(expected_options = nil, identical = false)
|
|
88
95
|
mounted = file.mounted
|
|
89
96
|
|
|
@@ -206,18 +213,82 @@ module Inspec::Resources
|
|
|
206
213
|
end
|
|
207
214
|
|
|
208
215
|
def check_file_permission_by_user(access_type, user, path)
|
|
209
|
-
access_rule =
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
when 'write'
|
|
213
|
-
'@(\'FullControl\', \'Modify\', \'Write\')'
|
|
214
|
-
when 'execute'
|
|
215
|
-
'@(\'FullControl\', \'Modify\', \'ReadAndExecute\', \'ExecuteFile\')'
|
|
216
|
-
else
|
|
217
|
-
raise 'Invalid access_type provided'
|
|
218
|
-
end
|
|
216
|
+
access_rule = translate_perm_names(access_type)
|
|
217
|
+
access_rule = convert_to_powershell_array(access_rule)
|
|
218
|
+
|
|
219
219
|
cmd = inspec.command("@(@((Get-Acl '#{path}').access | Where-Object {$_.AccessControlType -eq 'Allow' -and $_.IdentityReference -eq '#{user}' }) | Where-Object {($_.FileSystemRights.ToString().Split(',') | % {$_.trim()} | ? {#{access_rule} -contains $_}) -ne $null}) | measure | % { $_.Count }")
|
|
220
220
|
cmd.stdout.chomp == '0' ? false : true
|
|
221
221
|
end
|
|
222
|
+
|
|
223
|
+
private
|
|
224
|
+
|
|
225
|
+
def convert_to_powershell_array(arr)
|
|
226
|
+
if arr.empty?
|
|
227
|
+
'@()'
|
|
228
|
+
else
|
|
229
|
+
%{@('#{arr.join("', '")}')}
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# Translates a developer-friendly string into a list of acceptable
|
|
234
|
+
# FileSystemRights that match it, because Windows has a fun heirarchy
|
|
235
|
+
# of permissions that are able to be noted in multiple ways.
|
|
236
|
+
#
|
|
237
|
+
# See also: https://www.codeproject.com/Reference/871338/AccessControl-FileSystemRights-Permissions-Table
|
|
238
|
+
def translate_perm_names(access_type)
|
|
239
|
+
names = translate_common_perms(access_type)
|
|
240
|
+
names ||= translate_granular_perms(access_type)
|
|
241
|
+
names ||= translate_uncommon_perms(access_type)
|
|
242
|
+
raise 'Invalid access_type provided' unless names
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def translate_common_perms(access_type)
|
|
246
|
+
case access_type
|
|
247
|
+
when 'full-control'
|
|
248
|
+
%w{FullControl}
|
|
249
|
+
when 'modify'
|
|
250
|
+
translate_perm_names('full-control') + %w{Modify}
|
|
251
|
+
when 'read'
|
|
252
|
+
translate_perm_names('modify') + %w{ReadAndExecute Read}
|
|
253
|
+
when 'write'
|
|
254
|
+
translate_perm_names('modify') + %w{Write}
|
|
255
|
+
when 'execute'
|
|
256
|
+
translate_perm_names('modify') + %w{ReadAndExecute ExecuteFile Traverse}
|
|
257
|
+
when 'delete'
|
|
258
|
+
translate_perm_names('modify') + %w{Delete}
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def translate_uncommon_perms(access_type)
|
|
263
|
+
case access_type
|
|
264
|
+
when 'delete-subdirectories-and-files'
|
|
265
|
+
translate_perm_names('full-control') + %w{DeleteSubdirectoriesAndFiles}
|
|
266
|
+
when 'change-permissions'
|
|
267
|
+
translate_perm_names('full-control') + %w{ChangePermissions}
|
|
268
|
+
when 'take-ownership'
|
|
269
|
+
translate_perm_names('full-control') + %w{TakeOwnership}
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def translate_granular_perms(access_type)
|
|
274
|
+
case access_type
|
|
275
|
+
when 'write-data', 'create-files'
|
|
276
|
+
translate_perm_names('write') + %w{WriteData CreateFiles}
|
|
277
|
+
when 'append-data', 'create-directories'
|
|
278
|
+
translate_perm_names('write') + %w{CreateDirectories AppendData}
|
|
279
|
+
when 'write-extended-attributes'
|
|
280
|
+
translate_perm_names('write') + %w{WriteExtendedAttributes}
|
|
281
|
+
when 'write-attributes'
|
|
282
|
+
translate_perm_names('write') + %w{WriteAttributes}
|
|
283
|
+
when 'read-data', 'list-directory'
|
|
284
|
+
translate_perm_names('read') + %w{ReadData ListDirectory}
|
|
285
|
+
when 'read-attributes'
|
|
286
|
+
translate_perm_names('read') + %w{ReadAttributes}
|
|
287
|
+
when 'read-extended-attributes'
|
|
288
|
+
translate_perm_names('read') + %w{ReadExtendedAttributes}
|
|
289
|
+
when 'read-permissions'
|
|
290
|
+
translate_perm_names('read') + %w{ReadPermissions}
|
|
291
|
+
end
|
|
292
|
+
end
|
|
222
293
|
end
|
|
223
294
|
end
|
data/lib/resources/port.rb
CHANGED
|
@@ -59,9 +59,11 @@ module Inspec::Resources
|
|
|
59
59
|
os = inspec.os
|
|
60
60
|
if os.linux?
|
|
61
61
|
LinuxPorts.new(inspec)
|
|
62
|
-
elsif
|
|
62
|
+
elsif os.aix?
|
|
63
63
|
# AIX: see http://www.ibm.com/developerworks/aix/library/au-lsof.html#resources
|
|
64
64
|
# and https://www-01.ibm.com/marketing/iwm/iwm/web/reg/pick.do?source=aixbp
|
|
65
|
+
AixPorts.new(inspec)
|
|
66
|
+
elsif os.darwin?
|
|
65
67
|
# Darwin: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man8/lsof.8.html
|
|
66
68
|
LsofPorts.new(inspec)
|
|
67
69
|
elsif os.windows?
|
|
@@ -263,6 +265,121 @@ module Inspec::Resources
|
|
|
263
265
|
end
|
|
264
266
|
end
|
|
265
267
|
|
|
268
|
+
class AixPorts < PortsInfo
|
|
269
|
+
def info
|
|
270
|
+
ports_via_netstat || ports_via_lsof
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def ports_via_lsof
|
|
274
|
+
return nil unless inspec.command('lsof').exist?
|
|
275
|
+
LsofPorts.new(inspec).info
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def ports_via_netstat
|
|
279
|
+
return nil unless inspec.command('netstat').exist?
|
|
280
|
+
|
|
281
|
+
cmd = inspec.command('netstat -Aan | grep LISTEN')
|
|
282
|
+
return nil unless cmd.exit_status.to_i.zero?
|
|
283
|
+
|
|
284
|
+
ports = []
|
|
285
|
+
# parse all lines
|
|
286
|
+
cmd.stdout.each_line do |line|
|
|
287
|
+
port_info = parse_netstat_line(line)
|
|
288
|
+
|
|
289
|
+
# only push protocols we are interested in
|
|
290
|
+
next unless %w{tcp tcp6 udp udp6}.include?(port_info['protocol'])
|
|
291
|
+
ports.push(port_info)
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
ports
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def parse_netstat_line(line)
|
|
298
|
+
# parse each line
|
|
299
|
+
# 1 - Socket, 2 - Proto, 3 - Receive-Q, 4 - Send-Q, 5 - Local address, 6 - Foreign Address, 7 - State
|
|
300
|
+
parsed = /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)?\s+(\S+)/.match(line)
|
|
301
|
+
return {} if parsed.nil?
|
|
302
|
+
|
|
303
|
+
# parse ip4 and ip6 addresses
|
|
304
|
+
protocol = parsed[2].downcase
|
|
305
|
+
|
|
306
|
+
# detect protocol if not provided
|
|
307
|
+
protocol += '6' if parsed[5].count(':') > 1 && %w{tcp udp}.include?(protocol)
|
|
308
|
+
protocol.chop! if %w{tcp4 upd4}.include?(protocol)
|
|
309
|
+
|
|
310
|
+
# extract host and port information
|
|
311
|
+
host, port = parse_net_address(parsed[5], protocol)
|
|
312
|
+
return {} if host.nil?
|
|
313
|
+
|
|
314
|
+
# extract PID
|
|
315
|
+
cmd = inspec.command("rmsock #{parsed[1]} tcpcb")
|
|
316
|
+
parsed_pid = /^The socket (\S+) is being held by proccess (\d+) \((\S+)\)/.match(cmd.stdout)
|
|
317
|
+
return {} if parsed_pid.nil?
|
|
318
|
+
process = parsed_pid[3]
|
|
319
|
+
pid = parsed_pid[2]
|
|
320
|
+
pid = pid.to_i if pid =~ /^\d+$/
|
|
321
|
+
|
|
322
|
+
{
|
|
323
|
+
'port' => port,
|
|
324
|
+
'address' => host,
|
|
325
|
+
'protocol' => protocol,
|
|
326
|
+
'process' => process,
|
|
327
|
+
'pid' => pid,
|
|
328
|
+
}
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
def parse_net_address(net_addr, protocol)
|
|
332
|
+
# local/foreign addresses on AIX use a '.' to separate the addresss
|
|
333
|
+
# from the port
|
|
334
|
+
address, _sep, port = net_addr.rpartition('.')
|
|
335
|
+
if protocol.eql?('tcp6') || protocol.eql?('udp6')
|
|
336
|
+
ip6addr = address
|
|
337
|
+
# AIX uses the wildcard character for ipv6 addresses listening on
|
|
338
|
+
# all interfaces.
|
|
339
|
+
ip6addr = '::' if ip6addr =~ /^\*$/
|
|
340
|
+
|
|
341
|
+
# v6 addresses need to end in a double-colon when using
|
|
342
|
+
# shorthand notation. netstat ends with a single colon.
|
|
343
|
+
# IPAddr will fail to properly parse an address unless it
|
|
344
|
+
# uses a double-colon for short-hand notation.
|
|
345
|
+
ip6addr += ':' if ip6addr =~ /\w:$/
|
|
346
|
+
|
|
347
|
+
begin
|
|
348
|
+
ip_parser = IPAddr.new(ip6addr)
|
|
349
|
+
rescue IPAddr::InvalidAddressError
|
|
350
|
+
# This IP is not parsable. There appears to be a bug in netstat
|
|
351
|
+
# output that truncates link-local IP addresses:
|
|
352
|
+
# example: udp6 0 0 fe80::42:acff:fe11::123 :::* 0 54550 3335/ntpd
|
|
353
|
+
# actual link address: inet6 fe80::42:acff:fe11:5/64 scope link
|
|
354
|
+
#
|
|
355
|
+
# in this example, the "5" is truncated making the netstat output
|
|
356
|
+
# an invalid IP address.
|
|
357
|
+
return [nil, nil]
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
# Check to see if this is a IPv4 address in a tcp6/udp6 line.
|
|
361
|
+
# If so, don't put brackets around the IP or URI won't know how
|
|
362
|
+
# to properly handle it.
|
|
363
|
+
# example: f000000000000000 tcp6 0 0 127.0.0.1.8005 *.* LISTEN
|
|
364
|
+
if ip_parser.ipv4?
|
|
365
|
+
ip_addr = URI("addr://#{ip6addr}:#{port}")
|
|
366
|
+
host = ip_addr.host
|
|
367
|
+
else
|
|
368
|
+
ip_addr = URI("addr://[#{ip6addr}]:#{port}")
|
|
369
|
+
host = ip_addr.host[1..ip_addr.host.size-2]
|
|
370
|
+
end
|
|
371
|
+
else
|
|
372
|
+
ip4addr = address
|
|
373
|
+
# In AIX the wildcard character is used to match all interfaces
|
|
374
|
+
ip4addr = '0.0.0.0' if ip4addr =~ /^\*$/
|
|
375
|
+
ip_addr = URI("addr://#{ip4addr}:#{port}")
|
|
376
|
+
host = ip_addr.host
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
[host, port.to_i]
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
|
|
266
383
|
# extract port information from netstat
|
|
267
384
|
class LinuxPorts < PortsInfo # rubocop:disable Metrics/ClassLength
|
|
268
385
|
ALLOWED_PROTOCOLS = %w{tcp tcp6 udp udp6}.freeze
|
|
@@ -430,13 +547,33 @@ module Inspec::Resources
|
|
|
430
547
|
# the netstat-provided data
|
|
431
548
|
host = '0.0.0.0' if host == '*'
|
|
432
549
|
|
|
433
|
-
#
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
# parse
|
|
438
|
-
|
|
439
|
-
|
|
550
|
+
# in case process list parsing is not successfull
|
|
551
|
+
process = nil
|
|
552
|
+
pid = nil
|
|
553
|
+
|
|
554
|
+
# parse process and pid from the process list
|
|
555
|
+
#
|
|
556
|
+
# remove the "users:((" and "))" parts
|
|
557
|
+
# input: users:((\"nginx\",pid=583,fd=8),(\"nginx\",pid=582,fd=8),(\"nginx\",pid=580,fd=8),(\"nginx\",pid=579,fd=8))
|
|
558
|
+
# res: \"nginx\",pid=583,fd=8),(\"nginx\",pid=582,fd=8),(\"nginx\",pid=580,fd=8),(\"nginx\",pid=579,fd=8
|
|
559
|
+
process_list_match = parsed[6].match(/users:\(\((.+)\)\)/)
|
|
560
|
+
if process_list_match
|
|
561
|
+
# list entires are seperated by "," the braces can also be removed
|
|
562
|
+
# input: \"nginx\",pid=583,fd=8),(\"nginx\",pid=582,fd=8),(\"nginx\",pid=580,fd=8),(\"nginx\",pid=579,fd=8
|
|
563
|
+
# res: ["\"nginx\",pid=583,fd=8", "\"nginx\",pid=582,fd=8", "\"nginx\",pid=580,fd=8", "\"nginx\",pid=579,fd=8"]
|
|
564
|
+
process_list = process_list_match[1].split('),(')
|
|
565
|
+
# To stay backwards compatible with netstat we need to select
|
|
566
|
+
# the last element in the resulting array.
|
|
567
|
+
# res: "\"nginx\",pid=579,fd=8"
|
|
568
|
+
|
|
569
|
+
# parse the process name from the process list
|
|
570
|
+
process_match = process_list.last.match(/^\"(\S+)\"/)
|
|
571
|
+
process = process_match.nil? ? nil : process_match[1]
|
|
572
|
+
|
|
573
|
+
# parse the PID from the process list
|
|
574
|
+
pid_match = process_list.last.match(/pid=(\d+)/)
|
|
575
|
+
pid = pid_match.nil? ? nil : pid_match[1].to_i
|
|
576
|
+
end
|
|
440
577
|
|
|
441
578
|
{
|
|
442
579
|
'port' => port,
|
data/lib/resources/postgres.rb
CHANGED
|
@@ -86,7 +86,7 @@ module Inspec::Resources
|
|
|
86
86
|
if data_dir_loc.nil?
|
|
87
87
|
warn 'Unable to find the PostgreSQL data_dir in expected location(s), please
|
|
88
88
|
execute "psql -t -A -p <port> -h <host> -c "show hba_file";" as the PostgreSQL
|
|
89
|
-
DBA to find the non-
|
|
89
|
+
DBA to find the non-standard data_dir location.'
|
|
90
90
|
end
|
|
91
91
|
data_dir_loc
|
|
92
92
|
end
|
|
@@ -18,7 +18,7 @@ module Inspec::Resources
|
|
|
18
18
|
@content = nil
|
|
19
19
|
os = inspec.os
|
|
20
20
|
return skip_resource 'The `windows_hotfix` resource is not a feature of your OS.' unless os.windows?
|
|
21
|
-
query = "
|
|
21
|
+
query = "get-hotfix -id #{@id}"
|
|
22
22
|
cmd = inspec.powershell(query)
|
|
23
23
|
@content = cmd.stdout
|
|
24
24
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: inspec
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.42.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dominik Richter
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2017-10-
|
|
11
|
+
date: 2017-10-18 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: train
|