inspec-core 6.8.24 → 7.0.95

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.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +8 -8
  3. data/etc/deprecations.json +42 -4
  4. data/inspec-core.gemspec +14 -7
  5. data/lib/inspec/archive/tar.rb +1 -0
  6. data/lib/inspec/backend.rb +2 -0
  7. data/lib/inspec/base_cli.rb +15 -2
  8. data/lib/inspec/cached_fetcher.rb +17 -1
  9. data/lib/inspec/cli.rb +2 -0
  10. data/lib/inspec/dependencies/cache.rb +47 -7
  11. data/lib/inspec/dsl.rb +44 -10
  12. data/lib/inspec/exceptions.rb +1 -0
  13. data/lib/inspec/fetcher/gem.rb +117 -0
  14. data/lib/inspec/fetcher/git.rb +21 -1
  15. data/lib/inspec/fetcher/local.rb +1 -1
  16. data/lib/inspec/fetcher.rb +1 -0
  17. data/lib/inspec/file_provider.rb +47 -1
  18. data/lib/inspec/metadata.rb +2 -0
  19. data/lib/inspec/plugin/v2/concerns/gem_spec_helper.rb +30 -0
  20. data/lib/inspec/plugin/v2/gem_source_manager.rb +50 -0
  21. data/lib/inspec/plugin/v2/installer.rb +65 -18
  22. data/lib/inspec/plugin/v2/loader.rb +37 -6
  23. data/lib/inspec/plugin/v2/plugin_types/resource_pack.rb +8 -0
  24. data/lib/inspec/plugin/v2.rb +1 -0
  25. data/lib/inspec/profile.rb +22 -3
  26. data/lib/inspec/profile_context.rb +10 -0
  27. data/lib/inspec/resources/audit_policy.rb +8 -2
  28. data/lib/inspec/resources/groups.rb +52 -0
  29. data/lib/inspec/resources.rb +0 -14
  30. data/lib/inspec/rule.rb +2 -0
  31. data/lib/inspec/runner.rb +7 -1
  32. data/lib/inspec/source_reader.rb +2 -0
  33. data/lib/inspec/ui.rb +1 -0
  34. data/lib/inspec/utils/deprecated_core_resources_list.rb +2 -2
  35. data/lib/inspec/utils/deprecation/config_file.rb +39 -3
  36. data/lib/inspec/utils/deprecation/deprecator.rb +10 -3
  37. data/lib/inspec/utils/simpleconfig.rb +2 -0
  38. data/lib/inspec/utils/telemetry/run_context_probe.rb +5 -2
  39. data/lib/inspec/version.rb +1 -1
  40. data/lib/inspec/waiver_file_reader.rb +35 -18
  41. data/lib/inspec.rb +2 -0
  42. data/lib/plugins/inspec-plugin-manager-cli/lib/inspec-plugin-manager-cli/cli_command.rb +1 -1
  43. data/lib/plugins/shared/core_plugin_test_helper.rb +1 -1
  44. data/lib/source_readers/gem.rb +67 -0
  45. metadata +82 -43
  46. data/lib/inspec/resources/docker.rb +0 -274
  47. data/lib/inspec/resources/docker_container.rb +0 -116
  48. data/lib/inspec/resources/docker_image.rb +0 -141
  49. data/lib/inspec/resources/docker_object.rb +0 -52
  50. data/lib/inspec/resources/docker_plugin.rb +0 -68
  51. data/lib/inspec/resources/docker_service.rb +0 -95
  52. data/lib/inspec/resources/elasticsearch.rb +0 -165
  53. data/lib/inspec/resources/ibmdb2_conf.rb +0 -65
  54. data/lib/inspec/resources/ibmdb2_session.rb +0 -78
  55. data/lib/inspec/resources/mongodb.rb +0 -69
  56. data/lib/inspec/resources/mongodb_conf.rb +0 -44
  57. data/lib/inspec/resources/mongodb_session.rb +0 -98
  58. data/lib/inspec/resources/opa.rb +0 -26
  59. data/lib/inspec/resources/opa_api.rb +0 -49
  60. data/lib/inspec/resources/opa_cli.rb +0 -57
  61. data/lib/inspec/resources/podman.rb +0 -353
  62. data/lib/inspec/resources/podman_container.rb +0 -84
  63. data/lib/inspec/resources/podman_image.rb +0 -108
  64. data/lib/inspec/resources/podman_network.rb +0 -81
  65. data/lib/inspec/resources/podman_pod.rb +0 -101
  66. data/lib/inspec/resources/podman_volume.rb +0 -87
  67. data/lib/inspec/resources/rabbitmq_conf.rb +0 -2
  68. data/lib/inspec/resources/rabbitmq_config.rb +0 -56
  69. data/lib/inspec/resources/sybase_conf.rb +0 -41
  70. data/lib/inspec/resources/sybase_session.rb +0 -124
  71. data/lib/inspec/utils/podman.rb +0 -24
