inspec 1.0.0 → 1.35.1
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/CHANGELOG.md +933 -101
- data/Gemfile +8 -17
- data/MAINTAINERS.md +2 -1
- data/MAINTAINERS.toml +9 -4
- data/README.md +49 -28
- data/Rakefile +54 -39
- data/bin/inspec +1 -1
- data/docs/dsl_inspec.md +17 -4
- data/docs/dsl_resource.md +1 -1
- data/docs/habitat.md +192 -0
- data/docs/inspec_and_friends.md +4 -2
- data/docs/matchers.md +11 -0
- data/docs/migration.md +293 -0
- data/docs/profiles.md +124 -76
- data/docs/resources/aide_conf.md.erb +81 -0
- data/docs/resources/apache_conf.md.erb +10 -10
- data/docs/resources/apt.md.erb +13 -13
- data/docs/resources/audit_policy.md.erb +10 -10
- data/docs/resources/auditd_conf.md.erb +10 -10
- data/docs/resources/auditd_rules.md.erb +11 -11
- data/docs/resources/bash.md.erb +12 -12
- data/docs/resources/bond.md.erb +15 -15
- data/docs/resources/bridge.md.erb +11 -11
- data/docs/resources/bsd_service.md.erb +11 -11
- data/docs/resources/command.md.erb +23 -23
- data/docs/resources/crontab.md.erb +84 -0
- data/docs/resources/csv.md.erb +10 -10
- data/docs/resources/dh_params.md +191 -0
- data/docs/resources/directory.md.erb +8 -8
- data/docs/resources/docker.md.erb +160 -0
- data/docs/resources/docker_container.md.erb +89 -0
- data/docs/resources/docker_image.md.erb +86 -0
- data/docs/resources/etc_group.md.erb +16 -16
- data/docs/resources/etc_hosts.md.erb +62 -0
- data/docs/resources/file.md.erb +80 -58
- data/docs/resources/gem.md.erb +32 -13
- data/docs/resources/group.md.erb +12 -12
- data/docs/resources/grub_conf.md.erb +11 -11
- data/docs/resources/host.md.erb +27 -18
- data/docs/resources/http.md.erb +104 -0
- data/docs/resources/iis_app.md.erb +126 -0
- data/docs/resources/iis_site.md.erb +17 -17
- data/docs/resources/inetd_conf.md.erb +10 -10
- data/docs/resources/ini.md.erb +9 -9
- data/docs/resources/interface.md.erb +13 -13
- data/docs/resources/iptables.md.erb +21 -14
- data/docs/resources/json.md.erb +11 -11
- data/docs/resources/kernel_module.md.erb +73 -12
- data/docs/resources/kernel_parameter.md.erb +12 -12
- data/docs/resources/key_rsa.md.erb +70 -0
- data/docs/resources/launchd_service.md.erb +11 -11
- data/docs/resources/limits_conf.md.erb +10 -10
- data/docs/resources/login_def.md.erb +12 -12
- data/docs/resources/mount.md.erb +14 -14
- data/docs/resources/mssql_session.md.erb +62 -0
- data/docs/resources/mysql_conf.md.erb +14 -14
- data/docs/resources/mysql_session.md.erb +22 -10
- data/docs/resources/npm.md.erb +13 -13
- data/docs/resources/ntp_conf.md.erb +9 -9
- data/docs/resources/oneget.md.erb +11 -11
- data/docs/resources/oracledb_session.md.erb +53 -0
- data/docs/resources/os.md.erb +17 -17
- data/docs/resources/os_env.md.erb +12 -12
- data/docs/resources/package.md.erb +29 -16
- data/docs/resources/parse_config.md.erb +18 -18
- data/docs/resources/parse_config_file.md.erb +29 -23
- data/docs/resources/{etc_passwd.md.erb → passwd.md.erb} +17 -17
- data/docs/resources/pip.md.erb +15 -15
- data/docs/resources/port.md.erb +23 -23
- data/docs/resources/postgres_conf.md.erb +15 -13
- data/docs/resources/postgres_hba_conf.md.erb +104 -0
- data/docs/resources/postgres_ident_conf.md.erb +87 -0
- data/docs/resources/postgres_session.md.erb +28 -21
- data/docs/resources/powershell.md.erb +14 -14
- data/docs/resources/processes.md.erb +123 -0
- data/docs/resources/rabbitmq_config.md.erb +55 -0
- data/docs/resources/registry_key.md.erb +44 -21
- data/docs/resources/runit_service.md.erb +11 -11
- data/docs/resources/security_policy.md.erb +10 -10
- data/docs/resources/service.md.erb +18 -18
- data/docs/resources/{etc_shadow.md.erb → shadow.md.erb} +19 -19
- data/docs/resources/ssh_config.md.erb +13 -13
- data/docs/resources/sshd_config.md.erb +15 -15
- data/docs/resources/ssl.md.erb +13 -13
- data/docs/resources/sys_info.md.erb +10 -10
- data/docs/resources/systemd_service.md.erb +11 -11
- data/docs/resources/sysv_service.md.erb +11 -11
- data/docs/resources/upstart_service.md.erb +11 -11
- data/docs/resources/user.md.erb +20 -20
- data/docs/resources/users.md.erb +19 -19
- data/docs/resources/vbscript.md.erb +13 -13
- data/docs/resources/virtualization.md.erb +71 -0
- data/docs/resources/windows_feature.md.erb +10 -10
- data/docs/resources/windows_task.md.erb +103 -0
- data/docs/resources/wmi.md.erb +10 -10
- data/docs/resources/x509_certificate.md.erb +146 -0
- data/docs/resources/xinetd_conf.md.erb +17 -17
- data/docs/resources/xml.md.erb +75 -0
- data/docs/resources/yaml.md.erb +25 -11
- data/docs/resources/yum.md.erb +24 -16
- data/docs/resources/zfs_dataset.md.erb +63 -0
- data/docs/resources/zfs_pool.md.erb +57 -0
- data/docs/ruby_usage.md +50 -0
- data/docs/shared/matcher_cmp.md.erb +4 -6
- data/examples/inheritance/README.md +49 -3
- data/examples/inheritance/controls/example.rb +4 -1
- data/examples/inheritance/inspec.yml +3 -1
- data/examples/meta-profile/README.md +29 -3
- data/examples/meta-profile/controls/example.rb +10 -5
- data/examples/meta-profile/inspec.yml +4 -8
- data/examples/profile/README.md +1 -1
- data/examples/profile/controls/example.rb +0 -1
- data/examples/profile/controls/gordon.rb +0 -1
- data/examples/profile/inspec.yml +1 -1
- data/examples/profile-attribute/inspec.yml +1 -1
- data/examples/profile-sensitive/README.md +29 -0
- data/examples/profile-sensitive/controls/sensitive-failures.rb +9 -0
- data/examples/profile-sensitive/controls/sensitive.rb +9 -0
- data/examples/profile-sensitive/inspec.yml +8 -0
- data/inspec.gemspec +10 -2
- data/lib/bundles/inspec-artifact/README.md +1 -0
- data/lib/bundles/inspec-artifact/cli.rb +284 -0
- data/lib/bundles/inspec-artifact.rb +7 -0
- data/lib/bundles/inspec-compliance/README.md +44 -15
- data/lib/bundles/inspec-compliance/api.rb +135 -29
- data/lib/bundles/inspec-compliance/cli.rb +128 -21
- data/lib/bundles/inspec-compliance/configuration.rb +8 -0
- data/lib/bundles/inspec-compliance/http.rb +26 -19
- data/lib/bundles/inspec-compliance/target.rb +50 -25
- data/lib/bundles/inspec-habitat/cli.rb +31 -0
- data/lib/bundles/inspec-habitat/log.rb +10 -0
- data/lib/bundles/inspec-habitat/profile.rb +372 -0
- data/lib/bundles/inspec-habitat.rb +12 -0
- data/lib/bundles/inspec-init/templates/profile/controls/example.rb +0 -1
- data/lib/bundles/inspec-init/templates/profile/inspec.yml +1 -1
- data/lib/bundles/inspec-supermarket/api.rb +7 -5
- data/lib/bundles/inspec-supermarket/cli.rb +2 -2
- data/lib/fetchers/git.rb +4 -2
- data/lib/fetchers/local.rb +4 -1
- data/lib/fetchers/url.rb +64 -10
- data/lib/inspec/archive/tar.rb +1 -1
- data/lib/inspec/backend.rb +26 -3
- data/lib/inspec/base_cli.rb +44 -7
- data/lib/inspec/cached_fetcher.rb +2 -2
- data/lib/inspec/cli.rb +34 -12
- data/lib/inspec/completions/fish.sh.erb +34 -0
- data/lib/inspec/control_eval_context.rb +0 -2
- data/lib/inspec/dependencies/cache.rb +0 -1
- data/lib/inspec/dependencies/dependency_set.rb +2 -2
- data/lib/inspec/dependencies/lockfile.rb +13 -6
- data/lib/inspec/dependencies/requirement.rb +6 -6
- data/lib/inspec/dependencies/resolver.rb +4 -4
- data/lib/inspec/dsl.rb +3 -5
- data/lib/inspec/env_printer.rb +9 -1
- data/lib/inspec/exceptions.rb +8 -0
- data/lib/inspec/fetcher.rb +1 -1
- data/lib/inspec/file_provider.rb +47 -11
- data/lib/inspec/library_eval_context.rb +1 -1
- data/lib/inspec/metadata.rb +62 -18
- data/lib/inspec/method_source.rb +24 -0
- data/lib/inspec/objects/attribute.rb +21 -0
- data/lib/inspec/objects/control.rb +21 -3
- data/lib/inspec/objects/each_loop.rb +2 -1
- data/lib/inspec/objects/list.rb +1 -1
- data/lib/inspec/objects/or_test.rb +17 -2
- data/lib/inspec/objects/tag.rb +27 -0
- data/lib/inspec/objects/test.rb +9 -8
- data/lib/inspec/objects.rb +1 -0
- data/lib/inspec/plugins/fetcher.rb +4 -5
- data/lib/inspec/plugins/resource.rb +1 -2
- data/lib/inspec/plugins/source_reader.rb +3 -3
- data/lib/inspec/plugins.rb +1 -1
- data/lib/inspec/polyfill.rb +0 -1
- data/lib/inspec/profile.rb +92 -23
- data/lib/inspec/profile_context.rb +1 -1
- data/lib/inspec/profile_vendor.rb +66 -0
- data/lib/inspec/resource.rb +29 -3
- data/lib/inspec/rspec_json_formatter.rb +672 -285
- data/lib/inspec/rule.rb +12 -16
- data/lib/inspec/runner.rb +26 -15
- data/lib/inspec/runner_rspec.rb +1 -0
- data/lib/inspec/runtime_profile.rb +26 -0
- data/lib/inspec/schema.rb +185 -0
- data/lib/inspec/secrets/yaml.rb +8 -1
- data/lib/inspec/secrets.rb +1 -1
- data/lib/inspec/shell.rb +92 -22
- data/lib/inspec/source_reader.rb +1 -1
- data/lib/inspec/version.rb +1 -1
- data/lib/inspec.rb +1 -1
- data/lib/matchers/matchers.rb +67 -17
- data/lib/resources/aide_conf.rb +162 -0
- data/lib/resources/apache.rb +0 -1
- data/lib/resources/apache_conf.rb +3 -3
- data/lib/resources/apt.rb +2 -1
- data/lib/resources/audit_policy.rb +0 -1
- data/lib/resources/auditd_conf.rb +1 -2
- data/lib/resources/auditd_rules.rb +5 -5
- data/lib/resources/bond.rb +1 -1
- data/lib/resources/bridge.rb +1 -1
- data/lib/resources/command.rb +5 -3
- data/lib/resources/crontab.rb +102 -0
- data/lib/resources/csv.rb +18 -1
- data/lib/resources/dh_params.rb +84 -0
- data/lib/resources/directory.rb +7 -3
- data/lib/resources/docker.rb +198 -0
- data/lib/resources/docker_container.rb +114 -0
- data/lib/resources/docker_image.rb +96 -0
- data/lib/resources/etc_group.rb +2 -3
- data/lib/resources/etc_hosts.rb +81 -0
- data/lib/resources/file.rb +88 -30
- data/lib/resources/gem.rb +26 -6
- data/lib/resources/groups.rb +4 -5
- data/lib/resources/grub_conf.rb +3 -4
- data/lib/resources/host.rb +175 -35
- data/lib/resources/http.rb +73 -0
- data/lib/resources/iis_app.rb +103 -0
- data/lib/resources/iis_site.rb +23 -0
- data/lib/resources/inetd_conf.rb +9 -4
- data/lib/resources/interface.rb +4 -3
- data/lib/resources/json.rb +37 -14
- data/lib/resources/kernel_module.rb +77 -10
- data/lib/resources/kernel_parameter.rb +0 -1
- data/lib/resources/key_rsa.rb +67 -0
- data/lib/resources/limits_conf.rb +3 -4
- data/lib/resources/login_def.rb +2 -3
- data/lib/resources/mount.rb +34 -4
- data/lib/resources/mssql_session.rb +81 -12
- data/lib/resources/mysql.rb +0 -1
- data/lib/resources/mysql_conf.rb +1 -2
- data/lib/resources/mysql_session.rb +18 -7
- data/lib/resources/nginx_conf.rb +95 -0
- data/lib/resources/ntp_conf.rb +2 -3
- data/lib/resources/oracledb_session.rb +138 -0
- data/lib/resources/os_env.rb +7 -5
- data/lib/resources/package.rb +70 -13
- data/lib/resources/packages.rb +111 -0
- data/lib/resources/parse_config.rb +3 -4
- data/lib/resources/passwd.rb +4 -5
- data/lib/resources/pip.rb +29 -21
- data/lib/resources/port.rb +133 -14
- data/lib/resources/postgres.rb +53 -43
- data/lib/resources/postgres_conf.rb +40 -13
- data/lib/resources/postgres_hba_conf.rb +101 -0
- data/lib/resources/postgres_ident_conf.rb +79 -0
- data/lib/resources/postgres_session.rb +28 -20
- data/lib/resources/powershell.rb +2 -2
- data/lib/resources/processes.rb +61 -26
- data/lib/resources/rabbitmq_conf.rb +53 -0
- data/lib/resources/registry_key.rb +34 -11
- data/lib/resources/security_policy.rb +2 -2
- data/lib/resources/service.rb +17 -7
- data/lib/resources/ssh_conf.rb +17 -6
- data/lib/resources/ssl.rb +3 -4
- data/lib/resources/sys_info.rb +1 -1
- data/lib/resources/toml.rb +26 -0
- data/lib/resources/users.rb +41 -41
- data/lib/resources/virtualization.rb +252 -0
- data/lib/resources/windows_task.rb +106 -0
- data/lib/resources/x509_certificate.rb +143 -0
- data/lib/resources/xinetd.rb +18 -2
- data/lib/resources/xml.rb +27 -0
- data/lib/resources/yaml.rb +10 -2
- data/lib/resources/yum.rb +25 -7
- data/lib/resources/zfs_dataset.rb +60 -0
- data/lib/resources/zfs_pool.rb +49 -0
- data/lib/source_readers/flat.rb +2 -1
- data/lib/source_readers/inspec.rb +30 -11
- data/lib/utils/command_wrapper.rb +3 -3
- data/lib/utils/database_helpers.rb +77 -0
- data/lib/utils/erlang_parser.rb +192 -0
- data/lib/utils/filter.rb +2 -1
- data/lib/utils/filter_array.rb +0 -1
- data/lib/utils/find_files.rb +1 -2
- data/lib/utils/latest_version.rb +21 -0
- data/lib/utils/nginx_parser.rb +76 -0
- data/lib/utils/object_traversal.rb +5 -4
- data/lib/utils/parser.rb +23 -4
- data/lib/utils/plugin_registry.rb +3 -3
- data/lib/utils/simpleconfig.rb +25 -8
- data/lib/utils/spdx.rb +13 -0
- data/lib/utils/spdx.txt +344 -0
- metadata +168 -22
- data/docs/cli.md +0 -342
- data/docs/resources/process.md.erb +0 -73
- /data/docs/{plugin_kitchen_inspec.html.md → plugin_kitchen_inspec.md} +0 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# copyright: 2017, Chef Software, Inc. <legal@chef.io>
|
|
3
|
+
# author: Joshua Timberman
|
|
4
|
+
# author: Alex Pop
|
|
5
|
+
|
|
6
|
+
require 'utils/filter'
|
|
7
|
+
|
|
8
|
+
module Inspec::Resources
|
|
9
|
+
class Packages < Inspec.resource(1)
|
|
10
|
+
name 'packages'
|
|
11
|
+
desc 'Use the packages InSpec audit resource to test properties for multiple packages installed on the system'
|
|
12
|
+
example "
|
|
13
|
+
describe packages(/xserver-xorg.*/) do
|
|
14
|
+
its('entries') { should be_empty }
|
|
15
|
+
end
|
|
16
|
+
describe packages('vim').entries.length do
|
|
17
|
+
it { should be > 1 }
|
|
18
|
+
end
|
|
19
|
+
describe packages(/vi.+/).where { status != 'installed' } do
|
|
20
|
+
its('statuses') { should be_empty }
|
|
21
|
+
end
|
|
22
|
+
"
|
|
23
|
+
|
|
24
|
+
def initialize(pattern)
|
|
25
|
+
os = inspec.os
|
|
26
|
+
if os.debian?
|
|
27
|
+
@pkgs = Debs.new(inspec)
|
|
28
|
+
elsif os.redhat? || %w{suse amazon fedora}.include?(os[:family])
|
|
29
|
+
@pkgs = Rpms.new(inspec)
|
|
30
|
+
else
|
|
31
|
+
return skip_resource "The packages resource is not yet supported on OS #{inspec.os.name}"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
@pattern = pattern_regexp(pattern)
|
|
35
|
+
all_pkgs = @pkgs.build_package_list
|
|
36
|
+
@list = all_pkgs.find_all do |hm|
|
|
37
|
+
hm[:name] =~ @pattern
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def to_s
|
|
42
|
+
"Packages #{@pattern.class == String ? @pattern : @pattern.inspect}"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
filter = FilterTable.create
|
|
46
|
+
filter.add_accessor(:where)
|
|
47
|
+
.add_accessor(:entries)
|
|
48
|
+
.add(:statuses, field: 'status', style: :simple)
|
|
49
|
+
.add(:names, field: 'name')
|
|
50
|
+
.add(:versions, field: 'version')
|
|
51
|
+
.connect(self, :filtered_packages)
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def pattern_regexp(p)
|
|
56
|
+
if p.class == String
|
|
57
|
+
Regexp.new(Regexp.escape(p))
|
|
58
|
+
elsif p.class == Regexp
|
|
59
|
+
p
|
|
60
|
+
else
|
|
61
|
+
raise 'Invalid name argument to packages resource, please use a "string" or /regexp/'
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def filtered_packages
|
|
66
|
+
warn "The packages resource is not yet supported on OS #{inspec.os.name}" if resource_skipped
|
|
67
|
+
@list
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
class PkgsManagement
|
|
72
|
+
PackageStruct = Struct.new(:status, :name, :version)
|
|
73
|
+
attr_reader :inspec
|
|
74
|
+
def initialize(inspec)
|
|
75
|
+
@inspec = inspec
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Debian / Ubuntu
|
|
80
|
+
class Debs < PkgsManagement
|
|
81
|
+
def build_package_list
|
|
82
|
+
# use two spaces as delimiter in case any of the fields has a space in it
|
|
83
|
+
command = "dpkg-query -W -f='${db:Status-Abbrev} ${Package} ${Version}\\n'"
|
|
84
|
+
cmd = inspec.command(command)
|
|
85
|
+
all = cmd.stdout.split("\n")
|
|
86
|
+
return [] if all.nil?
|
|
87
|
+
all.map do |m|
|
|
88
|
+
a = m.split(/ {2,}/)
|
|
89
|
+
a[0] = 'installed' if a[0] =~ /^.i/
|
|
90
|
+
a[2] = a[2].split(':').last
|
|
91
|
+
PackageStruct.new(*a)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# RedHat family
|
|
97
|
+
class Rpms < PkgsManagement
|
|
98
|
+
def build_package_list
|
|
99
|
+
# use two spaces as delimiter in case any of the fields has a space in it
|
|
100
|
+
command = "rpm -qa --queryformat '%{NAME} %{VERSION}-%{RELEASE}\\n'"
|
|
101
|
+
cmd = inspec.command(command)
|
|
102
|
+
all = cmd.stdout.split("\n")
|
|
103
|
+
return [] if all.nil?
|
|
104
|
+
all.map do |m|
|
|
105
|
+
a = m.split(' ')
|
|
106
|
+
a.unshift('installed')
|
|
107
|
+
PackageStruct.new(*a)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -2,13 +2,12 @@
|
|
|
2
2
|
# copyright: 2015, Vulcano Security GmbH
|
|
3
3
|
# author: Dominik Richter
|
|
4
4
|
# author: Christoph Hartmann
|
|
5
|
-
# license: All rights reserved
|
|
6
5
|
|
|
7
6
|
# Usage example:
|
|
8
7
|
#
|
|
9
8
|
# audit = command('/sbin/auditctl -l').stdout
|
|
10
9
|
# options = {
|
|
11
|
-
#
|
|
10
|
+
# assignment_regex: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
|
|
12
11
|
# multiple_values: true
|
|
13
12
|
# }
|
|
14
13
|
# describe parse_config(audit, options ) do
|
|
@@ -26,7 +25,7 @@ module Inspec::Resources
|
|
|
26
25
|
output2 = command('curl http://127.0.0.1/php_status').stdout
|
|
27
26
|
# php status is in format 'key : value', and we do not allow for multiple values
|
|
28
27
|
options2 = {
|
|
29
|
-
|
|
28
|
+
assignment_regex: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
|
|
30
29
|
multiple_values: false
|
|
31
30
|
}
|
|
32
31
|
|
|
@@ -76,7 +75,7 @@ module Inspec::Resources
|
|
|
76
75
|
return skip_resource "Can't find file \"#{conf_path}\""
|
|
77
76
|
end
|
|
78
77
|
@content = read_file(conf_path).to_s
|
|
79
|
-
if @content.empty? && inspec.file(conf_path).
|
|
78
|
+
if @content.empty? && !inspec.file(conf_path).empty?
|
|
80
79
|
return skip_resource "Can't read file \"#{conf_path}\""
|
|
81
80
|
end
|
|
82
81
|
|
data/lib/resources/passwd.rb
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
# copyright: 2015, Vulcano Security GmbH
|
|
3
3
|
# author: Christoph Hartmann
|
|
4
4
|
# author: Dominik Richter
|
|
5
|
-
# license: All rights reserved
|
|
6
5
|
|
|
7
6
|
# The file format consists of
|
|
8
7
|
# - username
|
|
@@ -62,17 +61,17 @@ module Inspec::Resources
|
|
|
62
61
|
.add(:shells, field: 'shell')
|
|
63
62
|
|
|
64
63
|
filter.add(:count) { |t, _|
|
|
65
|
-
warn '[DEPRECATION] `passwd.count` is deprecated. Please use `passwd.entries.length` instead. It will be removed in version
|
|
64
|
+
warn '[DEPRECATION] `passwd.count` is deprecated. Please use `passwd.entries.length` instead. It will be removed in the next major version.'
|
|
66
65
|
t.entries.length
|
|
67
66
|
}
|
|
68
67
|
|
|
69
68
|
filter.add(:usernames) { |t, x|
|
|
70
|
-
warn '[DEPRECATION] `passwd.usernames` is deprecated. Please use `passwd.users` instead. It will be removed in version
|
|
69
|
+
warn '[DEPRECATION] `passwd.usernames` is deprecated. Please use `passwd.users` instead. It will be removed in the next major version.'
|
|
71
70
|
t.users(x)
|
|
72
71
|
}
|
|
73
72
|
|
|
74
73
|
filter.add(:username) { |t, x|
|
|
75
|
-
warn '[DEPRECATION] `passwd.username` is deprecated. Please use `passwd.users` instead. It will be removed in version
|
|
74
|
+
warn '[DEPRECATION] `passwd.username` is deprecated. Please use `passwd.users` instead. It will be removed in the next major version.'
|
|
76
75
|
t.users(x)[0]
|
|
77
76
|
}
|
|
78
77
|
|
|
@@ -84,7 +83,7 @@ module Inspec::Resources
|
|
|
84
83
|
}
|
|
85
84
|
|
|
86
85
|
def uid(x)
|
|
87
|
-
warn '[DEPRECATION] `passwd.uid(arg)` is deprecated. Please use `passwd.uids(arg)` instead. It will be removed in version
|
|
86
|
+
warn '[DEPRECATION] `passwd.uid(arg)` is deprecated. Please use `passwd.uids(arg)` instead. It will be removed in the next major version.'
|
|
88
87
|
uids(x)
|
|
89
88
|
end
|
|
90
89
|
|
data/lib/resources/pip.rb
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
# it { should be_installed }
|
|
8
8
|
# end
|
|
9
9
|
#
|
|
10
|
+
|
|
10
11
|
module Inspec::Resources
|
|
11
12
|
class PipPackage < Inspec.resource(1)
|
|
12
13
|
name 'pip'
|
|
@@ -15,10 +16,17 @@ module Inspec::Resources
|
|
|
15
16
|
describe pip('Jinja2') do
|
|
16
17
|
it { should be_installed }
|
|
17
18
|
end
|
|
19
|
+
|
|
20
|
+
describe pip('django', '/path/to/virtualenv/bin/pip') do
|
|
21
|
+
it { should be_installed }
|
|
22
|
+
its('version') { should eq('1.11.4')}
|
|
23
|
+
end
|
|
18
24
|
"
|
|
19
25
|
|
|
20
|
-
def initialize(package_name)
|
|
26
|
+
def initialize(package_name, pip_path = nil)
|
|
21
27
|
@package_name = package_name
|
|
28
|
+
@pip_cmd = pip_path || default_pip_path
|
|
29
|
+
return skip_resource 'pip not found' unless inspec.command(@pip_cmd).exist?
|
|
22
30
|
end
|
|
23
31
|
|
|
24
32
|
def info
|
|
@@ -26,12 +34,12 @@ module Inspec::Resources
|
|
|
26
34
|
|
|
27
35
|
@info = {}
|
|
28
36
|
@info[:type] = 'pip'
|
|
29
|
-
cmd = inspec.command("#{pip_cmd} show #{@package_name}")
|
|
37
|
+
cmd = inspec.command("#{@pip_cmd} show #{@package_name}")
|
|
30
38
|
return @info if cmd.exit_status != 0
|
|
31
39
|
|
|
32
40
|
params = SimpleConfig.new(
|
|
33
41
|
cmd.stdout,
|
|
34
|
-
|
|
42
|
+
assignment_regex: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
|
|
35
43
|
multiple_values: false,
|
|
36
44
|
).params
|
|
37
45
|
@info[:name] = params['Name']
|
|
@@ -54,28 +62,28 @@ module Inspec::Resources
|
|
|
54
62
|
|
|
55
63
|
private
|
|
56
64
|
|
|
57
|
-
def
|
|
65
|
+
def default_pip_path
|
|
66
|
+
return 'pip' unless inspec.os.windows?
|
|
67
|
+
|
|
58
68
|
# Pip is not on the default path for Windows, therefore we do some logic
|
|
59
69
|
# to find the binary on Windows
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
pipdir.pop
|
|
72
|
-
pipcmd = pipdir.push('Scripts').push('pip.exe').join('/')
|
|
73
|
-
end
|
|
74
|
-
rescue JSON::ParserError => _e
|
|
75
|
-
return nil
|
|
70
|
+
cmd = inspec.command('New-Object -Type PSObject | Add-Member -MemberType NoteProperty -Name Pip -Value (Invoke-Command -ScriptBlock {where.exe pip}) -PassThru | Add-Member -MemberType NoteProperty -Name Python -Value (Invoke-Command -ScriptBlock {where.exe python}) -PassThru | ConvertTo-Json')
|
|
71
|
+
begin
|
|
72
|
+
paths = JSON.parse(cmd.stdout)
|
|
73
|
+
# use pip if it on system path
|
|
74
|
+
pipcmd = paths['Pip']
|
|
75
|
+
# calculate path on windows
|
|
76
|
+
if defined?(paths['Python']) && pipcmd.nil?
|
|
77
|
+
pipdir = paths['Python'].split('\\')
|
|
78
|
+
# remove python.exe
|
|
79
|
+
pipdir.pop
|
|
80
|
+
pipcmd = pipdir.push('Scripts').push('pip.exe').join('/')
|
|
76
81
|
end
|
|
82
|
+
rescue JSON::ParserError => _e
|
|
83
|
+
return nil
|
|
77
84
|
end
|
|
78
|
-
|
|
85
|
+
|
|
86
|
+
pipcmd
|
|
79
87
|
end
|
|
80
88
|
end
|
|
81
89
|
end
|
data/lib/resources/port.rb
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
require 'utils/parser'
|
|
6
6
|
require 'utils/filter'
|
|
7
|
+
require 'ipaddr'
|
|
7
8
|
|
|
8
9
|
# TODO: currently we return local ip only
|
|
9
10
|
# TODO: improve handling of same port on multiple interfaces
|
|
@@ -45,7 +46,7 @@ module Inspec::Resources
|
|
|
45
46
|
.add(:protocols, field: 'protocol', style: :simple)
|
|
46
47
|
.add(:processes, field: 'process', style: :simple)
|
|
47
48
|
.add(:pids, field: 'pid', style: :simple)
|
|
48
|
-
.add(:listening?) { |x| x.entries.
|
|
49
|
+
.add(:listening?) { |x| !x.entries.empty? }
|
|
49
50
|
filter.connect(self, :info)
|
|
50
51
|
|
|
51
52
|
def to_s
|
|
@@ -169,7 +170,7 @@ module Inspec::Resources
|
|
|
169
170
|
ports = []
|
|
170
171
|
|
|
171
172
|
# check that lsof is available, otherwise fail
|
|
172
|
-
|
|
173
|
+
raise 'Please ensure `lsof` is available on the machine.' if !inspec.command(@lsof.to_s).exist?
|
|
173
174
|
|
|
174
175
|
# -F p=pid, c=command, P=protocol name, t=type, n=internet addresses
|
|
175
176
|
# see 'OUTPUT FOR OTHER PROGRAMS' in LSOF(8)
|
|
@@ -263,10 +264,34 @@ module Inspec::Resources
|
|
|
263
264
|
end
|
|
264
265
|
|
|
265
266
|
# extract port information from netstat
|
|
266
|
-
class LinuxPorts < PortsInfo
|
|
267
|
+
class LinuxPorts < PortsInfo # rubocop:disable Metrics/ClassLength
|
|
268
|
+
ALLOWED_PROTOCOLS = %w{tcp tcp6 udp udp6}.freeze
|
|
269
|
+
|
|
267
270
|
def info
|
|
271
|
+
ports_via_ss || ports_via_netstat
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def ports_via_ss
|
|
275
|
+
return nil unless inspec.command('ss').exist?
|
|
276
|
+
|
|
277
|
+
cmd = inspec.command('ss -tulpen')
|
|
278
|
+
return nil unless cmd.exit_status.to_i.zero?
|
|
279
|
+
|
|
280
|
+
ports = []
|
|
281
|
+
|
|
282
|
+
cmd.stdout.each_line do |line|
|
|
283
|
+
parsed_line = parse_ss_line(line)
|
|
284
|
+
ports << parsed_line unless parsed_line.nil?
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
ports
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def ports_via_netstat
|
|
291
|
+
return nil unless inspec.command('netstat').exist?
|
|
292
|
+
|
|
268
293
|
cmd = inspec.command('netstat -tulpen')
|
|
269
|
-
return nil
|
|
294
|
+
return nil unless cmd.exit_status.to_i.zero?
|
|
270
295
|
|
|
271
296
|
ports = []
|
|
272
297
|
# parse all lines
|
|
@@ -286,10 +311,38 @@ module Inspec::Resources
|
|
|
286
311
|
ip6 = /^(\S+):(\d+)$/.match(net_addr)
|
|
287
312
|
ip6addr = ip6[1]
|
|
288
313
|
ip6addr = '::' if ip6addr =~ /^:::$/
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
#
|
|
292
|
-
|
|
314
|
+
|
|
315
|
+
# v6 addresses need to end in a double-colon when using
|
|
316
|
+
# shorthand notation. netstat ends with a single colon.
|
|
317
|
+
# IPAddr will fail to properly parse an address unless it
|
|
318
|
+
# uses a double-colon for short-hand notation.
|
|
319
|
+
ip6addr += ':' if ip6addr =~ /\w:$/
|
|
320
|
+
|
|
321
|
+
begin
|
|
322
|
+
ip_parser = IPAddr.new(ip6addr)
|
|
323
|
+
rescue IPAddr::InvalidAddressError
|
|
324
|
+
# This IP is not parsable. There appears to be a bug in netstat
|
|
325
|
+
# output that truncates link-local IP addresses:
|
|
326
|
+
# example: udp6 0 0 fe80::42:acff:fe11::123 :::* 0 54550 3335/ntpd
|
|
327
|
+
# actual link address: inet6 fe80::42:acff:fe11:5/64 scope link
|
|
328
|
+
#
|
|
329
|
+
# in this example, the "5" is truncated making the netstat output
|
|
330
|
+
# an invalid IP address.
|
|
331
|
+
return [nil, nil]
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
# Check to see if this is a IPv4 address in a tcp6/udp6 line.
|
|
335
|
+
# If so, don't put brackets around the IP or URI won't know how
|
|
336
|
+
# to properly handle it.
|
|
337
|
+
# example: tcp6 0 0 127.0.0.1:8005 :::* LISTEN
|
|
338
|
+
if ip_parser.ipv4?
|
|
339
|
+
ip_addr = URI("addr://#{ip6addr}:#{ip6[2]}")
|
|
340
|
+
host = ip_addr.host
|
|
341
|
+
else
|
|
342
|
+
ip_addr = URI("addr://[#{ip6addr}]:#{ip6[2]}")
|
|
343
|
+
# strip []
|
|
344
|
+
host = ip_addr.host[1..ip_addr.host.size-2]
|
|
345
|
+
end
|
|
293
346
|
else
|
|
294
347
|
ip_addr = URI('addr://'+net_addr)
|
|
295
348
|
host = ip_addr.host
|
|
@@ -317,6 +370,7 @@ module Inspec::Resources
|
|
|
317
370
|
|
|
318
371
|
# extract host and port information
|
|
319
372
|
host, port = parse_net_address(parsed[4], protocol)
|
|
373
|
+
return {} if host.nil?
|
|
320
374
|
|
|
321
375
|
# extract PID
|
|
322
376
|
process = parsed[9].split('/')
|
|
@@ -332,6 +386,66 @@ module Inspec::Resources
|
|
|
332
386
|
'pid' => pid,
|
|
333
387
|
}
|
|
334
388
|
end
|
|
389
|
+
|
|
390
|
+
def parse_ss_line(line)
|
|
391
|
+
parsed = line.split(/\s+/, 7)
|
|
392
|
+
|
|
393
|
+
# ss only returns "tcp" and "udp" as the protocol. However, netstat would return
|
|
394
|
+
# "tcp6" and "udp6" as necessary. In order to maintain backward compatibility, we
|
|
395
|
+
# will manually modify the protocol value if the line we're parsing is an IPv6
|
|
396
|
+
# entry.
|
|
397
|
+
process_info = parsed[6]
|
|
398
|
+
protocol = parsed[0]
|
|
399
|
+
protocol += '6' if process_info.include?('v6only:1')
|
|
400
|
+
return nil unless ALLOWED_PROTOCOLS.include?(protocol)
|
|
401
|
+
|
|
402
|
+
# parse the Local Address:Port
|
|
403
|
+
# examples:
|
|
404
|
+
# *:22
|
|
405
|
+
# :::22
|
|
406
|
+
# 10.0.2.15:1234
|
|
407
|
+
# ::ffff:10.0.2.15:9300
|
|
408
|
+
# fe80::a00:27ff:fe32:ed09%enp0s3:9200
|
|
409
|
+
parsed_net_address = parsed[4].match(/(\S+):(\*|\d+)$/)
|
|
410
|
+
return nil if parsed_net_address.nil?
|
|
411
|
+
host = parsed_net_address[1]
|
|
412
|
+
port = parsed_net_address[2]
|
|
413
|
+
return nil if host.nil? && port.nil?
|
|
414
|
+
|
|
415
|
+
# For backward compatibility with the netstat output, ensure the
|
|
416
|
+
# port is stored as an integer
|
|
417
|
+
port = port.to_i
|
|
418
|
+
|
|
419
|
+
# for those "v4-but-listed-in-v6" entries, strip off the
|
|
420
|
+
# leading IPv6 value at the beginning
|
|
421
|
+
# example: ::ffff:10.0.2.15:9200
|
|
422
|
+
host.delete!('::ffff:') if host.start_with?('::ffff:')
|
|
423
|
+
|
|
424
|
+
# if there's an interface name in the local address, which is common for
|
|
425
|
+
# IPv6 listeners, strip that out too.
|
|
426
|
+
# example: fe80::a00:27ff:fe32:ed09%enp0s3
|
|
427
|
+
host = host.split('%').first
|
|
428
|
+
|
|
429
|
+
# if host is "*", replace with "0.0.0.0" to maintain backward compatibility with
|
|
430
|
+
# the netstat-provided data
|
|
431
|
+
host = '0.0.0.0' if host == '*'
|
|
432
|
+
|
|
433
|
+
# parse the process name from the processes information
|
|
434
|
+
process_match = parsed[6].match(/users:\(\(\"(\S+)\"/)
|
|
435
|
+
process = process_match.nil? ? nil : process_match[1]
|
|
436
|
+
|
|
437
|
+
# parse the PID from the processes information
|
|
438
|
+
pid_match = parsed[6].match(/pid=(\d+)/)
|
|
439
|
+
pid = pid_match.nil? ? nil : pid_match[1].to_i
|
|
440
|
+
|
|
441
|
+
{
|
|
442
|
+
'port' => port,
|
|
443
|
+
'address' => host,
|
|
444
|
+
'protocol' => protocol,
|
|
445
|
+
'process' => process,
|
|
446
|
+
'pid' => pid,
|
|
447
|
+
}
|
|
448
|
+
end
|
|
335
449
|
end
|
|
336
450
|
|
|
337
451
|
# extracts information from sockstat
|
|
@@ -434,13 +548,17 @@ module Inspec::Resources
|
|
|
434
548
|
# the last . to :
|
|
435
549
|
local_addr[local_addr.rindex('.')] = ':'
|
|
436
550
|
host, port = parse_net_address(local_addr, protocol)
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
551
|
+
if host.nil?
|
|
552
|
+
nil
|
|
553
|
+
else
|
|
554
|
+
{
|
|
555
|
+
'port' => port,
|
|
556
|
+
'address' => host,
|
|
557
|
+
'protocol' => protocol,
|
|
558
|
+
}
|
|
559
|
+
end
|
|
442
560
|
}
|
|
443
|
-
ports
|
|
561
|
+
ports.compact
|
|
444
562
|
end
|
|
445
563
|
end
|
|
446
564
|
|
|
@@ -476,6 +594,7 @@ module Inspec::Resources
|
|
|
476
594
|
local_addr[local_addr.rindex('.')] = ':'
|
|
477
595
|
# extract host and port information
|
|
478
596
|
host, port = parse_net_address(local_addr, protocol)
|
|
597
|
+
return {} if host.nil?
|
|
479
598
|
# map data
|
|
480
599
|
{
|
|
481
600
|
'port' => port,
|
data/lib/resources/postgres.rb
CHANGED
|
@@ -2,67 +2,50 @@
|
|
|
2
2
|
# copyright: 2015, Vulcano Security GmbH
|
|
3
3
|
# author: Dominik Richter
|
|
4
4
|
# author: Christoph Hartmann
|
|
5
|
-
#
|
|
5
|
+
# author: Aaron Lippold
|
|
6
6
|
|
|
7
7
|
module Inspec::Resources
|
|
8
8
|
class Postgres < Inspec.resource(1)
|
|
9
9
|
name 'postgres'
|
|
10
10
|
|
|
11
|
-
attr_reader :service, :data_dir, :conf_dir, :conf_path
|
|
11
|
+
attr_reader :service, :data_dir, :conf_dir, :conf_path, :version, :cluster
|
|
12
12
|
def initialize
|
|
13
|
-
|
|
14
|
-
if os.debian?
|
|
13
|
+
if inspec.os.debian?
|
|
15
14
|
#
|
|
16
15
|
# https://wiki.debian.org/PostgreSql
|
|
17
16
|
#
|
|
18
17
|
# Debian allows multiple versions of postgresql to be
|
|
19
18
|
# installed as well as multiple "clusters" to be configured.
|
|
20
19
|
#
|
|
21
|
-
version = version_from_dir('/etc/postgresql')
|
|
22
|
-
cluster = cluster_from_dir("/etc/postgresql/#{version}")
|
|
23
|
-
@conf_dir = "/etc/postgresql/#{version}/#{cluster}"
|
|
24
|
-
@data_dir = "/var/lib/postgresql/#{version}/#{cluster}"
|
|
25
|
-
elsif os.redhat?
|
|
26
|
-
#
|
|
27
|
-
# /var/lib/pgsql/data is the default data directory on RHEL6
|
|
28
|
-
# and RHEL7. However, PR #824 explicitly added version-based
|
|
29
|
-
# directories. Thus, we call #version_from_dir unless it looks
|
|
30
|
-
# like we are using unversioned directories.
|
|
31
|
-
#
|
|
32
|
-
# TODO(ssd): This has the potential to be noisy because of the
|
|
33
|
-
# warning in version_from_dir. We should determine which case
|
|
34
|
-
# is more common and only warn in the less common case.
|
|
35
|
-
#
|
|
36
|
-
version = if inspec.directory('/var/lib/pgsql/data').exist?
|
|
37
|
-
warn 'Found /var/lib/pgsql/data. Assuming postgresql install uses un-versioned directories.'
|
|
38
|
-
nil
|
|
39
|
-
else
|
|
40
|
-
version_from_dir('/var/lib/pgsql/')
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
@data_dir = File.join('/var/lib/pgsql/', version.to_s, 'data')
|
|
44
|
-
elsif os[:name] == 'arch'
|
|
45
|
-
#
|
|
46
|
-
# https://wiki.archlinux.org/index.php/PostgreSQL
|
|
47
|
-
#
|
|
48
|
-
# The archlinux wiki points to /var/lib/postgresql/data as the
|
|
49
|
-
# main data directory.
|
|
50
|
-
#
|
|
51
|
-
@data_dir = '/var/lib/postgres/data'
|
|
20
|
+
@version = version_from_psql || version_from_dir('/etc/postgresql')
|
|
21
|
+
@cluster = cluster_from_dir("/etc/postgresql/#{@version}")
|
|
22
|
+
@conf_dir = "/etc/postgresql/#{@version}/#{@cluster}"
|
|
23
|
+
@data_dir = "/var/lib/postgresql/#{@version}/#{@cluster}"
|
|
52
24
|
else
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
25
|
+
@version = version_from_psql
|
|
26
|
+
if @version.nil?
|
|
27
|
+
if inspec.directory('/var/lib/pgsql/data').exist?
|
|
28
|
+
warn 'Unable to determine PostgreSQL version: psql did not return
|
|
29
|
+
a version number and unversioned data directories were found.'
|
|
30
|
+
nil
|
|
31
|
+
else
|
|
32
|
+
@version = version_from_dir('/var/lib/pgsql')
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
@data_dir = locate_data_dir_location_by_version(@version)
|
|
60
36
|
end
|
|
61
37
|
|
|
62
38
|
@service = 'postgresql'
|
|
39
|
+
@service += "-#{@version}" if @version.to_f >= 9.4
|
|
63
40
|
@conf_dir ||= @data_dir
|
|
41
|
+
|
|
64
42
|
verify_dirs
|
|
65
|
-
|
|
43
|
+
if !@version.nil? && !@conf_dir.empty?
|
|
44
|
+
@conf_path = File.join @conf_dir, 'postgresql.conf'
|
|
45
|
+
else
|
|
46
|
+
@conf_path = nil
|
|
47
|
+
return skip_resource 'Seems like PostgreSQL is not installed on your system'
|
|
48
|
+
end
|
|
66
49
|
end
|
|
67
50
|
|
|
68
51
|
def to_s
|
|
@@ -81,6 +64,33 @@ module Inspec::Resources
|
|
|
81
64
|
end
|
|
82
65
|
end
|
|
83
66
|
|
|
67
|
+
def version_from_psql
|
|
68
|
+
return unless inspec.command('psql').exist?
|
|
69
|
+
inspec.command("psql --version | awk '{ print $NF }' | awk -F. '{ print $1\".\"$2 }'").stdout.strip
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def locate_data_dir_location_by_version(ver = @version)
|
|
73
|
+
data_dir_loc = nil
|
|
74
|
+
dir_list = [
|
|
75
|
+
"/var/lib/pgsql/#{ver}/data",
|
|
76
|
+
'/var/lib/pgsql/data',
|
|
77
|
+
'/var/lib/postgres/data',
|
|
78
|
+
'/var/lib/postgresql/data',
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
dir_list.each do |dir|
|
|
82
|
+
data_dir_loc = dir if inspec.directory(dir).exist?
|
|
83
|
+
break
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
if data_dir_loc.nil?
|
|
87
|
+
warn 'Unable to find the PostgreSQL data_dir in expected location(s), please
|
|
88
|
+
execute "psql -t -A -p <port> -h <host> -c "show hba_file";" as the PostgreSQL
|
|
89
|
+
DBA to find the non-starndard data_dir location.'
|
|
90
|
+
end
|
|
91
|
+
data_dir_loc
|
|
92
|
+
end
|
|
93
|
+
|
|
84
94
|
def version_from_dir(dir)
|
|
85
95
|
dirs = inspec.command("ls -d #{dir}/*/").stdout
|
|
86
96
|
entries = dirs.lines.count
|