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,77 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# author: Christoph Hartmann
|
|
3
|
+
# author: Dominik Richter
|
|
4
|
+
|
|
5
|
+
module DatabaseHelper
|
|
6
|
+
class SQLColumn
|
|
7
|
+
def initialize(row, name)
|
|
8
|
+
@row = row
|
|
9
|
+
@name = name
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def value
|
|
13
|
+
@row[@name.downcase]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def to_s
|
|
17
|
+
'SQL Column'
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class SQLRow
|
|
22
|
+
def initialize(query, row)
|
|
23
|
+
@query = query
|
|
24
|
+
@row = row
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def column(column)
|
|
28
|
+
SQLColumn.new(@row, column)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def to_s
|
|
32
|
+
'SQL Row'
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class SQLQueryResult
|
|
37
|
+
attr_reader :error
|
|
38
|
+
def initialize(cmd, results)
|
|
39
|
+
@cmd = cmd
|
|
40
|
+
@results = results
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def empty?
|
|
44
|
+
@results.empty?
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def successful?
|
|
48
|
+
@cmd.exit_status == 0 && @error.nil?
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def row(id)
|
|
52
|
+
SQLRow.new(self, @results[id])
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def size
|
|
56
|
+
@results.size
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def stdout
|
|
60
|
+
warn '[DEPRECATION] The `stdout` method is deprecated. Use `row` instead.'
|
|
61
|
+
@cmd.stdout
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def stderr
|
|
65
|
+
warn '[DEPRECATION] The `stderr` method is deprecated. Use `successful?` instead.'
|
|
66
|
+
@cmd.stderr
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def inspect
|
|
70
|
+
to_s
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def to_s
|
|
74
|
+
'SQL ResultSet'
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# author: Dominik Richter
|
|
3
|
+
# author: Christoph Hartmann
|
|
4
|
+
|
|
5
|
+
require 'parslet'
|
|
6
|
+
|
|
7
|
+
class ErlangParser < Parslet::Parser
|
|
8
|
+
root :outermost
|
|
9
|
+
# only designed for rabbitmq config files for now:
|
|
10
|
+
rule(:outermost) { filler? >> array.maybe >> dot.maybe }
|
|
11
|
+
|
|
12
|
+
rule(:exp) {
|
|
13
|
+
(tuple | array | binary | string | bool | identifier | float | integer) >> filler?
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
rule(:array) {
|
|
17
|
+
str('[') >> filler? >> (
|
|
18
|
+
exp.repeat(1) >>
|
|
19
|
+
(comma >> exp).repeat
|
|
20
|
+
).maybe.as(:array) >> str(']') >> filler?
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
rule(:tuple) {
|
|
24
|
+
str('{') >> filler? >> (
|
|
25
|
+
exp.repeat(1) >> filler? >>
|
|
26
|
+
(comma >> exp).repeat
|
|
27
|
+
).maybe.as(:tuple) >> str('}') >> filler?
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
rule(:filler?) { space.repeat }
|
|
31
|
+
rule(:space) { match('\s+') | match["\n"] | comment }
|
|
32
|
+
|
|
33
|
+
rule(:comment) { str('%') >> (match["\n\r"].absent? >> any).repeat }
|
|
34
|
+
rule(:comma) { str(',') >> filler? }
|
|
35
|
+
rule(:dot) { str('.') >> filler? }
|
|
36
|
+
rule(:bool) { str('true').as(:bool) | str('false').as(:bool) }
|
|
37
|
+
|
|
38
|
+
rule(:identifier) {
|
|
39
|
+
(match('[a-zA-Z]') >> match('[a-zA-Z0-9_]').repeat).as(:identifier) >> filler?
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
rule(:float) {
|
|
43
|
+
(
|
|
44
|
+
integer >> (
|
|
45
|
+
str('.') >> match('[0-9]').repeat(1) |
|
|
46
|
+
str('e') >> match('[0-9]').repeat(1)
|
|
47
|
+
).as(:e)
|
|
48
|
+
).as(:float) >> filler?
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
rule(:integer) {
|
|
52
|
+
((str('+') | str('-')).maybe >> match('[0-9]').repeat(1)).as(:integer) >> filler?
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
rule(:string) { stringS | stringD }
|
|
56
|
+
|
|
57
|
+
rule(:stringS) {
|
|
58
|
+
str("'") >> (
|
|
59
|
+
str('\\') >> any | str("'").absent? >> any
|
|
60
|
+
).repeat.as(:string) >> str("'") >> filler?
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
rule(:stringD) {
|
|
64
|
+
str('"') >> (
|
|
65
|
+
str('\\') >> any | str('"').absent? >> any
|
|
66
|
+
).repeat.as(:string) >> str('"') >> filler?
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
rule(:binary_item) {
|
|
70
|
+
(string | integer) >>
|
|
71
|
+
(str(':') >> integer).maybe.as(:size) >>
|
|
72
|
+
(str('/') >> identifier).maybe.as(:type) >>
|
|
73
|
+
filler?
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
rule(:binary) {
|
|
77
|
+
str('<<') >> filler? >> (
|
|
78
|
+
binary_item.repeat(1) >>
|
|
79
|
+
(comma >> binary_item).repeat
|
|
80
|
+
).maybe.as(:binary) >> str('>>') >> filler?
|
|
81
|
+
}
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
class ErlangBitstream
|
|
85
|
+
def initialize
|
|
86
|
+
@data = [] # a stream of 8-bit numbers
|
|
87
|
+
@cur_bits = '' # a string of binary bits 10010010...
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
TYPES = {
|
|
91
|
+
'integer' => 8,
|
|
92
|
+
'float' => 8*8,
|
|
93
|
+
'utf8' => 8,
|
|
94
|
+
'utf16' => 8*2,
|
|
95
|
+
'utf32' => 8*4,
|
|
96
|
+
}.freeze
|
|
97
|
+
|
|
98
|
+
def bit_size(size, type)
|
|
99
|
+
raise 'Cannot specify size and type at the same time.' if !type.nil? && !size.nil?
|
|
100
|
+
return (size || 8).to_i if type.nil?
|
|
101
|
+
TYPES[type] || raise("Cannot handle binary-stream type #{type}")
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def add(i)
|
|
105
|
+
if i[:integer].nil? && i[:string].nil?
|
|
106
|
+
raise 'No data provided, internal error for binary-stream processing!'
|
|
107
|
+
end
|
|
108
|
+
s = bit_size(i[:size], i[:type])
|
|
109
|
+
unless i[:string].nil?
|
|
110
|
+
str2int(i[:string].to_s, i[:type]).map { |e| add_bits(int2bits(e, 8)) }
|
|
111
|
+
else
|
|
112
|
+
add_int(i[:integer], s)
|
|
113
|
+
end
|
|
114
|
+
rescue RuntimeError => e
|
|
115
|
+
raise 'Error processing Erlang bit string '\
|
|
116
|
+
"'#{i[:string] || i[:integer]}:#{i[:size]}/#{i[:type]}'. #{e.message}"
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def str2int(s, type)
|
|
120
|
+
case type
|
|
121
|
+
when 'utf8' then s.encode('utf-8').unpack('C*')
|
|
122
|
+
when 'utf16' then s.encode('utf-16').unpack('C*').drop(2)
|
|
123
|
+
when 'utf32' then s.encode('utf-32').unpack('C*').drop(4)
|
|
124
|
+
when 'integer', 'float' then raise "Cannot handle bit string as type #{type}"
|
|
125
|
+
else s.split('').map { |x| x.ord & 0xff }
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def int2bits(i, len)
|
|
130
|
+
format("%0#{len}b", i)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def add_int(v, size)
|
|
134
|
+
x = v.to_i & (2**size - 1) # only get the bits specified in size
|
|
135
|
+
add_bits(int2bits(x, size))
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def add_bits(s)
|
|
139
|
+
b = (@cur_bits + s).scan(/.{1,8}/)
|
|
140
|
+
@data += b[0..-2].map { |x| x.to_i(2) }
|
|
141
|
+
@cur_bits = b.last
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def value(encoding = 'utf-8')
|
|
145
|
+
# fill in the rest
|
|
146
|
+
rest = '0' * (8 - @cur_bits.length) + @cur_bits
|
|
147
|
+
arr = @data + [rest.to_i(2)]
|
|
148
|
+
s = arr.pack('C*')
|
|
149
|
+
s.force_encoding(encoding) unless encoding.nil?
|
|
150
|
+
s
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
class ErlangTransform < Parslet::Transform
|
|
155
|
+
class Tuple < Array; end
|
|
156
|
+
class Identifier < String; end
|
|
157
|
+
|
|
158
|
+
def self.assemble_binary(seq)
|
|
159
|
+
b = ErlangBitstream.new
|
|
160
|
+
seq.each { |i| b.add(i) }
|
|
161
|
+
b.value
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
rule(string: simple(:x)) { x.to_s }
|
|
165
|
+
rule(string: []) { '' }
|
|
166
|
+
rule(integer: simple(:x)) { x.to_i }
|
|
167
|
+
rule(float: { integer: simple(:a), e: simple(:b) }) { (a+b).to_f }
|
|
168
|
+
rule(bool: 'true') { true }
|
|
169
|
+
rule(bool: 'false') { false }
|
|
170
|
+
rule(binary: subtree(:x)) { x.nil? ? '' : ErlangTransform.assemble_binary(x) }
|
|
171
|
+
rule(identifier: simple(:x)) { Identifier.new(x.to_s) }
|
|
172
|
+
rule(array: subtree(:x)) { Array(x) }
|
|
173
|
+
rule(tuple: subtree(:x)) {
|
|
174
|
+
x.nil? ? Tuple.new : Tuple.new(x)
|
|
175
|
+
}
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
class ErlangConfigFile
|
|
179
|
+
def self.parse(content)
|
|
180
|
+
lex = ErlangParser.new.parse(content)
|
|
181
|
+
tree = ErlangTransform.new.apply(lex)
|
|
182
|
+
turn_to_hash(tree)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def self.turn_to_hash(t)
|
|
186
|
+
if t.is_a?(Array) && t.all? { |x| x.class == ErlangTransform::Tuple && x.length == 2 }
|
|
187
|
+
Hash[t.map { |i| [i[0], turn_to_hash(i[1])] }]
|
|
188
|
+
else
|
|
189
|
+
t
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
data/lib/utils/filter.rb
CHANGED
|
@@ -44,6 +44,7 @@ module FilterTable
|
|
|
44
44
|
def initialize(resource, params, filters)
|
|
45
45
|
@resource = resource
|
|
46
46
|
@params = params
|
|
47
|
+
@params = [] if @params.nil?
|
|
47
48
|
@filters = filters
|
|
48
49
|
end
|
|
49
50
|
|
|
@@ -69,7 +70,7 @@ module FilterTable
|
|
|
69
70
|
end
|
|
70
71
|
|
|
71
72
|
def new_entry(*_)
|
|
72
|
-
|
|
73
|
+
raise "#{self.class} must not be used on its own. It must be inherited "\
|
|
73
74
|
'and the #new_entry method must be implemented. This is an internal '\
|
|
74
75
|
'error and should not happen.'
|
|
75
76
|
end
|
data/lib/utils/filter_array.rb
CHANGED
data/lib/utils/find_files.rb
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
# copyright: 2015, Vulcano Security GmbH
|
|
3
|
-
# license: All rights reserved
|
|
4
3
|
# author: Dominik Richter
|
|
5
4
|
# author: Christoph Hartmann
|
|
6
5
|
|
|
@@ -26,8 +25,8 @@ module FindFiles
|
|
|
26
25
|
type = TYPES[opts[:type].to_sym] if opts[:type]
|
|
27
26
|
|
|
28
27
|
cmd = "find #{path}"
|
|
29
|
-
cmd += " -maxdepth #{depth.to_i}" if depth.to_i > 0
|
|
30
28
|
cmd += " -type #{type}" unless type.nil?
|
|
29
|
+
cmd += " -maxdepth #{depth.to_i}" if depth.to_i > 0
|
|
31
30
|
|
|
32
31
|
result = inspec.command(cmd)
|
|
33
32
|
exit_status = result.exit_status
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# author: Christoph Hartmann
|
|
3
|
+
|
|
4
|
+
require 'json'
|
|
5
|
+
require 'net/http'
|
|
6
|
+
|
|
7
|
+
class LatestInSpecVersion
|
|
8
|
+
# fetches the latest version from rubygems server
|
|
9
|
+
def latest
|
|
10
|
+
uri = URI('https://rubygems.org/api/v1/gems/inspec.json')
|
|
11
|
+
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https',
|
|
12
|
+
open_timeout: 0.5, read_timeout: 0.5
|
|
13
|
+
) {|http|
|
|
14
|
+
http.get(uri.path)
|
|
15
|
+
}
|
|
16
|
+
inspec_info = JSON.parse(res.body)
|
|
17
|
+
inspec_info['version']
|
|
18
|
+
rescue Exception # rubocop:disable Lint/RescueException
|
|
19
|
+
nil
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# author: Dominik Richter
|
|
3
|
+
# author: Christoph Hartmann
|
|
4
|
+
|
|
5
|
+
require 'parslet'
|
|
6
|
+
|
|
7
|
+
class NginxParser < Parslet::Parser
|
|
8
|
+
root :outermost
|
|
9
|
+
# only designed for rabbitmq config files for now:
|
|
10
|
+
rule(:outermost) { filler? >> exp.repeat }
|
|
11
|
+
|
|
12
|
+
rule(:filler?) { one_filler.repeat }
|
|
13
|
+
rule(:one_filler) { match('\s+') | match["\n"] | comment }
|
|
14
|
+
rule(:space) { match('\s+') }
|
|
15
|
+
rule(:comment) { str('#') >> (match["\n\r"].absent? >> any).repeat }
|
|
16
|
+
|
|
17
|
+
rule(:exp) {
|
|
18
|
+
section | assignment
|
|
19
|
+
}
|
|
20
|
+
rule(:assignment) {
|
|
21
|
+
(identifier >> values.maybe.as(:args)).as(:assignment) >> str(';') >> filler?
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
rule(:identifier) {
|
|
25
|
+
(match('[a-zA-Z]') >> match('\S').repeat).as(:identifier) >> space >> space.repeat
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
rule(:value) {
|
|
29
|
+
((match('[#;{]').absent? >> any) >> (
|
|
30
|
+
str('\\') >> any | match('[#;{]|\s').absent? >> any
|
|
31
|
+
).repeat).as(:value) >> space.repeat
|
|
32
|
+
}
|
|
33
|
+
rule(:values) {
|
|
34
|
+
value.repeat >> space.maybe
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
rule(:section) {
|
|
38
|
+
identifier.as(:section) >> values.maybe.as(:args) >> str('{') >> filler? >> exp.repeat.as(:expressions) >> str('}') >> filler?
|
|
39
|
+
}
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class NginxTransform < Parslet::Transform
|
|
43
|
+
Group = Struct.new(:id, :args, :body)
|
|
44
|
+
Exp = Struct.new(:key, :vals)
|
|
45
|
+
|
|
46
|
+
def self.assemble_binary(seq)
|
|
47
|
+
b = ErlangBitstream.new
|
|
48
|
+
seq.each { |i| b.add(i) }
|
|
49
|
+
b.value
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
rule(section: { identifier: simple(:x) }, args: subtree(:y), expressions: subtree(:z)) { Group.new(x.to_s, y, z) }
|
|
53
|
+
rule(assignment: { identifier: simple(:x), args: subtree(:y) }) { Exp.new(x.to_s, y) }
|
|
54
|
+
rule(value: simple(:x)) { x.to_s }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
class NginxConfig
|
|
58
|
+
def self.parse(content)
|
|
59
|
+
lex = NginxParser.new.parse(content)
|
|
60
|
+
tree = NginxTransform.new.apply(lex)
|
|
61
|
+
gtree = NginxTransform::Group.new(nil, '', tree)
|
|
62
|
+
read_nginx_group(gtree)
|
|
63
|
+
rescue Parslet::ParseFailed => err
|
|
64
|
+
raise "Failed to parse NginX config: #{err}"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def self.read_nginx_group(t)
|
|
68
|
+
agg_conf = Hash.new([])
|
|
69
|
+
agg_conf['_'] = t.args unless t.args == ''
|
|
70
|
+
|
|
71
|
+
groups, conf = t.body.partition { |i| i.is_a? NginxTransform::Group }
|
|
72
|
+
conf.each { |x| agg_conf[x.key] += [x.vals] }
|
|
73
|
+
groups.each { |x| agg_conf[x.id] += [read_nginx_group(x)] }
|
|
74
|
+
agg_conf
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -6,11 +6,12 @@ module ObjectTraverser
|
|
|
6
6
|
key = keys.shift
|
|
7
7
|
return nil if key.nil? || value.nil?
|
|
8
8
|
|
|
9
|
-
# if value is an array, iterate over each child
|
|
10
9
|
if value.is_a?(Array)
|
|
11
|
-
value =
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
value = if key.is_a?(Fixnum)
|
|
11
|
+
value[key]
|
|
12
|
+
elsif value.respond_to?(key.to_sym)
|
|
13
|
+
value.send(key.to_sym)
|
|
14
|
+
end
|
|
14
15
|
else
|
|
15
16
|
value = value[key.to_s].nil? ? nil : value[key.to_s]
|
|
16
17
|
end
|
data/lib/utils/parser.rb
CHANGED
|
@@ -63,7 +63,7 @@ module CommentParser
|
|
|
63
63
|
end
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
-
module
|
|
66
|
+
module LinuxMountParser
|
|
67
67
|
# this parses the output of mount command (only tested on linux)
|
|
68
68
|
# this method expects only one line of the mount output
|
|
69
69
|
def parse_mount_options(mount_line, compatibility = false)
|
|
@@ -94,6 +94,20 @@ module MountParser
|
|
|
94
94
|
end
|
|
95
95
|
end
|
|
96
96
|
|
|
97
|
+
module BsdMountParser
|
|
98
|
+
# this parses the output of mount command (only tested on freebsd)
|
|
99
|
+
# this method expects only one line of the mount output
|
|
100
|
+
def parse_mount_options(mount_line, _compatibility = false)
|
|
101
|
+
return {} if mount_line.nil? || mount_line.empty?
|
|
102
|
+
|
|
103
|
+
mount = mount_line.chomp.split(' ', 4)
|
|
104
|
+
options = mount[3].tr('()', '').split(', ')
|
|
105
|
+
|
|
106
|
+
# parse device and type
|
|
107
|
+
{ device: mount[0], type: options.shift, options: options }
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
97
111
|
module SolarisNetstatParser
|
|
98
112
|
# takes this as a input and parses the values
|
|
99
113
|
# UDP: IPv4
|
|
@@ -197,7 +211,7 @@ module XinetdParser
|
|
|
197
211
|
res = {}
|
|
198
212
|
cur_group = nil
|
|
199
213
|
simple_conf = []
|
|
200
|
-
rest = raw
|
|
214
|
+
rest = raw + "\n"
|
|
201
215
|
until rest.empty?
|
|
202
216
|
# extract content line
|
|
203
217
|
nl = rest.index("\n") || (rest.length-1)
|
|
@@ -209,7 +223,12 @@ module XinetdParser
|
|
|
209
223
|
next if inner_line.empty?
|
|
210
224
|
|
|
211
225
|
if inner_line == '}'
|
|
212
|
-
|
|
226
|
+
if cur_group == 'defaults'
|
|
227
|
+
res[cur_group] = SimpleConfig.new(simple_conf.join("\n"))
|
|
228
|
+
else
|
|
229
|
+
res[cur_group] ||= []
|
|
230
|
+
res[cur_group].push(SimpleConfig.new(simple_conf.join("\n")))
|
|
231
|
+
end
|
|
213
232
|
cur_group = nil
|
|
214
233
|
elsif rest.lstrip[0] == '{'
|
|
215
234
|
cur_group = inner_line
|
|
@@ -224,7 +243,7 @@ module XinetdParser
|
|
|
224
243
|
others.each { |ores|
|
|
225
244
|
ores.each { |k, v|
|
|
226
245
|
res[k] ||= []
|
|
227
|
-
res[k].
|
|
246
|
+
res[k].concat(v)
|
|
228
247
|
}
|
|
229
248
|
}
|
|
230
249
|
else
|
|
@@ -39,7 +39,7 @@ class PluginRegistry
|
|
|
39
39
|
#
|
|
40
40
|
# @return [PluginRegistry] plugin registry for this plugin
|
|
41
41
|
def self.plugin_registry
|
|
42
|
-
|
|
42
|
+
raise "Plugin #{self} does not implement `self.plugin_registry()`. This method is required"
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
# Register a new plugin by name
|
|
@@ -47,7 +47,7 @@ class PluginRegistry
|
|
|
47
47
|
# @param [String] the unique name of this plugin
|
|
48
48
|
# @return [nil] disregard
|
|
49
49
|
def self.name(name)
|
|
50
|
-
|
|
50
|
+
raise "Trying to register #{self} with name == nil" if name.nil?
|
|
51
51
|
@name = name
|
|
52
52
|
plugin_registry.registry[name] = self
|
|
53
53
|
end
|
|
@@ -72,7 +72,7 @@ class PluginRegistry
|
|
|
72
72
|
# @param [String] target to try to resolve
|
|
73
73
|
# @return [Plugin] instance if it can be resolved, nil otherwise
|
|
74
74
|
def self.resolve(_target)
|
|
75
|
-
|
|
75
|
+
raise "Plugin #{self} does not implement `self.resolve(target)`. This method is required"
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
# When a plugin's resolve doesn't lead to the final state, it can
|
data/lib/utils/simpleconfig.rb
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
# copyright: 2015, Dominik Richter
|
|
3
|
-
# license: All rights reserved
|
|
4
3
|
# author: Dominik Richter
|
|
5
4
|
# author: Christoph Hartmann
|
|
6
5
|
|
|
@@ -33,7 +32,7 @@ class SimpleConfig
|
|
|
33
32
|
raw_data = raw_data.tr(options[:line_separator], "\n")
|
|
34
33
|
end
|
|
35
34
|
rest = raw_data
|
|
36
|
-
rest = parse_rest(rest, options)
|
|
35
|
+
rest = parse_rest(rest, options) until rest.empty?
|
|
37
36
|
end
|
|
38
37
|
|
|
39
38
|
private
|
|
@@ -55,16 +54,28 @@ class SimpleConfig
|
|
|
55
54
|
end
|
|
56
55
|
|
|
57
56
|
def parse_params_line(line, opts)
|
|
57
|
+
# Deprecation handling
|
|
58
|
+
if opts.key?(:assignment_re)
|
|
59
|
+
warn '[DEPRECATION] `:assignment_re` is deprecated in favor of `:assignment_regex` '\
|
|
60
|
+
'and will be removed in the next major version. See: https://github.com/chef/inspec/issues/1709'
|
|
61
|
+
opts[:assignment_regex] = opts[:assignment_re]
|
|
62
|
+
end
|
|
63
|
+
if opts.key?(:key_vals)
|
|
64
|
+
warn '[DEPRECATION] `:key_vals` is deprecated in favor of `:key_values` '\
|
|
65
|
+
'and will be removed in the next major version. See: https://github.com/chef/inspec/issues/1709'
|
|
66
|
+
opts[:key_values] = opts[:key_vals]
|
|
67
|
+
end
|
|
68
|
+
|
|
58
69
|
# now line contains what we are interested in parsing
|
|
59
70
|
# check if it is an assignment
|
|
60
|
-
m = opts[:
|
|
71
|
+
m = opts[:assignment_regex].match(line)
|
|
61
72
|
return nil if m.nil?
|
|
62
73
|
|
|
63
74
|
if opts[:multiple_values]
|
|
64
75
|
@vals[m[1]] ||= []
|
|
65
|
-
@vals[m[1]].push(parse_values(m, opts[:
|
|
76
|
+
@vals[m[1]].push(parse_values(m, opts[:key_values]))
|
|
66
77
|
else
|
|
67
|
-
@vals[m[1]] = parse_values(m, opts[:
|
|
78
|
+
@vals[m[1]] = parse_values(m, opts[:key_values])
|
|
68
79
|
end
|
|
69
80
|
end
|
|
70
81
|
|
|
@@ -73,7 +84,13 @@ class SimpleConfig
|
|
|
73
84
|
m = opts[:group_re].match(line)
|
|
74
85
|
return nil if m.nil?
|
|
75
86
|
@groups.push(m[1])
|
|
76
|
-
|
|
87
|
+
|
|
88
|
+
# We use a Hashie::Mash to provide method syntax for retrieving
|
|
89
|
+
# values. For configs that have keys whose values may be hashes
|
|
90
|
+
# (such as a mysql config that has [sections]), providing
|
|
91
|
+
# a hash whose values are accessible via methods provide
|
|
92
|
+
# a better user experience with `its` blocks.
|
|
93
|
+
@vals = @params[m[1]] = Hashie::Mash.new
|
|
77
94
|
end
|
|
78
95
|
|
|
79
96
|
def parse_implicit_assignment_line(line, opts)
|
|
@@ -105,9 +122,9 @@ class SimpleConfig
|
|
|
105
122
|
multiline: false,
|
|
106
123
|
comment_char: '#',
|
|
107
124
|
line_separator: nil, # uses this char to seperate lines before parsing
|
|
108
|
-
|
|
125
|
+
assignment_regex: /^\s*([^=]*?)\s*=\s*(.*?)\s*$/,
|
|
109
126
|
group_re: /\[([^\]]+)\]\s*$/,
|
|
110
|
-
|
|
127
|
+
key_values: 1, # default for key=value, may require for 'key val1 val2 val3'
|
|
111
128
|
standalone_comments: false,
|
|
112
129
|
multiple_values: false,
|
|
113
130
|
}
|
data/lib/utils/spdx.rb
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# author: Christoph Hartmann
|
|
3
|
+
# author: Dominik Richter
|
|
4
|
+
class Spdx
|
|
5
|
+
def self.licenses
|
|
6
|
+
spdx_file = File.join(File.dirname(__FILE__), 'spdx.txt').freeze
|
|
7
|
+
File.read(spdx_file).split("\n")
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.valid_license?(license)
|
|
11
|
+
licenses.include?(license)
|
|
12
|
+
end
|
|
13
|
+
end
|