@@ -1,101 +0,0 @@
1
- require "inspec/resources/command"
2
- require "inspec/utils/podman"
3
-
4
- module Inspec::Resources
5
- class PodmanPod < Inspec.resource(1)
6
- include Inspec::Utils::Podman
7
-
8
- name "podman_pod"
9
- supports platform: "unix"
10
-
11
- desc "InSpec core resource to retrieve information about podman pod"
12
-
13
- example <<~EXAMPLE
14
- describe podman_pod("nginx-frontend") do
15
- it { should exist }
16
- its("id") { should eq "fcfe4d471cfface0d1b39bce23af7d31ab8736cd68c0360ade0b4afe364f79d4" }
17
- its("name") { should eq "nginx-frontend" }
18
- its("created_at") { should eq "2022-07-14T15:47:47.978078124+05:30" }
19
- its("create_command") { should include "new:nginx-frontend" }
20
- its("state") { should eq "Running" }
21
- its("hostname") { should eq "" }
22
- its("create_cgroup") { should eq true }
23
- its("cgroup_parent") { should eq "user.slice" }
24
- its("cgroup_path") { should eq "user.slice/user-libpod_pod_fcfe4d471cfface0d1b39bce23af7d31ab8736cd68c0360ade0b4afe364f79d4.slice" }
25
- its("create_infra") { should eq true }
26
- its("infra_container_id") { should eq "727538044b32a165934729dc2d47d9d5e981b6496aebfad7de470f7e76ea4251" }
27
- its("infra_config") { should include "DNSOption" }
28
- its("shared_namespaces") { should include "ipc" }
29
- its("num_containers") { should eq 2 }
30
- its("containers") { should_not be nil }
31
- end
32
-
33
- describe podman_pod("non-existing-pod") do
34
- it { should_not exist }
35
- end
36
- EXAMPLE
37
-
38
- attr_reader :pod_info, :pod_id
39
-
40
- def initialize(pod_id)
41
- skip_resource "The `podman_pod` resource is not yet available on your OS." unless inspec.os.unix?
42
- raise Inspec::Exceptions::ResourceFailed, "Podman is not running. Please make sure it is installed and running." unless podman_running?
43
-
44
- @pod_id = pod_id
45
- @pod_info = get_pod_info
46
- end
47
-
48
- LABELS = {
49
- "id" => "ID",
50
- "name" => "Name",
51
- "created_at" => "Created",
52
- "create_command" => "CreateCommand",
53
- "state" => "State",
54
- "hostname" => "Hostname",
55
- "create_cgroup" => "CreateCgroup",
56
- "cgroup_parent" => "CgroupParent",
57
- "cgroup_path" => "CgroupPath",
58
- "create_infra" => "CreateInfra",
59
- "infra_container_id" => "InfraContainerID",
60
- "infra_config" => "InfraConfig",
61
- "shared_namespaces" => "SharedNamespaces",
62
- "num_containers" => "NumContainers",
63
- "containers" => "Containers",
64
- }.freeze
65
-
66
- # This creates all the required properties methods dynamically.
67
- LABELS.each do |k, _|
68
- define_method(k) do
69
- pod_info[k.to_s]
70
- end
71
- end
72
-
73
- def exist?
74
- !pod_info.empty?
75
- end
76
-
77
- def resource_id
78
- pod_id
79
- end
80
-
81
- def to_s
82
- "Podman Pod #{resource_id}"
83
- end
84
-
85
- private
86
-
87
- def get_pod_info
88
- json_key_label = generate_go_template(LABELS)
89
-
90
- inspect_pod_cmd = inspec.command("podman pod inspect #{pod_id} --format '{#{json_key_label}}'")
91
-
92
- if inspect_pod_cmd.exit_status == 0
93
- parse_command_output(inspect_pod_cmd.stdout)
94
- elsif inspect_pod_cmd.stderr =~ /no pod with name or ID/
95
- {}
96
- else
97
- raise Inspec::Exceptions::ResourceFailed, "Unable to retrieve podman pod information for #{pod_id}.\nError message: #{inspect_pod_cmd.stderr}"
98
- end
99
- end
100
- end
101
- end
@@ -1,87 +0,0 @@
1
- require "inspec/resources/command"
2
- require "inspec/utils/podman"
3
-
4
- module Inspec::Resources
5
- class PodmanVolume < Inspec.resource(1)
6
- include Inspec::Utils::Podman
7
-
8
- name "podman_volume"
9
- supports platform: "unix"
10
-
11
- desc "InSpec core resource to retrieve information about podman volume"
12
-
13
- example <<~EXAMPLE
14
- describe podman_volume("my_volume") do
15
- it { should exist }
16
- its("name") { should eq "my_volume" }
17
- its("driver") { should eq "local" }
18
- its("mountpoint") { should eq "/var/home/core/.local/share/containers/storage/volumes/my_volume/_data" }
19
- its("created_at") { should eq "2022-07-14T13:21:19.965421792+05:30" }
20
- its("labels") { should eq({}) }
21
- its("scope") { should eq "local" }
22
- its("options") { should eq({}) }
23
- its("mount_count") { should eq 0 }
24
- its("needs_copy_up") { should eq true }
25
- its("needs_chown") { should eq true }
26
- end
27
- EXAMPLE
28
-
29
- attr_reader :volume_info, :volume_name
30
-
31
- def initialize(volume_name)
32
- skip_resource "The `podman_volume` resource is not yet available on your OS." unless inspec.os.unix?
33
- raise Inspec::Exceptions::ResourceFailed, "Podman is not running. Please make sure it is installed and running." unless podman_running?
34
-
35
- @volume_name = volume_name
36
- @volume_info = get_volume_info
37
- end
38
-
39
- LABELS = {
40
- "name" => "Name",
41
- "driver" => "Driver",
42
- "mountpoint" => "Mountpoint",
43
- "created_at" => "CreatedAt",
44
- "labels" => "Labels",
45
- "scope" => "Scope",
46
- "options" => "Options",
47
- "mount_count" => "MountCount",
48
- "needs_copy_up" => "NeedsCopyUp",
49
- "needs_chown" => "NeedsChown",
50
- }.freeze
51
-
52
- # This creates all the required properties methods dynamically.
53
- LABELS.each do |k, _|
54
- define_method(k) do
55
- volume_info[k.to_s]
56
- end
57
- end
58
-
59
- def exist?
60
- !volume_info.empty?
61
- end
62
-
63
- def resource_id
64
- volume_name
65
- end
66
-
67
- def to_s
68
- "podman_volume #{resource_id}"
69
- end
70
-
71
- private
72
-
73
- def get_volume_info
74
- json_key_label = generate_go_template(LABELS)
75
-
76
- inspect_volume_cmd = inspec.command("podman volume inspect #{volume_name} --format '{#{json_key_label}}'")
77
-
78
- if inspect_volume_cmd.exit_status == 0
79
- parse_command_output(inspect_volume_cmd.stdout)
80
- elsif inspect_volume_cmd.stderr =~ /inspecting object: no such/
81
- {}
82
- else
83
- raise Inspec::Exceptions::ResourceFailed, "Unable to retrieve podman volume information for #{volume_name}.\nError message: #{inspect_volume_cmd.stderr}"
84
- end
85
- end
86
- end
87
- end
@@ -1,2 +0,0 @@
1
- # This is just here to make the dynamic loader happy.
2
- require "inspec/resources/rabbitmq_config"
@@ -1,56 +0,0 @@
1
- require "inspec/utils/erlang_parser"
2
- require "inspec/utils/file_reader"
3
-
4
- module Inspec::Resources
5
- class RabbitmqConfig < Inspec.resource(1)
6
- name "rabbitmq_conf" # TODO: this is an alias. do we want this?
7
- name "rabbitmq_config"
8
- supports platform: "unix"
9
- desc "Use the rabbitmq_config InSpec resource to test configuration data "\
10
- "for the RabbitMQ service located in /etc/rabbitmq/rabbitmq.config on "\
11
- "Linux and UNIX platforms."
12
- example <<~EXAMPLE
13
- describe rabbitmq_config.params('rabbit', 'ssl_listeners') do
14
- it { should cmp 5671 }
15
- end
16
- EXAMPLE
17
-
18
- include FileReader
19
-
20
- def initialize(conf_path = nil)
21
- @conf_path = conf_path || "/etc/rabbitmq/rabbitmq.config"
22
- @content = read_file_content(@conf_path, allow_empty: true)
23
- end
24
-
25
- def params(*opts)
26
- opts.inject(read_params) do |res, nxt|
27
- res.respond_to?(:key) ? res[nxt] : nil
28
- end
29
- end
30
-
31
- def to_s
32
- "rabbitmq_config #{@conf_path}"
33
- end
34
-
35
- def resource_id
36
- @conf_path
37
- end
38
-
39
- private
40
-
41
- def read_content
42
- return @content if defined?(@content)
43
-
44
- @content = read_file_content(@conf_path, allow_empty: true)
45
- end
46
-
47
- def read_params
48
- return @params if defined?(@params)
49
- return @params = {} if read_content.nil?
50
-
51
- @params = ErlangConfigFile.parse(read_content)
52
- rescue Parslet::ParseFailed
53
- raise "Cannot parse RabbitMQ config: \"#{read_content}\""
54
- end
55
- end
56
- end
@@ -1,41 +0,0 @@
1
- require "inspec/resources/sybase_session"
2
-
3
- module Inspec::Resources
4
- class SybaseConf < Inspec.resource(1)
5
- name "sybase_conf"
6
- supports platform: "unix"
7
- # supports platform: "windows" # TODO
8
- desc "Use the sybase_conf InSpec resource to test Sybase config settings"
9
- example <<~EXAMPLE
10
- describe sybase_conf("max memory", password: 'password', server: 'SYBASE') do
11
- its("run_value") { should cmp 180224 }
12
- end
13
- EXAMPLE
14
-
15
- attr_reader :conf_param, :sql_query
16
- def initialize(conf_param_name, opts = {})
17
- @conf_param = conf_param_name
18
- opts[:username] ||= "sa"
19
- opts[:database] ||= "master"
20
- sql_session = inspec.sybase_session(opts)
21
- @sql_query = sql_session.query("sp_configure \"#{conf_param}\"")
22
- end
23
-
24
- def run_value
25
- sql_query.row(0).column("Run Value").value
26
- end
27
-
28
- def config_value
29
- sql_query.row(0).column("Config Value").value
30
- end
31
-
32
- def resource_id
33
- conf_param || "Sybase config settings"
34
- end
35
-
36
- def to_s
37
- "Sybase Conf #{conf_param}"
38
- end
39
-
40
- end
41
- end
@@ -1,124 +0,0 @@
1
- require "inspec/resources/command"
2
- require "inspec/utils/database_helpers"
3
- require "hashie/mash"
4
- require "csv" unless defined?(CSV)
5
- require "tempfile" unless defined?(Tempfile)
6
-
7
- module Inspec::Resources
8
- # STABILITY: Experimental
9
- # This resource needs further testing and refinement
10
- #
11
- class SybaseSession < Inspec.resource(1)
12
- name "sybase_session"
13
- supports platform: "unix"
14
- # supports platform: "windows" # TODO
15
- desc "Use the sybase_session InSpec resource to test commands against an Sybase database"
16
- example <<~EXAMPLE
17
- sql = sybase_session(username: 'my_user', password: 'password', server: 'SYBASE', database: 'pubs2')
18
- describe sql.query(\"SELECT * FROM authors\").row(0).column('au_lname') do
19
- its('value') { should eq 'Smith' }
20
- end
21
- EXAMPLE
22
-
23
- # TODO: allow to set -I interfaces file
24
- # TODO: allow to customize -s column separator
25
- attr_reader :bin, :col_sep, :database, :password, :server, :sybase_home, :username
26
-
27
- def initialize(opts = {})
28
- @username = opts[:username]
29
- @password = opts[:password]
30
- @database = opts[:database]
31
- @server = opts[:server]
32
- @sybase_home = opts[:sybase_home] || "/opt/sap"
33
- @bin = opts[:bin] || "isql"
34
- @col_sep = "|"
35
-
36
- fail_resource "Can't run Sybase checks without authentication" unless username && password
37
- fail_resource "You must provide a server name for the session" unless server
38
- fail_resource "You must provide a database name for the session" unless database
39
- fail_resource "Cannot find #{bin} CLI tool" unless inspec.command(bin).exist?
40
- end
41
-
42
- def query(sql)
43
- # We must write the SQl to a temp file on the remote target
44
- # try to get a temp path
45
- sql_file_path = upload_sql_file(sql)
46
-
47
- # TODO: Find if there is better way to get the current shell
48
- current_shell = inspec.command("echo $SHELL")
49
-
50
- res = current_shell.exit_status
51
-
52
- # isql reuires that we have a matching locale set, but does not support C.UTF-8. en_US.UTF-8 is the least evil.
53
- if res == 0 && ( current_shell.stdout&.include?("/csh") || current_shell.stdout&.include?("/tcsh") )
54
- command = "source #{sybase_home}/SYBASE.csh; setenv LANG en_US.UTF-8; #{bin} -s\"#{col_sep}\" -w80000 -S #{server} -U #{username} -D #{database} -P \"#{password}\" < #{sql_file_path}"
55
- else
56
- command = "LANG=en_US.UTF-8 SYBASE=#{sybase_home} #{bin} -s\"#{col_sep}\" -w80000 -S #{server} -U #{username} -D #{database} -P \"#{password}\" < #{sql_file_path}"
57
- end
58
-
59
- isql_cmd = inspec.command(command)
60
- # Check for isql errors
61
- res = isql_cmd.exit_status
62
- raise Inspec::Exceptions::ResourceFailed.new("isql exited with code #{res} and stderr '#{isql_cmd.stderr}', stdout '#{isql_cmd.stdout}'") unless res == 0
63
- # isql is ill-behaved, and returns 0 on error
64
- raise Inspec::Exceptions::ResourceFailed.new("isql exited with error '#{isql_cmd.stderr}', stdout '#{isql_cmd.stdout}'") unless isql_cmd.stderr == ""
65
- # check stdout for error messages when stderr is empty "Msg 102, Level 15, State 181:\nServer 'SYBASE', Line 1:\nIncorrect syntax near '.'.\n"
66
- raise Inspec::Exceptions::ResourceFailed.new("isql exited with error #{isql_cmd.stdout}") if isql_cmd.stdout.match?(/Msg\s\d+,\sLevel\s\d+,\sState\s\d+/)
67
-
68
- # Clean up temporary file
69
- rm_cmd = inspec.command("rm #{sql_file_path}")
70
- res = rm_cmd.exit_status # TODO: handle
71
- raise Inspec::Exceptions::ResourceFailed.new("Unable to delete temproary SQL input file at #{sql_file_path}: #{rm_cmd.stderr}") unless res == 0
72
-
73
- DatabaseHelper::SQLQueryResult.new(isql_cmd, parse_csv_result(isql_cmd.stdout))
74
- end
75
-
76
- def resource_id
77
- @database || "Sybase Session"
78
- end
79
-
80
- def to_s
81
- "Sybase Session"
82
- end
83
-
84
- private
85
-
86
- def parse_csv_result(stdout)
87
- output = stdout.gsub(/\r/, "").strip
88
- lines = output.lines
89
- # Remove second row (all dashes) and last 2 rows (blank and summary lines)
90
- trimmed_output = ([lines[0]] << lines.slice(2..-3)).join("")
91
- header_converter = Proc.new do |header|
92
- # This is here to suppress a warning from Hashie::Mash when it encounters a
93
- # header column that ends up with the name "default", which happens when using the
94
- # sybase_conf resource. It does mean that aly query whose output field includes the name
95
- # Default (exactly) will get renamed to default_value, but that seems unlikely.
96
- if header.match?(/^Default\s+$/)
97
- "default_value"
98
- else
99
- header.downcase.strip
100
- end
101
- end
102
- field_converter = ->(field) { field&.strip }
103
- CSV.parse(trimmed_output, headers: true, header_converters: header_converter, converters: field_converter, col_sep: col_sep).map { |row| Hashie::Mash.new(row.to_h) }
104
- end
105
-
106
- def upload_sql_file(sql)
107
- remote_temp_dir = "/tmp"
108
- remote_file_path = nil
109
- local_temp_file = Tempfile.new(["sybase", ".sql"])
110
- begin
111
- local_temp_file.write("#{sql}\n")
112
- local_temp_file.write("go\n")
113
- local_temp_file.flush
114
- filename = File.basename(local_temp_file.path)
115
- remote_file_path = "#{remote_temp_dir}/#{filename}"
116
- inspec.backend.upload([local_temp_file.path], remote_temp_dir)
117
- ensure
118
- local_temp_file.close
119
- local_temp_file.unlink
120
- end
121
- remote_file_path
122
- end
123
- end
124
- end
@@ -1,24 +0,0 @@
1
- require "inspec/resources/command"
2
-
3
- module Inspec
4
- module Utils
5
- module Podman
6
- def podman_running?
7
- inspec.command("podman version").exit_status == 0
8
- end
9
-
10
- # Generates the template in this format using labels hash: "\"id\": {{json .ID}}, \"name\": {{json .Name}}",
11
- def generate_go_template(labels)
12
- (labels.map { |k, v| "\"#{k}\": {{json .#{v}}}" }).join(", ")
13
- end
14
-
15
- def parse_command_output(output)
16
- require "json" unless defined?(JSON)
17
- JSON.parse(output)
18
- rescue JSON::ParserError => _e
19
- warn "Could not parse the command output"
20
- {}
21
- end
22
- end
23
- end
24
- end