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,106 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# author: Gary Bright @username-is-already-taken2
|
|
3
|
+
# author: Chris Beard @cdbeard2016
|
|
4
|
+
module Inspec::Resources
|
|
5
|
+
class WindowsTasks < Inspec.resource(1)
|
|
6
|
+
name 'windows_task'
|
|
7
|
+
desc 'Use the windows_task InSpec audit resource to test task schedules on Microsoft Windows.'
|
|
8
|
+
example "
|
|
9
|
+
describe windows_task('\\Microsoft\\Windows\\Time Synchronization\\SynchronizeTime') do
|
|
10
|
+
it { should be_enabled }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe windows_task('\\Microsoft\\Windows\\AppID\\PolicyConverter') do
|
|
14
|
+
it { should be_disabled }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe windows_task('\\Microsoft\\Windows\\Defrag\\ScheduledDefrag') do
|
|
18
|
+
it { should exist }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe windows_task('\\Microsoft\\Windows\\AppID\\PolicyConverter') do
|
|
22
|
+
its('logon_mode') { should eq 'Interactive/Background' }
|
|
23
|
+
its('last_result') { should eq '1' }
|
|
24
|
+
its('task_to_run') { should cmp '%Windir%\\system32\\appidpolicyconverter.exe' }
|
|
25
|
+
its('run_as_user') { should eq 'LOCAL SERVICE' }
|
|
26
|
+
end
|
|
27
|
+
"
|
|
28
|
+
|
|
29
|
+
def initialize(taskuri)
|
|
30
|
+
@taskuri = taskuri
|
|
31
|
+
@cache = nil
|
|
32
|
+
|
|
33
|
+
# verify that this resource is only supported on Windows
|
|
34
|
+
return skip_resource 'The `windows_task` resource is not supported on your OS.' unless inspec.os.windows?
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def exists?
|
|
38
|
+
return true unless info.nil? || info[:uri].nil?
|
|
39
|
+
false
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# rubocop:disable Style/WordArray
|
|
43
|
+
def enabled?
|
|
44
|
+
return false if info.nil? || info[:state].nil?
|
|
45
|
+
['Ready', 'Running'].include?(info[:state])
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def disabled?
|
|
49
|
+
return false if info.nil? || info[:state].nil?
|
|
50
|
+
info[:scheduled_task_state] == 'Disabled' || info[:state] == 'Disabled'
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def logon_mode
|
|
54
|
+
info[:logon_mode]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def last_result
|
|
58
|
+
info[:last_result]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def task_to_run
|
|
62
|
+
info[:task_to_run].to_s.strip
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def run_as_user
|
|
66
|
+
info[:run_as_user]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def type
|
|
70
|
+
info[:type] unless info.nil?
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def info
|
|
74
|
+
return @cache unless @cache.nil?
|
|
75
|
+
# PowerShell v5 has Get-ScheduledTask cmdlet,
|
|
76
|
+
# _using something with backward support to v3_
|
|
77
|
+
# script = "Get-ScheduledTask | ? { $_.URI -eq '#{@taskuri}' } | Select-Object URI,@{N='State';E={$_.State.ToString()}} | ConvertTo-Json"
|
|
78
|
+
|
|
79
|
+
# Using schtasks as suggested by @modille but aligning property names to match cmdlet to future proof.
|
|
80
|
+
script = "schtasks /query /v /fo csv /tn '#{@taskuri}' | ConvertFrom-Csv | Select @{N='URI';E={$_.TaskName}},@{N='State';E={$_.Status.ToString()}},'Logon Mode','Last Result','Task To Run','Run As User','Scheduled Task State' | ConvertTo-Json -Compress"
|
|
81
|
+
|
|
82
|
+
cmd = inspec.powershell(script)
|
|
83
|
+
|
|
84
|
+
begin
|
|
85
|
+
params = JSON.parse(cmd.stdout)
|
|
86
|
+
rescue JSON::ParserError => _e
|
|
87
|
+
return nil
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
@cache = {
|
|
91
|
+
uri: params['URI'],
|
|
92
|
+
state: params['State'],
|
|
93
|
+
logon_mode: params['Logon Mode'],
|
|
94
|
+
last_result: params['Last Result'],
|
|
95
|
+
task_to_run: params['Task To Run'],
|
|
96
|
+
run_as_user: params['Run As User'],
|
|
97
|
+
scheduled_task_state: params['Scheduled Task State'],
|
|
98
|
+
type: 'windows-task',
|
|
99
|
+
}
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def to_s
|
|
103
|
+
"Windows Task '#{@taskuri}'"
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# author: Richard Nixon
|
|
3
|
+
# author: Christoph Hartmann
|
|
4
|
+
|
|
5
|
+
require 'openssl'
|
|
6
|
+
require 'hashie/mash'
|
|
7
|
+
|
|
8
|
+
module Inspec::Resources
|
|
9
|
+
class X509CertificateResource < Inspec.resource(1) # rubocop:disable Metrics/ClassLength
|
|
10
|
+
name 'x509_certificate'
|
|
11
|
+
desc 'Used to test x.509 certificates'
|
|
12
|
+
example "
|
|
13
|
+
describe x509_certificate('/etc/pki/www.mywebsite.com.pem') do
|
|
14
|
+
its('subject') { should match /CN=My Website/ }
|
|
15
|
+
its('validity_in_days') { should be > 30 }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe x509_certificate('trials/x509/cert.pem') do
|
|
19
|
+
it { should be_certificate }
|
|
20
|
+
it { should be_valid }
|
|
21
|
+
its('fingerprint') { should eq '62b137bdf427e7273dc2e487877b3033e4c8ce17' }
|
|
22
|
+
its('signature_algorithm') { should eq 'sha1WithRSAEncryption' }
|
|
23
|
+
its('validity_in_days') { should_not be < 100 }
|
|
24
|
+
its('validity_in_days') { should be >= 100 }
|
|
25
|
+
its('subject_dn') { should eq '/C=DE/ST=Berlin/L=Berlin/O=InSpec/OU=Chef Software, Inc/CN=inspec.io/emailAddress=support@chef.io' }
|
|
26
|
+
its('subject.C') { should eq 'DE' }
|
|
27
|
+
its('subject.emailAddress') { should_not be_empty }
|
|
28
|
+
its('subject.emailAddress') { should eq 'support@chef.io' }
|
|
29
|
+
its('issuer_dn') { should eq '/C=DE/ST=Berlin/L=Berlin/O=InSpec/OU=Chef Software, Inc/CN=inspec.io/emailAddress=support@chef.io' }
|
|
30
|
+
its('key_length') { should be >= 2048 }
|
|
31
|
+
its('extensions.subjectKeyIdentifier') { should cmp 'A5:16:0B:12:F4:48:0F:06:6C:32:29:67:98:12:DF:3D:0D:75:9D:5C' }
|
|
32
|
+
end
|
|
33
|
+
"
|
|
34
|
+
|
|
35
|
+
# @see https://tools.ietf.org/html/rfc5280#page-23
|
|
36
|
+
def initialize(filename)
|
|
37
|
+
@certpath = filename
|
|
38
|
+
@issuer = nil
|
|
39
|
+
@parsed_subject = nil
|
|
40
|
+
@parsed_issuer = nil
|
|
41
|
+
@extensions = nil
|
|
42
|
+
|
|
43
|
+
file = inspec.file(@certpath)
|
|
44
|
+
return skip_resource "Unable to find certificate file #{@certpath}" unless file.exist?
|
|
45
|
+
|
|
46
|
+
begin
|
|
47
|
+
@cert = OpenSSL::X509::Certificate.new file.content
|
|
48
|
+
rescue OpenSSL::X509::CertificateError
|
|
49
|
+
@cert = nil
|
|
50
|
+
return skip_resource "Unable to load certificate #{@certpath}"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Forward these methods directly to OpenSSL::X509::Certificate instance
|
|
55
|
+
%w{version not_before not_after signature_algorithm public_key }.each do |m|
|
|
56
|
+
define_method m.to_sym do |*args|
|
|
57
|
+
@cert.method(m.to_sym).call(*args)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def certificate?
|
|
62
|
+
!@cert.nil?
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def fingerprint
|
|
66
|
+
return if @cert.nil?
|
|
67
|
+
OpenSSL::Digest::SHA1.new(@cert.to_der).to_s
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def serial
|
|
71
|
+
return if @cert.nil?
|
|
72
|
+
@cert.serial.to_i
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def subject_dn
|
|
76
|
+
return if @cert.nil?
|
|
77
|
+
@cert.subject.to_s
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def subject
|
|
81
|
+
return if @cert.nil?
|
|
82
|
+
# Return cached subject if we have already parsed it
|
|
83
|
+
return @parsed_subject if @parsed_subject
|
|
84
|
+
# Use a Mash to make it easier to access hash elements in "its('subject') {should ...}"
|
|
85
|
+
@parsed_subject = Hashie::Mash.new(Hash[@cert.subject.to_a.map { |k, v, _| [k, v] }])
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def issuer_dn
|
|
89
|
+
return if @cert.nil?
|
|
90
|
+
@cert.issuer.to_s
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def issuer
|
|
94
|
+
return if @cert.nil?
|
|
95
|
+
# Return cached subject if we have already parsed it
|
|
96
|
+
return @parsed_issuer if @parsed_issuer
|
|
97
|
+
# Use a Mash to make it easier to access hash elements in "its('issuer') {should ...}"
|
|
98
|
+
@parsed_issuer = Hashie::Mash.new(Hash[@cert.issuer.to_a.map { |k, v, _| [k, v] }])
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def key_length
|
|
102
|
+
return if @cert.nil?
|
|
103
|
+
@cert.public_key.n.num_bytes * 8
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def validity_in_days
|
|
107
|
+
(not_after - Time.now.utc) / 86400
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def valid?
|
|
111
|
+
now = Time.now
|
|
112
|
+
certificate? && (now >= not_before && now <= not_after)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def extensions
|
|
116
|
+
# Return cached Mash if we already parsed the certificate extensions
|
|
117
|
+
return @extensions if @extensions
|
|
118
|
+
# Return the exception class if we failed to instantiate a Cert from file
|
|
119
|
+
return @cert unless @cert.respond_to? :extensions
|
|
120
|
+
# Use a Mash to make it easier to access hash elements in "its('entensions') {should ...}"
|
|
121
|
+
@extensions = Hashie::Mash.new({})
|
|
122
|
+
# Make sure standard extensions exist so we don't get nil for nil:NilClass
|
|
123
|
+
# when the user tests for extensions which aren't present
|
|
124
|
+
%w{
|
|
125
|
+
keyUsage extendedKeyUsage basicConstraints subjectKeyIdentifier
|
|
126
|
+
authorityKeyIdentifier subjectAltName issuerAltName authorityInfoAccess
|
|
127
|
+
crlDistributionPoints issuingDistributionPoint certificatePolicies
|
|
128
|
+
policyConstraints nameConstraints noCheck tlsfeature nsComment
|
|
129
|
+
}.each { |extension| @extensions[extension] ||= [] }
|
|
130
|
+
# Now parse the extensions into the Mash
|
|
131
|
+
extension_array = @cert.extensions.map(&:to_s)
|
|
132
|
+
extension_array.each do |extension|
|
|
133
|
+
kv = extension.split(/ *= */, 2)
|
|
134
|
+
@extensions[kv.first] = kv.last.split(/ *, */)
|
|
135
|
+
end
|
|
136
|
+
@extensions
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def to_s
|
|
140
|
+
"x509_certificate #{@certpath}"
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
data/lib/resources/xinetd.rb
CHANGED
|
@@ -41,6 +41,7 @@ module Inspec::Resources
|
|
|
41
41
|
.add(:ids, field: 'id')
|
|
42
42
|
.add(:socket_types, field: 'socket_type')
|
|
43
43
|
.add(:types, field: 'type')
|
|
44
|
+
.add(:protocols, field: 'protocol')
|
|
44
45
|
.add(:wait, field: 'wait')
|
|
45
46
|
.add(:disabled?) { |x| x.where('disable' => 'no').services.empty? }
|
|
46
47
|
.add(:enabled?) { |x| x.where('disable' => 'yes').services.empty? }
|
|
@@ -56,7 +57,7 @@ module Inspec::Resources
|
|
|
56
57
|
end
|
|
57
58
|
|
|
58
59
|
@contents[path] = file.content
|
|
59
|
-
if @contents[path].
|
|
60
|
+
if @contents[path].nil? || @contents[path].empty?
|
|
60
61
|
return skip_resource "Can't read file \"#{path}\""
|
|
61
62
|
end
|
|
62
63
|
|
|
@@ -91,8 +92,23 @@ module Inspec::Resources
|
|
|
91
92
|
params
|
|
92
93
|
end
|
|
93
94
|
|
|
95
|
+
# Method used to derive the default protocol used from the socket_type
|
|
96
|
+
def default_protocol(type)
|
|
97
|
+
case type
|
|
98
|
+
when 'stream'
|
|
99
|
+
'tcp'
|
|
100
|
+
when 'dgram'
|
|
101
|
+
'udp'
|
|
102
|
+
else
|
|
103
|
+
'unknown'
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
94
107
|
def service_lines
|
|
95
|
-
@services ||= params['services'].values.flatten.map
|
|
108
|
+
@services ||= params['services'].values.flatten.map { |service|
|
|
109
|
+
service.params['protocol'] ||= default_protocol(service.params['socket_type'])
|
|
110
|
+
service.params
|
|
111
|
+
}
|
|
96
112
|
end
|
|
97
113
|
end
|
|
98
114
|
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# author: Jonathan Morley
|
|
3
|
+
|
|
4
|
+
module Inspec::Resources
|
|
5
|
+
class XmlConfig < JsonConfig
|
|
6
|
+
name 'xml'
|
|
7
|
+
desc 'Use the xml InSpec resource to test configuration data in an XML file'
|
|
8
|
+
example "
|
|
9
|
+
describe xml('default.xml') do
|
|
10
|
+
its('key/sub_key') { should eq(['value']) }
|
|
11
|
+
end
|
|
12
|
+
"
|
|
13
|
+
|
|
14
|
+
def parse(content)
|
|
15
|
+
require 'rexml/document'
|
|
16
|
+
REXML::Document.new(content)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def value(key)
|
|
20
|
+
REXML::XPath.each(@params, key.first.to_s).map(&:text)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def to_s
|
|
24
|
+
"XML #{@path}"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
data/lib/resources/yaml.rb
CHANGED
|
@@ -14,8 +14,16 @@ module Inspec::Resources
|
|
|
14
14
|
name 'yaml'
|
|
15
15
|
desc 'Use the yaml InSpec audit resource to test configuration data in a YAML file.'
|
|
16
16
|
example "
|
|
17
|
-
describe yaml do
|
|
18
|
-
its('name') { should eq '
|
|
17
|
+
describe yaml('config.yaml') do
|
|
18
|
+
its(['driver', 'name']) { should eq 'vagrant' }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe yaml({ command: 'retrieve_data.py --yaml' }) do
|
|
22
|
+
its('state') { should eq 'open' }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
describe yaml({ content: \"key1: value1\nkey2: value2\" }) do
|
|
26
|
+
its('key2') { should cmp 'value2' }
|
|
19
27
|
end
|
|
20
28
|
"
|
|
21
29
|
|
data/lib/resources/yum.rb
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
# author: Christoph Hartmann
|
|
3
3
|
# author: Dominik Richter
|
|
4
4
|
|
|
5
|
-
require 'resources/file'
|
|
6
|
-
|
|
7
5
|
# Usage:
|
|
8
6
|
# describe yum do
|
|
9
7
|
# its('repos') { should exist }
|
|
@@ -22,6 +20,7 @@ require 'resources/file'
|
|
|
22
20
|
# describe yum.repo('epel') do
|
|
23
21
|
# it { should exist }
|
|
24
22
|
# it { should be_enabled }
|
|
23
|
+
# its('baseurl') { should include 'mycompany.biz' }
|
|
25
24
|
# end
|
|
26
25
|
#
|
|
27
26
|
# deprecated:
|
|
@@ -33,7 +32,7 @@ require 'resources/file'
|
|
|
33
32
|
module Inspec::Resources
|
|
34
33
|
class Yum < Inspec.resource(1)
|
|
35
34
|
name 'yum'
|
|
36
|
-
desc 'Use the yum InSpec audit resource to test
|
|
35
|
+
desc 'Use the yum InSpec audit resource to test the configuration of Yum repositories.'
|
|
37
36
|
example "
|
|
38
37
|
describe yum.repo('name') do
|
|
39
38
|
it { should exist }
|
|
@@ -121,19 +120,38 @@ module Inspec::Resources
|
|
|
121
120
|
def info
|
|
122
121
|
return @cache if defined?(@cache)
|
|
123
122
|
selection = @yum.repositories.select { |e| e['id'] == @reponame || shortname(e['id']) == @reponame }
|
|
124
|
-
@cache = selection
|
|
123
|
+
@cache = selection.empty? ? {} : selection.first
|
|
125
124
|
@cache
|
|
126
125
|
end
|
|
127
126
|
|
|
128
127
|
def exist?
|
|
129
|
-
!info.
|
|
128
|
+
!info.empty?
|
|
130
129
|
end
|
|
131
130
|
|
|
132
131
|
def enabled?
|
|
133
|
-
|
|
134
|
-
return false if repo.nil?
|
|
132
|
+
return false unless exist?
|
|
135
133
|
info['status'] == 'enabled'
|
|
136
134
|
end
|
|
135
|
+
|
|
136
|
+
# provide a method for each of the repo metadata items we know about
|
|
137
|
+
[
|
|
138
|
+
:baseurl,
|
|
139
|
+
:expire,
|
|
140
|
+
:filename,
|
|
141
|
+
:mirrors,
|
|
142
|
+
:pkgs,
|
|
143
|
+
:size,
|
|
144
|
+
:status,
|
|
145
|
+
:updated,
|
|
146
|
+
].each do |key|
|
|
147
|
+
define_method key do
|
|
148
|
+
info[key.to_s]
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def to_s
|
|
153
|
+
"YumRepo #{@reponame}"
|
|
154
|
+
end
|
|
137
155
|
end
|
|
138
156
|
|
|
139
157
|
# for compatability with serverspec
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# author: Joseph Benden
|
|
3
|
+
|
|
4
|
+
module Inspec::Resources
|
|
5
|
+
class ZfsDataset < Inspec.resource(1)
|
|
6
|
+
name 'zfs_dataset'
|
|
7
|
+
desc "
|
|
8
|
+
Use the zfs_dataset InSpec audit resource to test if the named
|
|
9
|
+
ZFS Dataset is present and/or has certain properties.
|
|
10
|
+
"
|
|
11
|
+
example "
|
|
12
|
+
describe zfs_dataset('tank/tmp') do
|
|
13
|
+
its('exec') { should eq('off') }
|
|
14
|
+
its('setuid') { should eq('off') }
|
|
15
|
+
end
|
|
16
|
+
"
|
|
17
|
+
|
|
18
|
+
def initialize(zfs_dataset)
|
|
19
|
+
return skip_resource 'The `zfs_dataset` resource is not supported on your OS yet.' if !inspec.os.bsd?
|
|
20
|
+
@zfs_dataset = zfs_dataset
|
|
21
|
+
|
|
22
|
+
@params = gather
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# method called by 'it { should exist }'
|
|
26
|
+
def exists?
|
|
27
|
+
inspec.command("/sbin/zfs get -Hp all #{@zfs_dataset}").exit_status == 0
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def mounted?
|
|
31
|
+
return false if !exists?
|
|
32
|
+
inspec.mount(@params['mountpoint']).mounted?
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def to_s
|
|
36
|
+
"ZFS Dataset #{@zfs_dataset}"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def gather
|
|
40
|
+
cmd = inspec.command("/sbin/zfs get -Hp all #{@zfs_dataset}")
|
|
41
|
+
return nil if cmd.exit_status.to_i != 0
|
|
42
|
+
|
|
43
|
+
# parse data
|
|
44
|
+
cmd.stdout.chomp.split("\n").each_with_object(Hash.new(0)) do |line, h|
|
|
45
|
+
t = line.split("\t")
|
|
46
|
+
h[t[1].to_s] = t[2].to_s
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# override method
|
|
51
|
+
def exec
|
|
52
|
+
@params['exec']
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# expose all parameters
|
|
56
|
+
def method_missing(name)
|
|
57
|
+
@params[name.to_s]
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# author: Joseph Benden
|
|
3
|
+
|
|
4
|
+
module Inspec::Resources
|
|
5
|
+
class ZfsPool < Inspec.resource(1)
|
|
6
|
+
name 'zfs_pool'
|
|
7
|
+
desc "
|
|
8
|
+
Use the zfs_pool InSpec audit resource to test if the named
|
|
9
|
+
ZFS Pool is present and/or has certain properties.
|
|
10
|
+
"
|
|
11
|
+
example "
|
|
12
|
+
describe zfs_pool('tank') do
|
|
13
|
+
its('failmode') { should eq('continue') }
|
|
14
|
+
end
|
|
15
|
+
"
|
|
16
|
+
|
|
17
|
+
def initialize(zfs_pool)
|
|
18
|
+
return skip_resource 'The `zfs_pool` resource is not supported on your OS yet.' if !inspec.os.bsd?
|
|
19
|
+
@zfs_pool = zfs_pool
|
|
20
|
+
|
|
21
|
+
@params = gather
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# method called by 'it { should exist }'
|
|
25
|
+
def exists?
|
|
26
|
+
inspec.command("/sbin/zpool get -Hp all #{@zfs_pool}").exit_status == 0
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def to_s
|
|
30
|
+
"ZFS Pool #{@zfs_pool}"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def gather
|
|
34
|
+
cmd = inspec.command("/sbin/zpool get -Hp all #{@zfs_pool}")
|
|
35
|
+
return nil if cmd.exit_status.to_i != 0
|
|
36
|
+
|
|
37
|
+
# parse data
|
|
38
|
+
cmd.stdout.chomp.split("\n").each_with_object(Hash.new(0)) do |line, h|
|
|
39
|
+
t = line.split("\t")
|
|
40
|
+
h[t[1].to_s] = t[2].to_s
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# expose all parameters
|
|
45
|
+
def method_missing(name)
|
|
46
|
+
@params[name.to_s]
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
data/lib/source_readers/flat.rb
CHANGED
|
@@ -20,13 +20,14 @@ module SourceReaders
|
|
|
20
20
|
new(target, files)
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
attr_reader :metadata, :tests, :libraries
|
|
23
|
+
attr_reader :metadata, :tests, :libraries, :data_files
|
|
24
24
|
|
|
25
25
|
def initialize(target, files)
|
|
26
26
|
@target = target
|
|
27
27
|
@metadata = ::Inspec::Metadata.new(nil)
|
|
28
28
|
@tests = load_tests(files)
|
|
29
29
|
@libraries = {}
|
|
30
|
+
@data_files = {}
|
|
30
31
|
end
|
|
31
32
|
|
|
32
33
|
private
|
|
@@ -23,33 +23,52 @@ module SourceReaders
|
|
|
23
23
|
nil
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
attr_reader :metadata, :tests, :libraries
|
|
26
|
+
attr_reader :metadata, :tests, :libraries, :data_files
|
|
27
27
|
|
|
28
|
+
# This create a new instance of an InSpec profile source reader
|
|
29
|
+
#
|
|
30
|
+
# @param [FileProvider] target An instance of a FileProvider object that can list files and read them
|
|
31
|
+
# @param [String] metadata_source eg. inspec.yml or metadata.rb
|
|
28
32
|
def initialize(target, metadata_source)
|
|
29
|
-
@target
|
|
30
|
-
@metadata
|
|
33
|
+
@target = target
|
|
34
|
+
@metadata = load_metadata(metadata_source)
|
|
35
|
+
@tests = load_tests
|
|
36
|
+
@libraries = load_libs
|
|
37
|
+
@data_files = load_data_files
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def load_metadata(metadata_source)
|
|
43
|
+
Inspec::Metadata.from_ref(
|
|
31
44
|
metadata_source,
|
|
32
45
|
@target.read(metadata_source),
|
|
33
46
|
nil)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
47
|
+
rescue Psych::SyntaxError => e
|
|
48
|
+
raise "Unable to parse inspec.yml: line #{e.line}, #{e.problem} #{e.context}"
|
|
49
|
+
rescue => e
|
|
50
|
+
raise "Unable to parse #{metadata_source}: #{e.class} -- #{e.message}"
|
|
37
51
|
end
|
|
38
52
|
|
|
39
|
-
private
|
|
40
|
-
|
|
41
53
|
def load_tests
|
|
42
54
|
tests = @target.files.find_all do |path|
|
|
43
|
-
path.start_with?('controls'
|
|
55
|
+
path.start_with?('controls') && path.end_with?('.rb')
|
|
44
56
|
end
|
|
45
|
-
Hash[tests.map { |x| [x, @target.read(x)] }]
|
|
57
|
+
Hash[tests.map { |x| [x, @target.read(x)] }.delete_if { |_file, contents| contents.nil? }]
|
|
46
58
|
end
|
|
47
59
|
|
|
48
60
|
def load_libs
|
|
49
61
|
tests = @target.files.find_all do |path|
|
|
50
62
|
path.start_with?('libraries') && path.end_with?('.rb')
|
|
51
63
|
end
|
|
52
|
-
Hash[tests.map { |x| [x, @target.read(x)] }]
|
|
64
|
+
Hash[tests.map { |x| [x, @target.read(x)] }.delete_if { |_file, contents| contents.nil? }]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def load_data_files
|
|
68
|
+
files = @target.files.find_all do |path|
|
|
69
|
+
path.start_with?('files' + File::SEPARATOR)
|
|
70
|
+
end
|
|
71
|
+
Hash[files.map { |x| [x, @target.read(x)] }.delete_if { |_file, contents| contents.nil? }]
|
|
53
72
|
end
|
|
54
73
|
end
|
|
55
74
|
end
|
|
@@ -9,20 +9,20 @@ class CommandWrapper
|
|
|
9
9
|
|
|
10
10
|
def self.wrap(cmd, options)
|
|
11
11
|
unless options.is_a?(Hash)
|
|
12
|
-
|
|
12
|
+
raise 'All options for the command wrapper must be provided as a hash. '\
|
|
13
13
|
"You entered: #{options.inspect}. Please consult the documentation."
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
wrap = options[:wrap]
|
|
17
17
|
if !wrap.nil? && !wrap.is_a?(Proc)
|
|
18
|
-
|
|
18
|
+
raise "Called command wrapper with wrap: #{wrap.inspect}. It must be called with a Proc."
|
|
19
19
|
elsif !wrap.nil?
|
|
20
20
|
return wrap.call(cmd)
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
shell = options[:shell]
|
|
24
24
|
unless UNIX_SHELLS.include?(shell)
|
|
25
|
-
|
|
25
|
+
raise "Don't know how to wrap commands for shell: #{shell.inspect}."
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
path = options[:path] || shell
|