inspec 4.7.3 → 4.7.18
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/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
|