inspec 4.7.3 → 4.7.18
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/inspec.gemspec +1 -1
- data/lib/bundles/inspec-supermarket/api.rb +2 -1
- data/lib/bundles/inspec-supermarket/cli.rb +6 -6
- data/lib/bundles/inspec-supermarket/target.rb +1 -0
- data/lib/fetchers/git.rb +3 -1
- data/lib/fetchers/mock.rb +1 -0
- data/lib/fetchers/url.rb +6 -3
- data/lib/inspec/backend.rb +1 -0
- data/lib/inspec/base_cli.rb +4 -1
- data/lib/inspec/cli.rb +5 -4
- data/lib/inspec/config.rb +9 -1
- data/lib/inspec/control_eval_context.rb +1 -0
- data/lib/inspec/dependencies/cache.rb +1 -0
- data/lib/inspec/dependencies/dependency_set.rb +2 -0
- data/lib/inspec/dependencies/lockfile.rb +1 -0
- data/lib/inspec/dependencies/requirement.rb +8 -7
- data/lib/inspec/dependencies/resolver.rb +3 -3
- data/lib/inspec/describe.rb +1 -0
- data/lib/inspec/dsl.rb +1 -1
- data/lib/inspec/dsl_shared.rb +1 -1
- data/lib/inspec/env_printer.rb +4 -4
- data/lib/inspec/fetcher.rb +4 -2
- data/lib/inspec/file_provider.rb +18 -8
- data/lib/inspec/formatters/base.rb +5 -0
- data/lib/inspec/impact.rb +2 -0
- data/lib/inspec/input_registry.rb +14 -13
- data/lib/inspec/metadata.rb +6 -2
- data/lib/inspec/method_source.rb +1 -1
- data/lib/inspec/objects/control.rb +4 -1
- data/lib/inspec/objects/describe.rb +3 -1
- data/lib/inspec/objects/input.rb +6 -5
- data/lib/inspec/objects/list.rb +2 -0
- data/lib/inspec/objects/test.rb +3 -2
- data/lib/inspec/plugin/v1/plugin_types/resource.rb +7 -0
- data/lib/inspec/plugin/v1/plugins.rb +4 -3
- data/lib/inspec/plugin/v1/registry.rb +3 -2
- data/lib/inspec/plugin/v2.rb +1 -0
- data/lib/inspec/plugin/v2/activator.rb +2 -0
- data/lib/inspec/plugin/v2/config_file.rb +4 -1
- data/lib/inspec/plugin/v2/filter.rb +1 -0
- data/lib/inspec/plugin/v2/installer.rb +9 -7
- data/lib/inspec/plugin/v2/loader.rb +2 -0
- data/lib/inspec/plugin/v2/plugin_base.rb +1 -0
- data/lib/inspec/plugin/v2/plugin_types/cli.rb +2 -2
- data/lib/inspec/plugin/v2/registry.rb +3 -1
- data/lib/inspec/profile.rb +13 -6
- data/lib/inspec/profile_context.rb +4 -2
- data/lib/inspec/reporters/cli.rb +14 -10
- data/lib/inspec/reporters/json.rb +1 -0
- data/lib/inspec/reporters/json_automate.rb +3 -0
- data/lib/inspec/reporters/json_min.rb +2 -0
- data/lib/inspec/resource.rb +2 -0
- data/lib/inspec/resources/aide_conf.rb +4 -3
- data/lib/inspec/resources/apache_conf.rb +1 -1
- data/lib/inspec/resources/apt.rb +2 -0
- data/lib/inspec/resources/auditd.rb +19 -18
- data/lib/inspec/resources/bridge.rb +5 -2
- data/lib/inspec/resources/chocolatey_package.rb +2 -0
- data/lib/inspec/resources/command.rb +1 -1
- data/lib/inspec/resources/crontab.rb +9 -8
- data/lib/inspec/resources/csv.rb +1 -1
- data/lib/inspec/resources/dh_params.rb +6 -0
- data/lib/inspec/resources/docker.rb +37 -34
- data/lib/inspec/resources/docker_container.rb +1 -0
- data/lib/inspec/resources/docker_image.rb +1 -0
- data/lib/inspec/resources/docker_plugin.rb +1 -0
- data/lib/inspec/resources/docker_service.rb +1 -0
- data/lib/inspec/resources/elasticsearch.rb +24 -24
- data/lib/inspec/resources/etc_fstab.rb +8 -7
- data/lib/inspec/resources/etc_group.rb +4 -0
- data/lib/inspec/resources/etc_hosts.rb +4 -4
- data/lib/inspec/resources/etc_hosts_allow_deny.rb +5 -3
- data/lib/inspec/resources/file.rb +4 -1
- data/lib/inspec/resources/filesystem.rb +5 -3
- data/lib/inspec/resources/firewalld.rb +7 -4
- data/lib/inspec/resources/groups.rb +6 -4
- data/lib/inspec/resources/grub_conf.rb +3 -0
- data/lib/inspec/resources/host.rb +5 -3
- data/lib/inspec/resources/http.rb +6 -4
- data/lib/inspec/resources/iis_app.rb +1 -0
- data/lib/inspec/resources/iis_app_pool.rb +1 -1
- data/lib/inspec/resources/iis_site.rb +4 -3
- data/lib/inspec/resources/interface.rb +10 -7
- data/lib/inspec/resources/json.rb +1 -1
- data/lib/inspec/resources/kernel_module.rb +1 -1
- data/lib/inspec/resources/kernel_parameter.rb +2 -1
- data/lib/inspec/resources/key_rsa.rb +5 -0
- data/lib/inspec/resources/mount.rb +3 -1
- data/lib/inspec/resources/mysql_conf.rb +3 -1
- data/lib/inspec/resources/mysql_session.rb +2 -0
- data/lib/inspec/resources/nginx.rb +1 -0
- data/lib/inspec/resources/nginx_conf.rb +10 -6
- data/lib/inspec/resources/ntp_conf.rb +1 -0
- data/lib/inspec/resources/oneget.rb +1 -1
- data/lib/inspec/resources/oracledb_session.rb +4 -2
- data/lib/inspec/resources/os_env.rb +1 -0
- data/lib/inspec/resources/package.rb +10 -6
- data/lib/inspec/resources/packages.rb +7 -5
- data/lib/inspec/resources/passwd.rb +7 -7
- data/lib/inspec/resources/pip.rb +2 -0
- data/lib/inspec/resources/port.rb +22 -8
- data/lib/inspec/resources/postgres.rb +2 -1
- data/lib/inspec/resources/postgres_conf.rb +2 -0
- data/lib/inspec/resources/postgres_hba_conf.rb +6 -6
- data/lib/inspec/resources/postgres_ident_conf.rb +3 -3
- data/lib/inspec/resources/processes.rb +16 -15
- data/lib/inspec/resources/rabbitmq_config.rb +2 -0
- data/lib/inspec/resources/registry_key.rb +8 -3
- data/lib/inspec/resources/security_identifier.rb +3 -1
- data/lib/inspec/resources/security_policy.rb +2 -1
- data/lib/inspec/resources/service.rb +13 -1
- data/lib/inspec/resources/shadow.rb +1 -0
- data/lib/inspec/resources/ssh_config.rb +2 -0
- data/lib/inspec/resources/ssl.rb +12 -11
- data/lib/inspec/resources/users.rb +29 -19
- data/lib/inspec/resources/virtualization.rb +10 -0
- data/lib/inspec/resources/windows_feature.rb +1 -1
- data/lib/inspec/resources/windows_hotfix.rb +2 -0
- data/lib/inspec/resources/windows_task.rb +4 -0
- data/lib/inspec/resources/wmi.rb +2 -1
- data/lib/inspec/resources/x509_certificate.rb +8 -0
- data/lib/inspec/resources/xinetd_conf.rb +10 -9
- data/lib/inspec/resources/yum.rb +15 -11
- data/lib/inspec/resources/zfs_dataset.rb +4 -2
- data/lib/inspec/resources/zfs_pool.rb +2 -1
- data/lib/inspec/rule.rb +11 -1
- data/lib/inspec/runner.rb +9 -6
- data/lib/inspec/runner_rspec.rb +10 -8
- data/lib/inspec/schema.rb +1 -0
- data/lib/inspec/secrets.rb +1 -0
- data/lib/inspec/secrets/yaml.rb +1 -0
- data/lib/inspec/shell.rb +20 -19
- data/lib/inspec/shell_detector.rb +1 -1
- data/lib/inspec/source_reader.rb +2 -0
- data/lib/inspec/ui.rb +1 -0
- data/lib/inspec/utils/deprecation/config_file.rb +8 -4
- data/lib/inspec/utils/erlang_parser.rb +2 -0
- data/lib/inspec/utils/file_reader.rb +1 -1
- data/lib/inspec/utils/filter.rb +16 -3
- data/lib/inspec/utils/find_files.rb +2 -2
- data/lib/inspec/utils/object_traversal.rb +1 -0
- data/lib/inspec/utils/parser.rb +2 -0
- data/lib/inspec/utils/simpleconfig.rb +4 -1
- data/lib/inspec/utils/telemetry/global_methods.rb +1 -0
- data/lib/inspec/version.rb +1 -1
- data/lib/matchers/matchers.rb +4 -1
- data/lib/plugins/inspec-artifact/lib/inspec-artifact/base.rb +12 -11
- data/lib/plugins/inspec-artifact/test/functional/inspec_artifact_test.rb +3 -3
- data/lib/plugins/inspec-compliance/lib/inspec-compliance/api.rb +15 -11
- data/lib/plugins/inspec-compliance/lib/inspec-compliance/api/login.rb +4 -2
- data/lib/plugins/inspec-compliance/lib/inspec-compliance/cli.rb +13 -12
- data/lib/plugins/inspec-compliance/lib/inspec-compliance/http.rb +3 -0
- data/lib/plugins/inspec-compliance/test/unit/api_test.rb +28 -28
- data/lib/plugins/inspec-compliance/test/unit/target_test.rb +1 -1
- data/lib/plugins/inspec-habitat/lib/inspec-habitat/profile.rb +1 -1
- data/lib/plugins/inspec-habitat/test/unit/profile_test.rb +7 -6
- data/lib/plugins/inspec-init/lib/inspec-init/cli_profile.rb +2 -2
- data/lib/plugins/inspec-init/lib/inspec-init/renderer.rb +1 -0
- data/lib/plugins/inspec-init/test/functional/inspec_init_plugin_test.rb +12 -10
- data/lib/plugins/inspec-plugin-manager-cli/lib/inspec-plugin-manager-cli/cli_command.rb +6 -5
- data/lib/plugins/inspec-plugin-manager-cli/test/functional/inspec-plugin_test.rb +1 -0
- data/lib/plugins/shared/core_plugin_test_helper.rb +1 -0
- data/lib/resource_support/aws/aws_resource_mixin.rb +3 -2
- data/lib/resources/aws/aws_billing_report.rb +1 -1
- data/lib/resources/aws/aws_billing_reports.rb +8 -7
- data/lib/resources/aws/aws_cloudtrail_trail.rb +1 -1
- data/lib/resources/aws/aws_cloudtrail_trails.rb +1 -0
- data/lib/resources/aws/aws_cloudwatch_alarm.rb +4 -3
- data/lib/resources/aws/aws_cloudwatch_log_metric_filter.rb +2 -1
- data/lib/resources/aws/aws_config_delivery_channel.rb +1 -1
- data/lib/resources/aws/aws_config_recorder.rb +2 -0
- data/lib/resources/aws/aws_ebs_volume.rb +1 -0
- data/lib/resources/aws/aws_ebs_volumes.rb +2 -0
- data/lib/resources/aws/aws_ec2_instance.rb +2 -0
- data/lib/resources/aws/aws_ec2_instances.rb +2 -0
- data/lib/resources/aws/aws_ecs_cluster.rb +2 -2
- data/lib/resources/aws/aws_eks_cluster.rb +3 -3
- data/lib/resources/aws/aws_elb.rb +2 -2
- data/lib/resources/aws/aws_elbs.rb +14 -12
- data/lib/resources/aws/aws_flow_log.rb +2 -2
- data/lib/resources/aws/aws_iam_access_key.rb +3 -1
- data/lib/resources/aws/aws_iam_access_keys.rb +18 -16
- data/lib/resources/aws/aws_iam_groups.rb +1 -0
- data/lib/resources/aws/aws_iam_password_policy.rb +9 -7
- data/lib/resources/aws/aws_iam_policies.rb +2 -1
- data/lib/resources/aws/aws_iam_policy.rb +10 -1
- data/lib/resources/aws/aws_iam_role.rb +1 -0
- data/lib/resources/aws/aws_iam_user.rb +5 -2
- data/lib/resources/aws/aws_iam_users.rb +12 -11
- data/lib/resources/aws/aws_kms_key.rb +2 -2
- data/lib/resources/aws/aws_kms_keys.rb +3 -1
- data/lib/resources/aws/aws_route_table.rb +2 -2
- data/lib/resources/aws/aws_route_tables.rb +2 -1
- data/lib/resources/aws/aws_s3_bucket.rb +5 -3
- data/lib/resources/aws/aws_s3_bucket_object.rb +3 -1
- data/lib/resources/aws/aws_s3_buckets.rb +1 -0
- data/lib/resources/aws/aws_security_group.rb +20 -9
- data/lib/resources/aws/aws_security_groups.rb +1 -0
- data/lib/resources/aws/aws_sns_subscription.rb +1 -1
- data/lib/resources/aws/aws_sns_topics.rb +2 -0
- data/lib/resources/aws/aws_subnet.rb +2 -2
- data/lib/resources/aws/aws_subnets.rb +4 -3
- data/lib/resources/aws/aws_vpc.rb +1 -1
- data/lib/resources/aws/aws_vpcs.rb +3 -2
- data/lib/resources/azure/azure_generic_resource.rb +4 -4
- data/lib/resources/azure/azure_resource_group.rb +1 -0
- data/lib/resources/azure/azure_virtual_machine_data_disk.rb +13 -12
- data/lib/source_readers/flat.rb +1 -0
- data/lib/source_readers/inspec.rb +1 -0
- metadata +2 -2
data/lib/inspec/utils/filter.rb
CHANGED
@@ -66,12 +66,14 @@ module FilterTable
|
|
66
66
|
def self.to_ruby(trace)
|
67
67
|
chain = trace.instance_variable_get(:@chain)
|
68
68
|
return "" if chain.empty?
|
69
|
+
|
69
70
|
" " + chain.map do |el|
|
70
71
|
m = el[0][0]
|
71
72
|
args = el[0].drop(1)
|
72
73
|
nxt = to_ruby(el[1])
|
73
74
|
next m.to_s + nxt if args.empty?
|
74
75
|
next m.to_s + " " + args[0].inspect + nxt if args.length == 1
|
76
|
+
|
75
77
|
m.to_s + "(" + args.map(&:inspect).join(", ") + ")" + nxt
|
76
78
|
end.join(" ")
|
77
79
|
end
|
@@ -91,7 +93,7 @@ module FilterTable
|
|
91
93
|
# block; then construct a new Table of the same class as ourselves,
|
92
94
|
# wrapping the filtered data, and return it.
|
93
95
|
def where(conditions = {}, &block)
|
94
|
-
return self
|
96
|
+
return self unless conditions.is_a?(Hash)
|
95
97
|
return self if conditions.empty? && !block_given?
|
96
98
|
|
97
99
|
# Initialize the details of the new Table.
|
@@ -101,7 +103,8 @@ module FilterTable
|
|
101
103
|
# If we were provided params, interpret them as criteria to be evaluated
|
102
104
|
# against the raw data. Criteria are assumed to be hash keys.
|
103
105
|
conditions.each do |raw_field_name, desired_value|
|
104
|
-
raise(ArgumentError, "'#{decorate_symbols(raw_field_name)}' is not a recognized criterion - expected one of #{decorate_symbols(list_fields).join(
|
106
|
+
raise(ArgumentError, "'#{decorate_symbols(raw_field_name)}' is not a recognized criterion - expected one of #{decorate_symbols(list_fields).join(", ")}'") unless field?(raw_field_name)
|
107
|
+
|
105
108
|
populate_lazy_field(raw_field_name, desired_value) if is_field_lazy?(raw_field_name)
|
106
109
|
new_criteria_string += " #{raw_field_name} == #{desired_value.inspect}"
|
107
110
|
filtered_raw_data = filter_raw_data(filtered_raw_data, raw_field_name, desired_value)
|
@@ -190,8 +193,10 @@ module FilterTable
|
|
190
193
|
def populate_lazy_field(field_name, criterion)
|
191
194
|
return unless is_field_lazy?(field_name)
|
192
195
|
return if field_populated?(field_name)
|
196
|
+
|
193
197
|
raw_data.each do |row|
|
194
198
|
next if row.key?(field_name) # skip row if pre-existing data is present
|
199
|
+
|
195
200
|
callback_for_lazy_field(field_name).call(row, criterion, self)
|
196
201
|
end
|
197
202
|
mark_lazy_field_populated(field_name)
|
@@ -206,6 +211,7 @@ module FilterTable
|
|
206
211
|
|
207
212
|
def callback_for_lazy_field(field_name)
|
208
213
|
return unless is_field_lazy?(field_name)
|
214
|
+
|
209
215
|
custom_properties_schema.values.find do |property_struct|
|
210
216
|
property_struct.field_name == field_name
|
211
217
|
end.opts[:lazy]
|
@@ -224,17 +230,20 @@ module FilterTable
|
|
224
230
|
def matches_float(x, y)
|
225
231
|
return false if x.nil?
|
226
232
|
return false if !x.is_a?(Float) && (x =~ /\A[-+]?(\d+\.?\d*|\.\d+)\z/).nil?
|
233
|
+
|
227
234
|
x.to_f == y
|
228
235
|
end
|
229
236
|
|
230
237
|
def matches_int(x, y)
|
231
238
|
return false if x.nil?
|
232
239
|
return false if !x.is_a?(Integer) && (x =~ /\A[-+]?\d+\z/).nil?
|
240
|
+
|
233
241
|
x.to_i == y
|
234
242
|
end
|
235
243
|
|
236
244
|
def matches_regex(x, y)
|
237
245
|
return x == y if x.is_a?(Regexp)
|
246
|
+
|
238
247
|
!x.to_s.match(y).nil?
|
239
248
|
end
|
240
249
|
|
@@ -257,6 +266,7 @@ module FilterTable
|
|
257
266
|
|
258
267
|
current_raw_data.find_all do |row|
|
259
268
|
next unless row.key?(field)
|
269
|
+
|
260
270
|
send(method_ref, row[field], desired_value)
|
261
271
|
end
|
262
272
|
end
|
@@ -265,6 +275,7 @@ module FilterTable
|
|
265
275
|
return thing.map { |t| decorate_symbols(t) } if thing.is_a?(Array)
|
266
276
|
return ":" + thing.to_s if thing.is_a? Symbol
|
267
277
|
return thing + " (String)" if thing.is_a? String
|
278
|
+
|
268
279
|
thing
|
269
280
|
end
|
270
281
|
end
|
@@ -273,7 +284,7 @@ module FilterTable
|
|
273
284
|
CustomPropertyType = Struct.new(:field_name, :block, :opts)
|
274
285
|
|
275
286
|
def initialize
|
276
|
-
@filter_methods =
|
287
|
+
@filter_methods = %i{where entries raw_data}
|
277
288
|
@custom_properties = {}
|
278
289
|
register_custom_matcher(:exist?) { |table| !table.raw_data.empty? }
|
279
290
|
register_custom_property(:count) { |table| table.raw_data.count }
|
@@ -313,6 +324,7 @@ module FilterTable
|
|
313
324
|
# Install a method that can wrap all the fields into a context with accessors
|
314
325
|
define_method :create_eval_context_for_row do |row_as_hash, criteria_string = ""|
|
315
326
|
return row_eval_context_type.new if row_as_hash.nil?
|
327
|
+
|
316
328
|
context = row_eval_context_type.new(*non_block_struct_fields.map { |field| row_as_hash[field] })
|
317
329
|
context.criteria_string = criteria_string
|
318
330
|
context.filter_table = self
|
@@ -330,6 +342,7 @@ module FilterTable
|
|
330
342
|
# a setter for each field.
|
331
343
|
@custom_properties.values.each do |property_info|
|
332
344
|
next unless property_info.opts[:lazy]
|
345
|
+
|
333
346
|
field_name = property_info.field_name.to_sym
|
334
347
|
row_eval_context_type.send(:define_method, field_name) do
|
335
348
|
unless filter_table.field_populated?(field_name)
|
data/lib/inspec/utils/parser.rb
CHANGED
@@ -8,6 +8,7 @@ module PasswdParser
|
|
8
8
|
def parse_passwd(content)
|
9
9
|
content.to_s.split("\n").map do |line|
|
10
10
|
next if line[0] == "#"
|
11
|
+
|
11
12
|
parse_passwd_line(line)
|
12
13
|
end.compact
|
13
14
|
end
|
@@ -224,6 +225,7 @@ module XinetdParser
|
|
224
225
|
|
225
226
|
def parse_xinetd(raw) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
226
227
|
return {} if raw.nil?
|
228
|
+
|
227
229
|
res = {}
|
228
230
|
cur_group = nil
|
229
231
|
simple_conf = []
|
@@ -26,7 +26,7 @@ class SimpleConfig
|
|
26
26
|
return if raw_data.nil?
|
27
27
|
|
28
28
|
# prepare raw data if required
|
29
|
-
|
29
|
+
unless options[:line_separator].nil?
|
30
30
|
raw_data = raw_data.tr(options[:line_separator], "\n")
|
31
31
|
end
|
32
32
|
rest = raw_data
|
@@ -67,8 +67,10 @@ class SimpleConfig
|
|
67
67
|
|
68
68
|
def parse_group_line(line, opts)
|
69
69
|
return nil if opts[:group_re].nil?
|
70
|
+
|
70
71
|
m = opts[:group_re].match(line)
|
71
72
|
return nil if m.nil?
|
73
|
+
|
72
74
|
@groups.push(m[1])
|
73
75
|
|
74
76
|
# We use a Hashie::Mash to provide method syntax for retrieving
|
@@ -81,6 +83,7 @@ class SimpleConfig
|
|
81
83
|
|
82
84
|
def parse_implicit_assignment_line(line, opts)
|
83
85
|
return nil if is_empty_line(line)
|
86
|
+
|
84
87
|
if opts[:multiple_values]
|
85
88
|
@vals[line.strip] ||= []
|
86
89
|
else
|
data/lib/inspec/version.rb
CHANGED
data/lib/matchers/matchers.rb
CHANGED
@@ -221,6 +221,7 @@ RSpec::Matchers.define :cmp do |first_expected| # rubocop:disable Metrics/BlockL
|
|
221
221
|
|
222
222
|
def octal?(value)
|
223
223
|
return false unless value.is_a?(String)
|
224
|
+
|
224
225
|
!(value =~ /\A0+[0-7]+\Z/).nil?
|
225
226
|
end
|
226
227
|
|
@@ -274,11 +275,12 @@ RSpec::Matchers.define :cmp do |first_expected| # rubocop:disable Metrics/BlockL
|
|
274
275
|
@operation ||= :==
|
275
276
|
@expected ||= first_expected
|
276
277
|
return actual === @expected if @operation == :=== # rubocop:disable Style/CaseEquality
|
278
|
+
|
277
279
|
actual = actual[0] if actual.is_a?(Array) && !@expected.is_a?(Array) && actual.length == 1
|
278
280
|
try_match(actual, @operation, @expected)
|
279
281
|
end
|
280
282
|
|
281
|
-
|
283
|
+
%i{== != < <= >= > === =~}.each do |op|
|
282
284
|
chain(op) do |x|
|
283
285
|
@operation = op
|
284
286
|
@expected = x
|
@@ -287,6 +289,7 @@ RSpec::Matchers.define :cmp do |first_expected| # rubocop:disable Metrics/BlockL
|
|
287
289
|
|
288
290
|
def format_expectation(negate)
|
289
291
|
return "expected: " + @expected.inspect if @operation == :== && !negate
|
292
|
+
|
290
293
|
negate_str = negate ? "not " : ""
|
291
294
|
"expected it #{negate_str}to be #{@operation} #{@expected.inspect}"
|
292
295
|
end
|
@@ -29,11 +29,11 @@ module InspecPlugins
|
|
29
29
|
def self.keygen(options)
|
30
30
|
key = KEY_ALG.new KEY_BITS
|
31
31
|
puts "Generating private key"
|
32
|
-
open "#{options[
|
32
|
+
open "#{options["keyname"]}.pem.key", "w" do |io|
|
33
33
|
io.write key.to_pem
|
34
34
|
end
|
35
35
|
puts "Generating public key"
|
36
|
-
open "#{options[
|
36
|
+
open "#{options["keyname"]}.pem.pub", "w" do |io|
|
37
37
|
io.write key.public_key.to_pem
|
38
38
|
end
|
39
39
|
end
|
@@ -41,13 +41,13 @@ module InspecPlugins
|
|
41
41
|
def self.profile_sign(options)
|
42
42
|
artifact = new
|
43
43
|
Dir.mktmpdir do |workdir|
|
44
|
-
puts "Signing #{options[
|
44
|
+
puts "Signing #{options["profile"]} with key #{options["keyname"]}"
|
45
45
|
path_to_profile = options["profile"]
|
46
46
|
profile_md = artifact.read_profile_metadata(path_to_profile)
|
47
|
-
artifact_filename = "#{profile_md[
|
47
|
+
artifact_filename = "#{profile_md["name"]}-#{profile_md["version"]}.#{SIGNED_PROFILE_SUFFIX}"
|
48
48
|
tarfile = artifact.profile_compress(path_to_profile, profile_md, workdir)
|
49
49
|
content = IO.binread(tarfile)
|
50
|
-
signing_key = KEY_ALG.new File.read "#{options[
|
50
|
+
signing_key = KEY_ALG.new File.read "#{options["keyname"]}.pem.key"
|
51
51
|
sha = ARTIFACT_DIGEST.new
|
52
52
|
signature = signing_key.sign sha, content
|
53
53
|
# convert the signature to Base64
|
@@ -93,17 +93,18 @@ module InspecPlugins
|
|
93
93
|
begin
|
94
94
|
p = Pathname.new(path_to_profile)
|
95
95
|
p = p.join("inspec.yml")
|
96
|
-
|
96
|
+
unless p.exist?
|
97
97
|
raise "#{path_to_profile} doesn't appear to be a valid #{PRODUCT_NAME} profile"
|
98
98
|
end
|
99
|
+
|
99
100
|
yaml = YAML.load_file(p.to_s)
|
100
101
|
yaml = yaml.to_hash
|
101
102
|
|
102
|
-
|
103
|
+
unless yaml.key? "name"
|
103
104
|
raise "Profile is invalid, name is not defined"
|
104
105
|
end
|
105
106
|
|
106
|
-
|
107
|
+
unless yaml.key? "version"
|
107
108
|
raise "Profile is invalid, version is not defined"
|
108
109
|
end
|
109
110
|
rescue => e
|
@@ -125,12 +126,12 @@ module InspecPlugins
|
|
125
126
|
def valid_header?(file_alg, file_version, file_keyname)
|
126
127
|
public_keyfile = "#{file_keyname}.pem.pub"
|
127
128
|
puts "Looking for #{public_keyfile} to verify artifact"
|
128
|
-
|
129
|
+
unless File.exist? public_keyfile
|
129
130
|
raise "Can't find #{public_keyfile}"
|
130
131
|
end
|
131
132
|
|
132
|
-
raise "Invalid artifact digest algorithm detected"
|
133
|
-
raise "Invalid artifact version detected"
|
133
|
+
raise "Invalid artifact digest algorithm detected" unless VALID_PROFILE_DIGESTS.member?(file_alg)
|
134
|
+
raise "Invalid artifact version detected" unless VALID_PROFILE_VERSIONS.member?(file_version)
|
134
135
|
end
|
135
136
|
|
136
137
|
def verify(file_to_verifiy, &content_block)
|
@@ -11,7 +11,7 @@ class ArtifactCli < Minitest::Test
|
|
11
11
|
|
12
12
|
def test_generating_archive_keys
|
13
13
|
Dir.mktmpdir do |dir|
|
14
|
-
unique_key_name = SecureRandom.uuid
|
14
|
+
unique_key_name = SecureRandom.uuid
|
15
15
|
out = run_inspec_process("artifact generate --keyname #{unique_key_name}", prefix: "cd #{dir} &&")
|
16
16
|
assert_equal 0, out.exit_status
|
17
17
|
|
@@ -23,8 +23,8 @@ class ArtifactCli < Minitest::Test
|
|
23
23
|
|
24
24
|
def test_verify_and_install_signed_profile
|
25
25
|
Dir.mktmpdir do |dir|
|
26
|
-
unique_key_name = SecureRandom.uuid
|
27
|
-
install_dir = File.join(dir, SecureRandom.uuid
|
26
|
+
unique_key_name = SecureRandom.uuid
|
27
|
+
install_dir = File.join(dir, SecureRandom.uuid)
|
28
28
|
FileUtils.mkdir(install_dir)
|
29
29
|
|
30
30
|
# create profile
|
@@ -27,13 +27,13 @@ module InspecPlugins
|
|
27
27
|
|
28
28
|
# Chef Compliance
|
29
29
|
if is_compliance_server?(config)
|
30
|
-
url = "#{config[
|
30
|
+
url = "#{config["server"]}/user/compliance"
|
31
31
|
# Chef Automate2
|
32
32
|
elsif is_automate2_server?(config)
|
33
|
-
url = "#{config[
|
33
|
+
url = "#{config["server"]}/compliance/profiles/search"
|
34
34
|
# Chef Automate
|
35
35
|
elsif is_automate_server?(config)
|
36
|
-
url = "#{config[
|
36
|
+
url = "#{config["server"]}/profiles/#{owner}"
|
37
37
|
else
|
38
38
|
raise ServerConfigurationMissing
|
39
39
|
end
|
@@ -122,15 +122,15 @@ module InspecPlugins
|
|
122
122
|
def self.upload(config, owner, profile_name, archive_path)
|
123
123
|
# Chef Compliance
|
124
124
|
if is_compliance_server?(config)
|
125
|
-
url = "#{config[
|
125
|
+
url = "#{config["server"]}/owners/#{owner}/compliance/#{profile_name}/tar"
|
126
126
|
# Chef Automate pre 0.8.0
|
127
127
|
elsif is_automate_server_pre_080?(config)
|
128
|
-
url = "#{config[
|
128
|
+
url = "#{config["server"]}/#{owner}"
|
129
129
|
elsif is_automate2_server?(config)
|
130
|
-
url = "#{config[
|
130
|
+
url = "#{config["server"]}/compliance/profiles?owner=#{owner}"
|
131
131
|
# Chef Automate
|
132
132
|
else
|
133
|
-
url = "#{config[
|
133
|
+
url = "#{config["server"]}/profiles/#{owner}"
|
134
134
|
end
|
135
135
|
|
136
136
|
headers = get_headers(config)
|
@@ -209,6 +209,7 @@ module InspecPlugins
|
|
209
209
|
|
210
210
|
def self.get_token(config)
|
211
211
|
return config["token"] unless config["refresh_token"]
|
212
|
+
|
212
213
|
_success, _msg, token = get_token_via_refresh_token(config["server"], config["refresh_token"], config["insecure"])
|
213
214
|
token
|
214
215
|
end
|
@@ -216,13 +217,13 @@ module InspecPlugins
|
|
216
217
|
def self.target_url(config, profile)
|
217
218
|
owner, id, ver = profile_split(profile)
|
218
219
|
|
219
|
-
return "#{config[
|
220
|
-
return "#{config[
|
220
|
+
return "#{config["server"]}/compliance/profiles/tar" if is_automate2_server?(config)
|
221
|
+
return "#{config["server"]}/owners/#{owner}/compliance/#{id}/tar" unless is_automate_server?(config)
|
221
222
|
|
222
223
|
if ver.nil?
|
223
|
-
"#{config[
|
224
|
+
"#{config["server"]}/profiles/#{owner}/#{id}/tar"
|
224
225
|
else
|
225
|
-
"#{config[
|
226
|
+
"#{config["server"]}/profiles/#{owner}/#{id}/version/#{ver}/tar"
|
226
227
|
end
|
227
228
|
end
|
228
229
|
|
@@ -249,6 +250,7 @@ module InspecPlugins
|
|
249
250
|
def self.is_automate_server_pre_080?(config)
|
250
251
|
# Automate versions before 0.8.x do not have a valid version in the config
|
251
252
|
return false unless config["server_type"] == "automate"
|
253
|
+
|
252
254
|
server_version_from_config(config).nil?
|
253
255
|
end
|
254
256
|
|
@@ -256,6 +258,7 @@ module InspecPlugins
|
|
256
258
|
# Automate versions 0.8.x and later will have a "version" key in the config
|
257
259
|
# that is properly parsed out via server_version_from_config below
|
258
260
|
return false unless config["server_type"] == "automate"
|
261
|
+
|
259
262
|
!server_version_from_config(config).nil?
|
260
263
|
end
|
261
264
|
|
@@ -272,6 +275,7 @@ module InspecPlugins
|
|
272
275
|
# that looks like: "version":{"api":"compliance","version":"0.8.24"}
|
273
276
|
return nil unless config.key?("version")
|
274
277
|
return nil unless config["version"].is_a?(Hash)
|
278
|
+
|
275
279
|
config["version"]["version"]
|
276
280
|
end
|
277
281
|
|
@@ -11,7 +11,7 @@ module InspecPlugins
|
|
11
11
|
def login(options)
|
12
12
|
raise ArgumentError, "Please specify a server using `#{EXEC_NAME} compliance login https://SERVER`" unless options["server"]
|
13
13
|
|
14
|
-
options["server"] = URI("https://#{options[
|
14
|
+
options["server"] = URI("https://#{options["server"]}").to_s if URI(options["server"]).scheme.nil?
|
15
15
|
|
16
16
|
options["server_type"] = InspecPlugins::Compliance::API.determine_server_type(options["server"], options["insecure"])
|
17
17
|
|
@@ -23,7 +23,7 @@ module InspecPlugins
|
|
23
23
|
when :compliance
|
24
24
|
Login::ComplianceServer.login(options)
|
25
25
|
else
|
26
|
-
raise CannotDetermineServerType, "Unable to determine if #{options[
|
26
|
+
raise CannotDetermineServerType, "Unable to determine if #{options["server"]} is a #{AUTOMATE_PRODUCT_NAME} or #{COMPLIANCE_PRODUCT_NAME} server"
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
@@ -143,6 +143,7 @@ module InspecPlugins
|
|
143
143
|
)
|
144
144
|
|
145
145
|
raise msg unless success
|
146
|
+
|
146
147
|
compliance_store_access_token(options, token)
|
147
148
|
end
|
148
149
|
|
@@ -154,6 +155,7 @@ module InspecPlugins
|
|
154
155
|
)
|
155
156
|
|
156
157
|
raise msg unless success
|
158
|
+
|
157
159
|
compliance_store_access_token(options, token)
|
158
160
|
end
|
159
161
|
|
@@ -37,7 +37,7 @@ module InspecPlugins
|
|
37
37
|
options["server"] = server
|
38
38
|
InspecPlugins::Compliance::API.login(options)
|
39
39
|
config = InspecPlugins::Compliance::Configuration.new
|
40
|
-
puts "Stored configuration for Chef #{config[
|
40
|
+
puts "Stored configuration for Chef #{config["server_type"].capitalize}: #{config["server"]}' with user: '#{config["user"]}'"
|
41
41
|
end
|
42
42
|
|
43
43
|
desc "profiles", "list all available profiles in #{COMPLIANCE_PRODUCT_NAME}"
|
@@ -45,7 +45,7 @@ module InspecPlugins
|
|
45
45
|
desc: "owner whose profiles to list"
|
46
46
|
def profiles
|
47
47
|
config = InspecPlugins::Compliance::Configuration.new
|
48
|
-
return
|
48
|
+
return unless loggedin(config)
|
49
49
|
|
50
50
|
# set owner to config
|
51
51
|
config["owner"] = options["owner"] || config["user"]
|
@@ -57,7 +57,7 @@ module InspecPlugins
|
|
57
57
|
headline("Available profiles:")
|
58
58
|
profiles.each do |profile|
|
59
59
|
owner = profile["owner_id"] || profile["owner"]
|
60
|
-
li("#{profile[
|
60
|
+
li("#{profile["title"]} v#{profile["version"]} (#{mark_text(owner + "/" + profile["name"])})")
|
61
61
|
end
|
62
62
|
else
|
63
63
|
puts msg if msg != "success"
|
@@ -73,7 +73,8 @@ module InspecPlugins
|
|
73
73
|
exec_options
|
74
74
|
def exec(*tests)
|
75
75
|
config = InspecPlugins::Compliance::Configuration.new
|
76
|
-
return
|
76
|
+
return unless loggedin(config)
|
77
|
+
|
77
78
|
o = opts(:exec).dup
|
78
79
|
diagnose(o)
|
79
80
|
configure_logger(o)
|
@@ -98,7 +99,7 @@ module InspecPlugins
|
|
98
99
|
configure_logger(o)
|
99
100
|
|
100
101
|
config = InspecPlugins::Compliance::Configuration.new
|
101
|
-
return
|
102
|
+
return unless loggedin(config)
|
102
103
|
|
103
104
|
profile_name = InspecPlugins::Compliance::API.sanitize_profile_name(profile_name)
|
104
105
|
if InspecPlugins::Compliance::API.exist?(config, profile_name)
|
@@ -127,7 +128,7 @@ module InspecPlugins
|
|
127
128
|
desc: "Owner that should own the profile"
|
128
129
|
def upload(path) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, PerceivedComplexity, Metrics/CyclomaticComplexity
|
129
130
|
config = InspecPlugins::Compliance::Configuration.new
|
130
|
-
return
|
131
|
+
return unless loggedin(config)
|
131
132
|
|
132
133
|
# set owner to config
|
133
134
|
config["owner"] = options["owner"] || config["user"]
|
@@ -177,7 +178,7 @@ module InspecPlugins
|
|
177
178
|
|
178
179
|
# check that the profile is not uploaded already,
|
179
180
|
# confirm upload to the user (overwrite with --force)
|
180
|
-
if InspecPlugins::Compliance::API.exist?(config, "#{config[
|
181
|
+
if InspecPlugins::Compliance::API.exist?(config, "#{config["owner"]}/#{profile_name}##{profile_version}") && !options["overwrite"]
|
181
182
|
error.call("Profile exists on the server, use --overwrite")
|
182
183
|
end
|
183
184
|
|
@@ -198,7 +199,7 @@ module InspecPlugins
|
|
198
199
|
archive_path = path
|
199
200
|
end
|
200
201
|
|
201
|
-
puts "Start upload to #{config[
|
202
|
+
puts "Start upload to #{config["owner"]}/#{profile_name}"
|
202
203
|
pname = ERB::Util.url_encode(profile_name)
|
203
204
|
|
204
205
|
if InspecPlugins::Compliance::API.is_automate_server?(config) || InspecPlugins::Compliance::API.is_automate2_server?(config)
|
@@ -225,8 +226,8 @@ module InspecPlugins
|
|
225
226
|
config = InspecPlugins::Compliance::Configuration.new
|
226
227
|
info = InspecPlugins::Compliance::API.version(config)
|
227
228
|
if !info.nil? && info["version"]
|
228
|
-
puts "Name: #{info[
|
229
|
-
puts "Version: #{info[
|
229
|
+
puts "Name: #{info["api"]}"
|
230
|
+
puts "Version: #{info["version"]}"
|
230
231
|
else
|
231
232
|
puts "Could not determine server version."
|
232
233
|
exit 1
|
@@ -241,7 +242,7 @@ module InspecPlugins
|
|
241
242
|
config = InspecPlugins::Compliance::Configuration.new
|
242
243
|
unless config.supported?(:oidc) || config["token"].nil? || config["server_type"] == "automate"
|
243
244
|
config = InspecPlugins::Compliance::Configuration.new
|
244
|
-
url = "#{config[
|
245
|
+
url = "#{config["server"]}/logout"
|
245
246
|
InspecPlugins::Compliance::HTTP.post(url, config["token"], config["insecure"], !config.supported?(:oidc))
|
246
247
|
end
|
247
248
|
success = config.destroy
|
@@ -257,7 +258,7 @@ module InspecPlugins
|
|
257
258
|
|
258
259
|
def loggedin(config)
|
259
260
|
serverknown = !config["server"].nil?
|
260
|
-
puts "You need to login first with `#{EXEC_NAME} compliance login`"
|
261
|
+
puts "You need to login first with `#{EXEC_NAME} compliance login`" unless serverknown
|
261
262
|
serverknown
|
262
263
|
end
|
263
264
|
end
|