inspec 1.41.0 → 1.42.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|