inspec-core 5.18.14 → 5.22.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +19 -17
- data/inspec-core.gemspec +22 -22
- data/lib/inspec/base_cli.rb +19 -17
- data/lib/inspec/cli.rb +27 -25
- data/lib/inspec/dependencies/dependency_set.rb +2 -2
- data/lib/inspec/dsl.rb +9 -5
- data/lib/inspec/enhanced_outcomes.rb +19 -0
- data/lib/inspec/env_printer.rb +1 -1
- data/lib/inspec/exceptions.rb +2 -0
- data/lib/inspec/formatters/base.rb +69 -16
- data/lib/inspec/plugin/v2/loader.rb +19 -8
- data/lib/inspec/plugin/v2/plugin_types/reporter.rb +1 -0
- data/lib/inspec/plugin/v2/plugin_types/streaming_reporter.rb +54 -0
- data/lib/inspec/profile.rb +9 -8
- data/lib/inspec/reporters/base.rb +1 -0
- data/lib/inspec/reporters/cli.rb +94 -3
- data/lib/inspec/reporters/json.rb +3 -1
- data/lib/inspec/reporters/yaml.rb +3 -1
- data/lib/inspec/reporters.rb +2 -1
- data/lib/inspec/resources/file.rb +1 -1
- data/lib/inspec/resources/http.rb +5 -5
- data/lib/inspec/resources/lxc.rb +65 -9
- data/lib/inspec/resources/mongodb_session.rb +5 -0
- data/lib/inspec/resources/nftables.rb +251 -0
- data/lib/inspec/resources/oracledb_session.rb +13 -4
- data/lib/inspec/resources/podman.rb +353 -0
- data/lib/inspec/resources/podman_container.rb +84 -0
- data/lib/inspec/resources/podman_image.rb +108 -0
- data/lib/inspec/resources/podman_network.rb +81 -0
- data/lib/inspec/resources/podman_pod.rb +101 -0
- data/lib/inspec/resources/podman_volume.rb +87 -0
- data/lib/inspec/resources/postgres_session.rb +2 -1
- data/lib/inspec/resources/service.rb +1 -1
- data/lib/inspec/resources.rb +1 -0
- data/lib/inspec/rule.rb +54 -17
- data/lib/inspec/run_data/control.rb +6 -0
- data/lib/inspec/run_data/statistics.rb +8 -2
- data/lib/inspec/runner.rb +18 -8
- data/lib/inspec/runner_rspec.rb +3 -2
- data/lib/inspec/schema/exec_json.rb +78 -2
- data/lib/inspec/schema/output_schema.rb +4 -1
- data/lib/inspec/schema/profile_json.rb +46 -0
- data/lib/inspec/schema.rb +91 -0
- data/lib/inspec/utils/convert.rb +8 -0
- data/lib/inspec/utils/podman.rb +24 -0
- data/lib/inspec/utils/simpleconfig.rb +10 -2
- data/lib/inspec/utils/waivers/csv_file_reader.rb +34 -0
- data/lib/inspec/utils/waivers/excel_file_reader.rb +39 -0
- data/lib/inspec/utils/waivers/json_file_reader.rb +15 -0
- data/lib/inspec/version.rb +1 -1
- data/lib/inspec/waiver_file_reader.rb +61 -0
- data/lib/matchers/matchers.rb +15 -2
- data/lib/plugins/inspec-init/templates/profiles/alicloud/README.md +27 -0
- data/lib/plugins/inspec-init/templates/profiles/alicloud/controls/example.rb +10 -0
- data/lib/plugins/inspec-init/templates/profiles/alicloud/inputs.yml +1 -0
- data/lib/plugins/inspec-init/templates/profiles/alicloud/inspec.yml +14 -0
- data/lib/plugins/inspec-reporter-html2/README.md +1 -1
- data/lib/plugins/inspec-reporter-html2/templates/body.html.erb +7 -1
- data/lib/plugins/inspec-reporter-html2/templates/control.html.erb +10 -6
- data/lib/plugins/inspec-reporter-html2/templates/default.css +12 -0
- data/lib/plugins/inspec-reporter-html2/templates/selector.html.erb +7 -1
- data/lib/plugins/inspec-sign/lib/inspec-sign/base.rb +5 -2
- data/lib/plugins/inspec-streaming-reporter-progress-bar/lib/inspec-streaming-reporter-progress-bar/streaming_reporter.rb +39 -13
- metadata +26 -9
@@ -0,0 +1,84 @@
|
|
1
|
+
require "inspec/resources/podman"
|
2
|
+
require_relative "docker_object"
|
3
|
+
|
4
|
+
# Change module if required
|
5
|
+
module Inspec::Resources
|
6
|
+
class PodmanContainer < Inspec.resource(1)
|
7
|
+
include Inspec::Resources::DockerObject
|
8
|
+
name "podman_container"
|
9
|
+
supports platform: "unix"
|
10
|
+
|
11
|
+
desc "Inspec core resource to retrieve information about podman container"
|
12
|
+
|
13
|
+
example <<~EXAMPLE
|
14
|
+
describe podman_container("sweet_mendeleev") do
|
15
|
+
it { should exist }
|
16
|
+
it { should be_running }
|
17
|
+
its("id") { should eq "591270d8d80d26671fd6ed622f367fbe19004d16e3b519c292313feb5f22e7f7" }
|
18
|
+
its("image") { should eq "docker.io/library/nginx:latest" }
|
19
|
+
its("labels") { should include "maintainer"=>"NGINX Docker Maintainers <docker-maint@nginx.com>" }
|
20
|
+
its("ports") { should eq nil }
|
21
|
+
end
|
22
|
+
|
23
|
+
describe podman_container(id: "591270d8d80d2667") do
|
24
|
+
it { should exist }
|
25
|
+
it { should be_running }
|
26
|
+
end
|
27
|
+
EXAMPLE
|
28
|
+
|
29
|
+
def initialize(opts = {})
|
30
|
+
skip_resource "The `podman_container` resource is not yet available on your OS." unless inspec.os.unix?
|
31
|
+
|
32
|
+
# if a string is provided, we expect it is the name
|
33
|
+
if opts.is_a?(String)
|
34
|
+
@opts = { name: opts }
|
35
|
+
else
|
36
|
+
@opts = opts
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def running?
|
41
|
+
status.downcase.start_with?("up") if object_info.entries.length == 1
|
42
|
+
end
|
43
|
+
|
44
|
+
def status
|
45
|
+
object_info.status[0] if object_info.entries.length == 1
|
46
|
+
end
|
47
|
+
|
48
|
+
def labels
|
49
|
+
object_info.labels
|
50
|
+
end
|
51
|
+
|
52
|
+
def ports
|
53
|
+
object_info.ports[0] if object_info.entries.length == 1
|
54
|
+
end
|
55
|
+
|
56
|
+
def command
|
57
|
+
return unless object_info.entries.length == 1
|
58
|
+
|
59
|
+
object_info.commands[0]
|
60
|
+
end
|
61
|
+
|
62
|
+
def image
|
63
|
+
object_info.images[0] if object_info.entries.length == 1
|
64
|
+
end
|
65
|
+
|
66
|
+
def resource_id
|
67
|
+
object_info.ids[0] || @opts[:id] || @opts[:name] || ""
|
68
|
+
end
|
69
|
+
|
70
|
+
def to_s
|
71
|
+
name = @opts[:name] || @opts[:id]
|
72
|
+
"Podman Container #{name}"
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def object_info
|
78
|
+
return @info if defined?(@info)
|
79
|
+
|
80
|
+
opts = @opts
|
81
|
+
@info = inspec.podman.containers.where { names == opts[:name] || (!id.nil? && !opts[:id].nil? && (id == opts[:id] || id.start_with?(opts[:id]))) }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require "inspec/resources/command"
|
2
|
+
require_relative "docker_object"
|
3
|
+
require "inspec/utils/podman"
|
4
|
+
|
5
|
+
module Inspec::Resources
|
6
|
+
class PodmanImage < Inspec.resource(1)
|
7
|
+
include Inspec::Resources::DockerObject
|
8
|
+
include Inspec::Utils::Podman
|
9
|
+
|
10
|
+
name "podman_image"
|
11
|
+
supports platform: "unix"
|
12
|
+
|
13
|
+
desc "InSpec core resource to retrieve information about podman image"
|
14
|
+
|
15
|
+
example <<~EXAMPLE
|
16
|
+
describe podman_image("docker.io/library/busybox") do
|
17
|
+
it { should exist }
|
18
|
+
its("repo_tags") { should include "docker.io/library/busybox:latest" }
|
19
|
+
its("size") { should eq 1636053 }
|
20
|
+
its("resource_id") { should eq "docker.io/library/busybox:latest" }
|
21
|
+
end
|
22
|
+
|
23
|
+
describe podman_image("docker.io/library/busybox:latest") do
|
24
|
+
it { should exist }
|
25
|
+
end
|
26
|
+
|
27
|
+
describe podman_image(repo: "docker.io/library/busybox", tag: "latest") do
|
28
|
+
it { should exist }
|
29
|
+
end
|
30
|
+
|
31
|
+
describe podman_image(id: "3c19bafed223") do
|
32
|
+
it { should exist }
|
33
|
+
end
|
34
|
+
EXAMPLE
|
35
|
+
|
36
|
+
attr_reader :opts, :image_info
|
37
|
+
|
38
|
+
def initialize(opts)
|
39
|
+
skip_resource "The `podman_image` resource is not yet available on your OS." unless inspec.os.unix?
|
40
|
+
opts = { image: opts } if opts.is_a?(String)
|
41
|
+
@opts = sanitize_options(opts)
|
42
|
+
raise Inspec::Exceptions::ResourceFailed, "Podman is not running. Please make sure it is installed and running." unless podman_running?
|
43
|
+
|
44
|
+
@image_info = get_image_info
|
45
|
+
end
|
46
|
+
|
47
|
+
LABELS = {
|
48
|
+
"id" => "ID",
|
49
|
+
"repo_tags" => "RepoTags",
|
50
|
+
"size" => "Size",
|
51
|
+
"digest" => "Digest",
|
52
|
+
"created_at" => "Created",
|
53
|
+
"version" => "Version",
|
54
|
+
"names_history" => "NamesHistory",
|
55
|
+
"repo_digests" => "RepoDigests",
|
56
|
+
"architecture" => "Architecture",
|
57
|
+
"os" => "Os",
|
58
|
+
"virtual_size" => "VirtualSize",
|
59
|
+
}.freeze
|
60
|
+
|
61
|
+
## This creates all the required properties methods dynamically.
|
62
|
+
LABELS.each do |k, v|
|
63
|
+
define_method(k) do
|
64
|
+
image_info[k.to_s]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def exist?
|
69
|
+
! image_info.empty?
|
70
|
+
end
|
71
|
+
|
72
|
+
def resource_id
|
73
|
+
opts[:id] || opts[:image] || ""
|
74
|
+
end
|
75
|
+
|
76
|
+
def to_s
|
77
|
+
"podman_image #{resource_id}"
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def sanitize_options(opts)
|
83
|
+
opts.merge!(parse_components_from_image(opts[:image]))
|
84
|
+
|
85
|
+
# assume a "latest" tag if we don't have one
|
86
|
+
opts[:tag] ||= "latest"
|
87
|
+
|
88
|
+
# Assemble/reassemble the image from the repo and tag
|
89
|
+
opts[:image] = "#{opts[:repo]}:#{opts[:tag]}" unless opts[:repo].nil?
|
90
|
+
|
91
|
+
opts
|
92
|
+
end
|
93
|
+
|
94
|
+
def get_image_info
|
95
|
+
current_image = opts[:id] || opts[:image] || opts[:repo] + ":" + opts[:tag]
|
96
|
+
json_key_label = generate_go_template(LABELS)
|
97
|
+
podman_inspect_cmd = inspec.command("podman image inspect #{current_image} --format '{#{json_key_label}}'")
|
98
|
+
|
99
|
+
if podman_inspect_cmd.exit_status == 0
|
100
|
+
parse_command_output(podman_inspect_cmd.stdout)
|
101
|
+
elsif podman_inspect_cmd.stderr =~ /failed to find image/
|
102
|
+
{}
|
103
|
+
else
|
104
|
+
raise Inspec::Exceptions::ResourceFailed, "Unable to retrieve podman image information for #{current_image}.\nError message: #{podman_inspect_cmd.stderr}"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require "inspec/resources/command"
|
2
|
+
require "inspec/utils/podman"
|
3
|
+
module Inspec::Resources
|
4
|
+
class PodmanNetwork < Inspec.resource(1)
|
5
|
+
include Inspec::Utils::Podman
|
6
|
+
|
7
|
+
name "podman_network"
|
8
|
+
|
9
|
+
supports platform: "unix"
|
10
|
+
|
11
|
+
desc "InSpec core resource to retrive information about the given Podman network"
|
12
|
+
|
13
|
+
example <<~EXAMPLE
|
14
|
+
describe podman_network("podman") do
|
15
|
+
it { should exist }
|
16
|
+
end
|
17
|
+
describe podman_network("3a7c94d937d5f3a0f1a9b1610589945aedfbe56207fd5d32fc8154aa1a8b007f") do
|
18
|
+
its("driver") { should eq bridge }
|
19
|
+
end
|
20
|
+
EXAMPLE
|
21
|
+
|
22
|
+
LABELS = {
|
23
|
+
id: "ID",
|
24
|
+
name: "Name",
|
25
|
+
driver: "Driver",
|
26
|
+
labels: "Labels",
|
27
|
+
options: "Options",
|
28
|
+
ipam_options: "IPAMOptions",
|
29
|
+
internal: "Internal",
|
30
|
+
created: "Created",
|
31
|
+
ipv6_enabled: "IPv6Enabled",
|
32
|
+
dns_enabled: "DNSEnabled",
|
33
|
+
network_interface: "NetworkInterface",
|
34
|
+
subnets: "Subnets",
|
35
|
+
}.freeze
|
36
|
+
|
37
|
+
attr_reader :param, :network_info
|
38
|
+
def initialize(param)
|
39
|
+
skip_resource "The `podman_network` resource is not yet available on your OS." unless inspec.os.unix?
|
40
|
+
|
41
|
+
@param = param
|
42
|
+
raise Inspec::Exceptions::ResourceFailed, "Podman is not running. Please make sure it is installed and running." unless podman_running?
|
43
|
+
|
44
|
+
@network_info = get_network_info
|
45
|
+
end
|
46
|
+
|
47
|
+
## This creates all the required properties methods dynamically.
|
48
|
+
LABELS.each do |k, v|
|
49
|
+
define_method(k) do
|
50
|
+
network_info[k.to_s]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def exist?
|
55
|
+
!network_info.empty?
|
56
|
+
end
|
57
|
+
|
58
|
+
def resource_id
|
59
|
+
id || param || ""
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_s
|
63
|
+
"podman_network #{resource_id}"
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def get_network_info
|
69
|
+
go_template_format = generate_go_template(LABELS)
|
70
|
+
result = inspec.command("podman network inspect #{param} --format '{#{go_template_format}}'")
|
71
|
+
|
72
|
+
if result.exit_status == 0
|
73
|
+
parse_command_output(result.stdout)
|
74
|
+
elsif result.stderr =~ /network not found/
|
75
|
+
{}
|
76
|
+
else
|
77
|
+
raise Inspec::Exceptions::ResourceFailed, "Unable to retrieve podman network information for #{param}.\nError message: #{result.stderr}"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,101 @@
|
|
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
|
@@ -0,0 +1,87 @@
|
|
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
|
@@ -81,7 +81,8 @@ module Inspec::Resources
|
|
81
81
|
# Socket path and empty host in the connection string establishes socket connection
|
82
82
|
# Socket connection only enabled for non-windows platforms
|
83
83
|
# Windows does not support unix domain sockets
|
84
|
-
|
84
|
+
option_port = @port.nil? ? "" : "-p #{@port}" # add explicit port if specified
|
85
|
+
"psql -d postgresql://#{@user}:#{@pass}@/#{dbs}?host=#{@socket_path} #{option_port} -A -t -w -c #{escaped_query(query)}"
|
85
86
|
else
|
86
87
|
# Host in connection string establishes tcp/ip connection
|
87
88
|
if inspec.os.windows?
|
@@ -646,7 +646,7 @@ module Inspec::Resources
|
|
646
646
|
return nil if srv.nil? || srv[0].nil?
|
647
647
|
|
648
648
|
# extract values from service
|
649
|
-
parsed_srv = /^(?<pid>[0-9-]+)\t(?<exit>[0-9]+)\t(?<name>\S*)$/.match(srv[0])
|
649
|
+
parsed_srv = /^(?<pid>[0-9-]+)\t(?<exit>[\-0-9]+)\t(?<name>\S*)$/.match(srv[0])
|
650
650
|
enabled = !parsed_srv["name"].nil? # it's in the list
|
651
651
|
|
652
652
|
# check if the service is running
|
data/lib/inspec/resources.rb
CHANGED
@@ -73,6 +73,7 @@ require "inspec/resources/mssql_sys_conf"
|
|
73
73
|
require "inspec/resources/mysql"
|
74
74
|
require "inspec/resources/mysql_conf"
|
75
75
|
require "inspec/resources/mysql_session"
|
76
|
+
require "inspec/resources/nftables"
|
76
77
|
require "inspec/resources/nginx"
|
77
78
|
require "inspec/resources/nginx_conf"
|
78
79
|
require "inspec/resources/npm"
|
data/lib/inspec/rule.rb
CHANGED
@@ -8,13 +8,15 @@ require "inspec/impact"
|
|
8
8
|
require "inspec/resource"
|
9
9
|
require "inspec/resources/os"
|
10
10
|
require "inspec/input_registry"
|
11
|
+
require "inspec/waiver_file_reader"
|
12
|
+
require "inspec/utils/convert"
|
11
13
|
|
12
14
|
module Inspec
|
13
15
|
class Rule
|
14
16
|
include ::RSpec::Matchers
|
15
17
|
|
16
18
|
attr_reader :__waiver_data
|
17
|
-
attr_accessor :resource_dsl
|
19
|
+
attr_accessor :resource_dsl, :na_impact_freeze
|
18
20
|
attr_reader :__profile_id
|
19
21
|
|
20
22
|
def initialize(id, profile_id, resource_dsl, opts, &block)
|
@@ -38,6 +40,7 @@ module Inspec
|
|
38
40
|
@__merge_count = 0
|
39
41
|
@__merge_changes = []
|
40
42
|
@__skip_only_if_eval = opts[:skip_only_if_eval]
|
43
|
+
@__na_rule = {}
|
41
44
|
|
42
45
|
# evaluate the given definition
|
43
46
|
return unless block_given?
|
@@ -73,10 +76,13 @@ module Inspec
|
|
73
76
|
end
|
74
77
|
|
75
78
|
def impact(v = nil)
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
79
|
+
# N/A impact freeze is required when only_applicable_if block has reset impact value to zero"
|
80
|
+
unless na_impact_freeze
|
81
|
+
if v.is_a?(String)
|
82
|
+
@impact = Inspec::Impact.impact_from_string(v)
|
83
|
+
elsif !v.nil?
|
84
|
+
@impact = v
|
85
|
+
end
|
80
86
|
end
|
81
87
|
|
82
88
|
@impact
|
@@ -133,15 +139,28 @@ module Inspec
|
|
133
139
|
#
|
134
140
|
# @param [Type] &block returns true if tests are added, false otherwise
|
135
141
|
# @return [nil]
|
136
|
-
def only_if(message = nil)
|
142
|
+
def only_if(message = nil, impact: nil)
|
137
143
|
return unless block_given?
|
138
144
|
return if @__skip_only_if_eval == true
|
139
145
|
|
146
|
+
self.impact(impact) if impact && !yield
|
140
147
|
@__skip_rule[:result] ||= !yield
|
141
148
|
@__skip_rule[:type] = :only_if
|
142
149
|
@__skip_rule[:message] = message
|
143
150
|
end
|
144
151
|
|
152
|
+
def only_applicable_if(message = nil)
|
153
|
+
return unless block_given?
|
154
|
+
return if yield
|
155
|
+
|
156
|
+
impact(0.0)
|
157
|
+
self.na_impact_freeze = true # this flag prevents impact value to reset to any other value
|
158
|
+
|
159
|
+
@__na_rule[:result] ||= !yield
|
160
|
+
@__na_rule[:type] = :only_applicable_if
|
161
|
+
@__na_rule[:message] = message
|
162
|
+
end
|
163
|
+
|
145
164
|
# Describe will add one or more tests to this control. There is 2 ways
|
146
165
|
# of calling it:
|
147
166
|
#
|
@@ -252,6 +271,10 @@ module Inspec
|
|
252
271
|
rule.instance_variable_get(:@__skip_rule)
|
253
272
|
end
|
254
273
|
|
274
|
+
def self.na_status(rule)
|
275
|
+
rule.instance_variable_get(:@__na_rule)
|
276
|
+
end
|
277
|
+
|
255
278
|
def self.set_skip_rule(rule, value, message = nil, type = :only_if)
|
256
279
|
rule.instance_variable_set(:@__skip_rule,
|
257
280
|
{
|
@@ -273,16 +296,26 @@ module Inspec
|
|
273
296
|
# creates a dummay array of "checks" with a skip outcome
|
274
297
|
def self.prepare_checks(rule)
|
275
298
|
skip_check = skip_status(rule)
|
276
|
-
|
299
|
+
na_check = na_status(rule)
|
300
|
+
return checks(rule) unless skip_check[:result].eql?(true) || na_check[:result].eql?(true)
|
277
301
|
|
278
|
-
|
279
|
-
|
302
|
+
resource = rule.noop
|
303
|
+
if skip_check[:result].eql?(true)
|
304
|
+
if skip_check[:message]
|
305
|
+
msg = "Skipped control due to #{skip_check[:type]} condition: #{skip_check[:message]}"
|
306
|
+
else
|
307
|
+
msg = "Skipped control due to #{skip_check[:type]} condition."
|
308
|
+
end
|
309
|
+
resource.skip_resource(msg)
|
280
310
|
else
|
281
|
-
|
311
|
+
if na_check[:message]
|
312
|
+
msg = "N/A control due to #{na_check[:type]} condition: #{na_check[:message]}"
|
313
|
+
else
|
314
|
+
msg = "N/A control due to #{na_check[:type]} condition."
|
315
|
+
end
|
316
|
+
resource.fail_resource(msg)
|
282
317
|
end
|
283
318
|
|
284
|
-
resource = rule.noop
|
285
|
-
resource.skip_resource(msg)
|
286
319
|
[["describe", [resource], nil]]
|
287
320
|
end
|
288
321
|
|
@@ -337,17 +370,20 @@ module Inspec
|
|
337
370
|
# only_if mechanism)
|
338
371
|
# Double underscore: not intended to be called as part of the DSL
|
339
372
|
def __apply_waivers
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
373
|
+
control_id = @__rule_id # TODO: control ID slugging
|
374
|
+
waiver_files = Inspec::Config.cached.final_options["waiver_file"] if Inspec::Config.cached.respond_to?(:final_options)
|
375
|
+
|
376
|
+
waiver_data_by_profile = Inspec::WaiverFileReader.fetch_waivers_by_profile(__profile_id, waiver_files) unless waiver_files.nil?
|
377
|
+
|
378
|
+
return unless waiver_data_by_profile && waiver_data_by_profile[control_id] && waiver_data_by_profile[control_id].is_a?(Hash)
|
344
379
|
|
345
380
|
# An InSpec Input is a datastructure that tracks a profile parameter
|
346
381
|
# over time. Its value can be set by many sources, and it keeps a
|
347
382
|
# log of each "set" event so that when it is collapsed to a value,
|
348
383
|
# it can determine the correct (highest priority) value.
|
349
384
|
# Store in an instance variable for.. later reading???
|
350
|
-
@__waiver_data =
|
385
|
+
@__waiver_data = waiver_data_by_profile[control_id]
|
386
|
+
|
351
387
|
__waiver_data["skipped_due_to_waiver"] = false
|
352
388
|
__waiver_data["message"] = ""
|
353
389
|
|
@@ -376,6 +412,7 @@ module Inspec
|
|
376
412
|
# expiration_date. We only care here if it has a "run" key and it
|
377
413
|
# is false-like, since all non-skipped waiver operations are handled
|
378
414
|
# during reporting phase.
|
415
|
+
__waiver_data["run"] = Converter.to_boolean(__waiver_data["run"]) if __waiver_data.key?("run")
|
379
416
|
return unless __waiver_data.key?("run") && !__waiver_data["run"]
|
380
417
|
|
381
418
|
# OK, apply a skip.
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "inspec/enhanced_outcomes"
|
2
|
+
|
1
3
|
module Inspec
|
2
4
|
class RunData
|
3
5
|
Control = Struct.new(
|
@@ -31,6 +33,10 @@ module Inspec
|
|
31
33
|
].each do |field|
|
32
34
|
self[field] = raw_ctl_data[field]
|
33
35
|
end
|
36
|
+
|
37
|
+
def status
|
38
|
+
Inspec::EnhancedOutcomes.determine_status(results, impact)
|
39
|
+
end
|
34
40
|
end
|
35
41
|
end
|
36
42
|
|
@@ -16,14 +16,20 @@ module Inspec
|
|
16
16
|
:total,
|
17
17
|
:passed,
|
18
18
|
:skipped,
|
19
|
-
:failed
|
19
|
+
:failed,
|
20
|
+
:not_reviewed,
|
21
|
+
:not_applicable,
|
22
|
+
:error
|
20
23
|
) do
|
21
24
|
include HashLikeStruct
|
22
25
|
def initialize(raw_stat_ctl_data)
|
23
26
|
self.total = raw_stat_ctl_data[:total]
|
24
27
|
self.passed = Inspec::RunData::Statistics::Controls::Total.new(raw_stat_ctl_data[:passed][:total])
|
25
|
-
self.skipped = Inspec::RunData::Statistics::Controls::Total.new(raw_stat_ctl_data[:skipped][:total])
|
26
28
|
self.failed = Inspec::RunData::Statistics::Controls::Total.new(raw_stat_ctl_data[:failed][:total])
|
29
|
+
self.skipped = Inspec::RunData::Statistics::Controls::Total.new(raw_stat_ctl_data[:skipped][:total]) if raw_stat_ctl_data[:skipped]
|
30
|
+
self.not_reviewed = Inspec::RunData::Statistics::Controls::Total.new(raw_stat_ctl_data[:not_reviewed][:total]) if raw_stat_ctl_data[:not_reviewed]
|
31
|
+
self.not_applicable = Inspec::RunData::Statistics::Controls::Total.new(raw_stat_ctl_data[:not_applicable][:total]) if raw_stat_ctl_data[:not_applicable]
|
32
|
+
self.error = Inspec::RunData::Statistics::Controls::Total.new(raw_stat_ctl_data[:error][:total]) if raw_stat_ctl_data[:error]
|
27
33
|
end
|
28
34
|
end
|
29
35
|
class Controls
|