inspec 0.34.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +323 -6
  3. data/Gemfile +10 -0
  4. data/README.md +1 -1
  5. data/Rakefile +4 -55
  6. data/docs/.gitignore +2 -0
  7. data/docs/README.md +40 -0
  8. data/docs/cli.md +342 -0
  9. data/docs/dsl_inspec.md +245 -0
  10. data/docs/dsl_resource.md +93 -0
  11. data/docs/inspec_and_friends.md +105 -0
  12. data/docs/matchers.md +136 -0
  13. data/docs/plugin_kitchen_inspec.html.md +55 -0
  14. data/docs/profiles.md +285 -0
  15. data/docs/resources/apache_conf.md.erb +75 -0
  16. data/docs/resources/apt.md.erb +84 -0
  17. data/docs/resources/audit_policy.md.erb +61 -0
  18. data/docs/resources/auditd_conf.md.erb +79 -0
  19. data/docs/resources/auditd_rules.md.erb +132 -0
  20. data/docs/resources/bash.md.erb +84 -0
  21. data/docs/resources/bond.md.erb +97 -0
  22. data/docs/resources/bridge.md.erb +67 -0
  23. data/docs/resources/bsd_service.md.erb +76 -0
  24. data/docs/resources/command.md.erb +151 -0
  25. data/docs/resources/csv.md.erb +62 -0
  26. data/docs/resources/directory.md.erb +43 -0
  27. data/docs/resources/etc_group.md.erb +116 -0
  28. data/docs/resources/etc_passwd.md.erb +155 -0
  29. data/docs/resources/etc_shadow.md.erb +149 -0
  30. data/docs/resources/file.md.erb +460 -0
  31. data/docs/resources/gem.md.erb +73 -0
  32. data/docs/resources/group.md.erb +74 -0
  33. data/docs/resources/grub_conf.md.erb +115 -0
  34. data/docs/resources/host.md.erb +85 -0
  35. data/docs/resources/iis_site.md.erb +142 -0
  36. data/docs/resources/inetd_conf.md.erb +99 -0
  37. data/docs/resources/ini.md.erb +69 -0
  38. data/docs/resources/interface.md.erb +66 -0
  39. data/docs/resources/iptables.md.erb +70 -0
  40. data/docs/resources/json.md.erb +76 -0
  41. data/docs/resources/kernel_module.md.erb +60 -0
  42. data/docs/resources/kernel_parameter.md.erb +72 -0
  43. data/docs/resources/launchd_service.md.erb +76 -0
  44. data/docs/resources/limits_conf.md.erb +80 -0
  45. data/docs/resources/login_def.md.erb +77 -0
  46. data/docs/resources/mount.md.erb +83 -0
  47. data/docs/resources/mysql_conf.md.erb +102 -0
  48. data/docs/resources/mysql_session.md.erb +63 -0
  49. data/docs/resources/npm.md.erb +75 -0
  50. data/docs/resources/ntp_conf.md.erb +76 -0
  51. data/docs/resources/oneget.md.erb +67 -0
  52. data/docs/resources/os.md.erb +154 -0
  53. data/docs/resources/os_env.md.erb +98 -0
  54. data/docs/resources/package.md.erb +115 -0
  55. data/docs/resources/parse_config.md.erb +122 -0
  56. data/docs/resources/parse_config_file.md.erb +143 -0
  57. data/docs/resources/pip.md.erb +74 -0
  58. data/docs/resources/port.md.erb +150 -0
  59. data/docs/resources/postgres_conf.md.erb +90 -0
  60. data/docs/resources/postgres_session.md.erb +75 -0
  61. data/docs/resources/powershell.md.erb +116 -0
  62. data/docs/resources/process.md.erb +73 -0
  63. data/docs/resources/registry_key.md.erb +149 -0
  64. data/docs/resources/runit_service.md.erb +76 -0
  65. data/docs/resources/security_policy.md.erb +61 -0
  66. data/docs/resources/service.md.erb +135 -0
  67. data/docs/resources/ssh_config.md.erb +94 -0
  68. data/docs/resources/sshd_config.md.erb +97 -0
  69. data/docs/resources/ssl.md.erb +133 -0
  70. data/docs/resources/sys_info.md.erb +55 -0
  71. data/docs/resources/systemd_service.md.erb +76 -0
  72. data/docs/resources/sysv_service.md.erb +76 -0
  73. data/docs/resources/upstart_service.md.erb +76 -0
  74. data/docs/resources/user.md.erb +154 -0
  75. data/docs/resources/users.md.erb +140 -0
  76. data/docs/resources/vbscript.md.erb +69 -0
  77. data/docs/resources/windows_feature.md.erb +61 -0
  78. data/docs/resources/wmi.md.erb +95 -0
  79. data/docs/resources/xinetd_conf.md.erb +170 -0
  80. data/docs/resources/yaml.md.erb +69 -0
  81. data/docs/resources/yum.md.erb +103 -0
  82. data/docs/ruby_usage.md +154 -0
  83. data/docs/shared/matcher_be.md.erb +1 -0
  84. data/docs/shared/matcher_cmp.md.erb +45 -0
  85. data/docs/shared/matcher_eq.md.erb +3 -0
  86. data/docs/shared/matcher_include.md.erb +1 -0
  87. data/docs/shared/matcher_match.md.erb +1 -0
  88. data/docs/shell.md +150 -0
  89. data/examples/meta-profile/inspec.yml +2 -4
  90. data/inspec.gemspec +1 -1
  91. data/lib/bundles/inspec-compliance/api.rb +28 -18
  92. data/lib/bundles/inspec-compliance/cli.rb +19 -27
  93. data/lib/bundles/inspec-compliance/target.rb +15 -2
  94. data/lib/fetchers/git.rb +4 -0
  95. data/lib/fetchers/local.rb +16 -1
  96. data/lib/fetchers/mock.rb +4 -0
  97. data/lib/fetchers/url.rb +46 -20
  98. data/lib/inspec/base_cli.rb +14 -0
  99. data/lib/inspec/cached_fetcher.rb +67 -0
  100. data/lib/inspec/cli.rb +22 -8
  101. data/lib/inspec/control_eval_context.rb +12 -2
  102. data/lib/inspec/dependencies/{vendor_index.rb → cache.rb} +5 -4
  103. data/lib/inspec/dependencies/dependency_set.rb +8 -14
  104. data/lib/inspec/dependencies/lockfile.rb +5 -13
  105. data/lib/inspec/dependencies/requirement.rb +31 -41
  106. data/lib/inspec/dependencies/resolver.rb +3 -3
  107. data/lib/inspec/dsl.rb +16 -4
  108. data/lib/inspec/errors.rb +1 -0
  109. data/lib/inspec/fetcher.rb +25 -1
  110. data/lib/inspec/objects/each_loop.rb +5 -2
  111. data/lib/inspec/objects/test.rb +8 -2
  112. data/lib/inspec/plugins/fetcher.rb +13 -12
  113. data/lib/inspec/plugins/resource.rb +3 -0
  114. data/lib/inspec/profile.rb +62 -26
  115. data/lib/inspec/profile_context.rb +44 -8
  116. data/lib/inspec/resource.rb +18 -3
  117. data/lib/inspec/rspec_json_formatter.rb +91 -40
  118. data/lib/inspec/rule.rb +45 -2
  119. data/lib/inspec/runner.rb +51 -39
  120. data/lib/inspec/shell.rb +5 -16
  121. data/lib/inspec/version.rb +1 -1
  122. data/lib/resources/apache_conf.rb +1 -1
  123. data/lib/resources/gem.rb +1 -0
  124. data/lib/resources/groups.rb +190 -0
  125. data/lib/resources/oneget.rb +1 -0
  126. data/lib/resources/os.rb +1 -1
  127. data/lib/resources/package.rb +3 -1
  128. data/lib/resources/parse_config.rb +18 -1
  129. data/lib/resources/pip.rb +1 -1
  130. data/lib/resources/security_policy.rb +54 -0
  131. data/lib/resources/ssl.rb +9 -11
  132. data/lib/resources/sys_info.rb +1 -1
  133. data/lib/resources/users.rb +81 -64
  134. metadata +91 -17
  135. data/docs/cli.rst +0 -442
  136. data/docs/dsl_inspec.rst +0 -259
  137. data/docs/dsl_resource.rst +0 -90
  138. data/docs/inspec_and_friends.rst +0 -85
  139. data/docs/matchers.rst +0 -137
  140. data/docs/profiles.rst +0 -169
  141. data/docs/readme.rst +0 -105
  142. data/docs/resources.rst +0 -4836
  143. data/docs/ruby_usage.rst +0 -145
  144. data/docs/shell.rst +0 -130
  145. data/docs/template.rst +0 -51
  146. data/lib/resources/group.rb +0 -137
data/docs/ruby_usage.rst DELETED
@@ -1,145 +0,0 @@
1
- =====================================================
2
- Using |ruby| in InSpec
3
- =====================================================
4
-
5
- The |inspec| DSL is a |ruby| based DSL for writing audit controls, which includes audit resources that you can invoke.
6
- Core and custom resources are written as regular |ruby| classes which inherit from ``Inspec.resource``.
7
-
8
- Assuming we have a |json| file like this on the node to be tested:
9
-
10
- .. code-block:: json
11
-
12
- {
13
- "keys":[
14
- {"username":"john", "key":"/opt/keys/johnd.key"},
15
- {"username":"jane", "key":"/opt/keys/janed.key"},
16
- {"username":"sunny ", "key":"/opt/keys/sunnym.key"}
17
- ]
18
- }
19
-
20
- The following example shows how you can use pure |ruby| code(variables, loops, conditionals, regular expressions, etc) to run a few tests against the above |json| file:
21
-
22
- .. code-block:: ruby
23
-
24
- control 'check-interns' do
25
- # use the json inspec resource to get the file
26
- json_obj = json('/opt/keys/interns.json')
27
- describe json_obj do
28
- its('keys') { should_not eq nil }
29
- end
30
- if json_obj['keys']
31
- # loop over the keys array
32
- json_obj['keys'].each do |intern|
33
- username = intern['username'].strip
34
- # check for white spaces chars in usernames
35
- describe username do
36
- it { should_not match(/\s/) }
37
- end
38
- # check key file owners and permissions
39
- describe file(intern['key']) do
40
- it { should be_owned_by username }
41
- its('mode') { should cmp '0600' }
42
- end
43
- end
44
- end
45
- end
46
-
47
- Execution
48
- =====================================================
49
-
50
- It's important to understand that |ruby| code used in custom resources and controls DSL is executed on the system that runs |inspec|. This allows |inspec| to work without |ruby| and rubygems being required on remote targets(servers or containers).
51
-
52
- For example, using ```ls``` or ``system('ls')`` will result in the ``ls`` command being run locally and not on the target(remote) system.
53
- In order to process the output of ``ls`` executed on the target system, use ``inspec.command('ls')`` or ``inspec.powershell('ls')``
54
-
55
- Similarly, use ``inspec.file(PATH)`` to access files or directories from remote systems in your tests or custom resources.
56
-
57
- Using rubygems
58
- =====================================================
59
-
60
- |ruby| gems are self-contained programs and libraries ...
61
-
62
-
63
- Interactive Debugging with Pry
64
- =====================================================
65
-
66
- Here's a sample |inspec| control that users |ruby| variables to instantiate an |inspec| resource once and use the content in multipLe tests.
67
-
68
- .. code-block:: ruby
69
-
70
- control 'check-perl' do
71
- impact 0.3
72
- title 'Check perl compiled options and permissions'
73
- perl_out = command('perl -V')
74
- #require 'pry'; binding.pry;
75
- describe perl_out do
76
- its('exit_status') { should eq 0 }
77
- its('stdout') { should match (/USE_64_BIT_ALL/) }
78
- its('stdout') { should match (/useposix=true/) }
79
- its('stdout') { should match (/-fstack-protector/) }
80
- end
81
-
82
- # extract an array of include directories
83
- perl_inc = perl_out.stdout.partition('@INC:').last.strip.split("\n")
84
- # ensure include directories are only writable by 'owner'
85
- perl_inc.each do |path|
86
- describe directory(path.strip) do
87
- it { should_not be_writable.by('group') }
88
- it { should_not be_writable.by('other') }
89
- end
90
- end
91
- end
92
-
93
- An **advanced** but very useful |ruby| tip. In the previous example, I commented out the ``require 'pry'; binding.pry;`` line. If you remove the ``#`` prefix and run the control, the execution will stop at that line and give you a ``pry`` shell. Use that to troubleshoot, print variables, see methods available, etc. For the above example:
94
-
95
- .. code-block:: ruby
96
-
97
- [1] pry> perl_out.exit_status
98
- => 0
99
- [2] pry> perl_out.stderr
100
- => ""
101
- [3] pry> ls perl_out
102
- Inspec::Plugins::Resource#methods: inspect
103
- Inspec::Resources::Cmd#methods: command exist? exit_status result stderr stdout to_s
104
- Inspec::Plugins::ResourceCommon#methods: resource_skipped skip_resource
105
- Inspec::Resource::Registry::Command#methods: inspec
106
- instance variables: @__backend_runner__ @__resource_name__ @command @result
107
- [4] pry> perl_out.stdout.partition('@INC:').last.strip.split("\n")
108
- => ["/Library/Perl/5.18/darwin-thread-multi-2level",
109
- " /Library/Perl/5.18",
110
- ...REDACTED...
111
- [5] pry> exit # or abort
112
-
113
- You can use ``pry`` inside both the controls DSL and resources.
114
- Similarly, for dev and test, you can use ``inspec shell`` which is based on ``pry``, for example:
115
-
116
- .. code-block:: ruby
117
-
118
- $ inspec shell
119
- Welcome to the interactive InSpec Shell
120
- To find out how to use it, type: help
121
-
122
- inspec> command('ls /home/gordon/git/inspec/docs').stdout
123
- => "ctl_inspec.rst\ndsl_inspec.rst\ndsl_resource.rst\n"
124
- inspec> command('ls').stdout.split("\n")
125
- => ["ctl_inspec.rst", "dsl_inspec.rst", "dsl_resource.rst"]
126
-
127
- inspec> help command
128
- Name: command
129
-
130
- Description:
131
- Use the command InSpec audit resource to test an arbitrary command that is run on the system.
132
-
133
- Example:
134
- describe command('ls -al /') do
135
- it { should exist }
136
- its('stdout') { should match /bin/ }
137
- its('stderr') { should eq '' }
138
- its('exit_status') { should eq 0 }
139
- end
140
-
141
- .. |inspec| replace:: InSpec
142
- .. |chef compliance| replace:: Chef Compliance
143
- .. |ruby| replace:: Ruby
144
- .. |csv| replace:: CSV
145
- .. |json| replace:: JSON
data/docs/shell.rst DELETED
@@ -1,130 +0,0 @@
1
- =====================================================
2
- InSpec Shell Usage
3
- =====================================================
4
-
5
- The InSpec interactive shell is a pry based REPL that can be used to quickly run InSpec controls and tests without having to write it to a file. Its functionality is similar to ``chef shell`` - it provides a way to exercise the InSpec DSL, its resources, tests and plugins without having to create a profile or write a test file. See http://pryrepl.org/ for an introduction to what pry is and what it can do.
6
-
7
-
8
- Launching the shell
9
- -----------------------------------------------------
10
-
11
- If you are using InSpec from a platform-specific package (rpm, msi, etc.) or from a chef prepared shell in ChefDK, you can directly launch InSpec shell against your local machine using the following. See https://docs.chef.io/install_dk.html#set-system-ruby for details.
12
-
13
- .. code-block:: bash
14
-
15
- $ inspec shell
16
- $ inspec help shell # This will describe inspec shell usage
17
-
18
- If you wish to connect to a remote machine (called a target within InSpec), you can use the ``-t`` flag. We support connecting using ssh, WinRm and docker. If no target is provided, we implicitly support the "local" target - i.e. tests running on the current machine running InSpec. For an ssh connection, use ``-i`` for specifying ssh key files, and the ``--sudo*`` commands for requesting a privelege escalation after logging in. For a WinRM connection, use ``--path`` to change the login path, ``--ssl`` to use SSL for transport layer encryption.
19
-
20
- .. code-block:: bash
21
-
22
- $ inspec shell -t ssh://root@192.168.64.2:11022 # Login to remote machine using ssh as root.
23
- $ inspec shell -t ssh://user@hostname:1234 -i /path/to/user_key # Login to hostname on port 1234 as user using given ssh key.
24
- $ inspec shell -t winrm://UserName:Password@windowsmachine:1234 # Login to windowsmachine over WinRM as UserName.
25
- $ inspec shell -t docker://container_id # Login to a docker container.
26
-
27
-
28
- Using Ruby in InSpec shell
29
- -----------------------------------------------------
30
-
31
- Since InSpec shell is pry based, you may treat the shell as an interactive Ruby session. You may write Ruby expressions and evaluate them. Source high-lighting, automatic indentation and command history (using the up and down arrow keys) are available to make your experience more delightful. You can exit the shell using ``exit``.
32
-
33
- .. code-block:: bash
34
-
35
- $ inspec shell
36
- Welcome to the interactive InSpec Shell
37
- To find out how to use it, type: help
38
-
39
- inspec> 1 + 2
40
- => 3
41
- inspec> exit
42
-
43
-
44
- Using InSpec DSL in InSpec shell
45
- -----------------------------------------------------
46
-
47
- InSpec shell will automatically evaluate the result of every command as if it were a test file. If you type in a Ruby command that is not an InSpec control or test, the shell will evaluate it as if it were a regular ruby command.
48
-
49
- Bare InSpec resources are instantiated and their help text is presented. You may also access the resource contents or other matchers that they define. Run ``help <resource>`` to get more help on using a particular resource or see the InSpec resources documentation online.
50
-
51
- .. code-block:: bash
52
-
53
- $ inspec shell
54
- Welcome to the interactive InSpec Shell
55
- To find out how to use it, type: help
56
-
57
- inspec> file('/Users/ksubramanian').directory?
58
- => true
59
- inspec> os_env('HOME')
60
- => Environment variable HOME
61
- inspec> os_env('HOME').content
62
- => /Users/ksubramanian
63
- inspec> exit
64
-
65
- InSpec tests are immediately executed.
66
-
67
-
68
- .. code-block:: bash
69
-
70
- inspec> describe file('/Users') # Empty test.
71
- Summary: 0 successful, 0 failures, 0 skipped
72
- inspec> describe file('/Users') do # Test with one check.
73
- inspec> it { should exist }
74
- inspec> end
75
- ✔ File /Users should exist
76
-
77
- Summary: 1 successful, 0 failures, 0 skipped
78
-
79
-
80
- All tests in a control are immediately executed as well. If a control is redefined in the shell, the old control's tests are destroyed and replaced with the redefinition and the control is re-run.
81
-
82
- .. code-block:: bash
83
-
84
- inspec> control 'my_control' do
85
- inspec> describe os_env('HOME') do
86
- inspec> its('content') { should eq '/Users/ksubramanian' }
87
- inspec> end
88
- inspec> end
89
- ✔ my_control: Environment variable HOME content should eq "/Users/ksubramanian"
90
-
91
- Summary: 1 successful, 0 failures, 0 skipped
92
-
93
- Syntax errors are illegal tests are also detected and reported.
94
-
95
-
96
- .. code-block:: bash
97
-
98
- inspec> control 'foo' do
99
- inspec> thisisnonsense
100
- inspec> end
101
- NameError: undefined local variable or method `thisisnonsense' for #<#<Class:0x007fd63b571f98>:0x007fd639825cc8>
102
- from /usr/local/lib/ruby/gems/2.3.0/gems/rspec-expectations-3.5.0/lib/rspec/matchers.rb:967:in `method_missing'
103
- inspec> control 'foo' do
104
- inspec> describe file('wut') do
105
- inspec> its('thismakesnosense') { should cmp 'fail' }
106
- inspec> end
107
- inspec> end
108
- ✖ foo: File wut thismakesnosense (undefined method `thismakesnosense' for File wut:Inspec::Resource::Registry::File)
109
-
110
- Summary: 0 successful, 1 failures, 0 skipped
111
-
112
-
113
- Running a single InSpec command
114
- -----------------------------------------------------
115
-
116
- If you wish to run a single InSpec command and fetch its results, you may use the ``-c`` flag. This is similar to using ``bash -c``.
117
-
118
- .. code-block:: bash
119
- $ inspec shell -c 'describe file("/Users/ksubramanian") do it { should exist } end'
120
-
121
- Target: local://
122
-
123
- ✔ File /Users/ksubramanian should exist
124
-
125
- Summary: 1 successful, 0 failures, 0 skipped
126
-
127
-
128
- .. code-block:: bash
129
- $ inspec shell --format json -c 'describe file("/Users/ksubramanian") do it { should exist } end'
130
- {"version":"0.30.0","profiles":{"":{"supports":[],"controls":{"(generated from in_memory.rb:1 5aab65c33fb1f133d9244017958eef64)":{"title":null,"desc":null,"impact":0.5,"refs":[],"tags":{},"code":" rule = rule_class.new(id, profile_id, {}) do\n res = describe(*args, &block)\n end\n","source_location":{"ref":"/Users/ksubramanian/repo/chef/inspec/lib/inspec/profile_context.rb","line":184},"results":[{"status":"passed","code_desc":"File /Users/ksubramanian should exist","run_time":0.000747,"start_time":"2016-08-16 11:41:40 -0400"}]}},"groups":{"in_memory.rb":{"title":null,"controls":["(generated from in_memory.rb:1 5aab65c33fb1f133d9244017958eef64)"]}},"attributes":[]}},"other_checks":[],"summary":{"duration":0.001078,"example_count":1,"failure_count":0,"skip_count":0}}
data/docs/template.rst DELETED
@@ -1,51 +0,0 @@
1
- resource_name
2
- =====================================================
3
- Use the ``resource_name`` audit resource to xxxxx.
4
-
5
- Syntax
6
- -----------------------------------------------------
7
- A ``resource_name`` audit resource block declares xxxxx. For example:
8
-
9
- .. code-block:: ruby
10
-
11
- describe xxxxx(xxxxx) do
12
- it { should xxxxx }
13
- end
14
-
15
- where
16
-
17
- * ``xxxxx`` must specify xxxxx
18
- * xxxxx
19
- * ``xxxxx`` is a valid matcher for this audit resource
20
-
21
- Matchers
22
- -----------------------------------------------------
23
- This audit resource has the following matchers.
24
-
25
- xxxxx
26
- +++++++++++++++++++++++++++++++++++++++++++++++++++++
27
- The ``xxxxx`` matcher tests if xxxxx. For example:
28
-
29
- .. code-block:: ruby
30
-
31
- it { should xxxxx }
32
-
33
- xxxxx
34
- +++++++++++++++++++++++++++++++++++++++++++++++++++++
35
- The ``xxxxx`` matcher tests if xxxxx. For example:
36
-
37
- .. code-block:: ruby
38
-
39
- it { should xxxxx }
40
-
41
- Examples
42
- -----------------------------------------------------
43
- The following examples show how to use this audit resource in a recipe.
44
-
45
- **xxxxx**
46
-
47
- xxxxx
48
-
49
- **xxxxx**
50
-
51
- xxxxx
@@ -1,137 +0,0 @@
1
- # encoding: utf-8
2
- # author: Christoph Hartmann
3
- # author: Dominik Richter
4
-
5
- # Usage:
6
- # describe group('root') do
7
- # it { should exist }
8
- # its('gid') { should eq 0 }
9
- # end
10
- #
11
- # deprecated has matcher
12
- # describe group('root') do
13
- # it { should have_gid 0 }
14
- # end
15
-
16
- module Inspec::Resources
17
- class Group < Inspec.resource(1)
18
- name 'group'
19
- desc 'Use the group InSpec audit resource to test groups on the system.'
20
- example "
21
- describe group('root') do
22
- it { should exist }
23
- its('gid') { should eq 0 }
24
- end
25
- "
26
-
27
- def initialize(groupname, domain = nil)
28
- @group = groupname.downcase
29
- @domain = domain
30
- @domain = @domain.downcase unless @domain.nil?
31
-
32
- @cache = nil
33
-
34
- # select group manager
35
- @group_provider = nil
36
- if inspec.os.unix?
37
- @group_provider = UnixGroup.new(inspec)
38
- elsif inspec.os.windows?
39
- @group_provider = WindowsGroup.new(inspec)
40
- else
41
- return skip_resource 'The `group` resource is not supported on your OS yet.'
42
- end
43
- end
44
-
45
- # verifies if a group exists
46
- def exists?
47
- # ensure that we found one group
48
- !group_info.nil? && group_info.size > 0
49
- end
50
-
51
- def gid
52
- return nil if group_info.nil? || group_info.size == 0
53
-
54
- # the default case should be one group
55
- return group_info[0][:gid] if group_info.size == 1
56
-
57
- # return array if we got multiple gids
58
- group_info.map { |grp| grp[:gid] }
59
- end
60
-
61
- # implements rspec has matcher, to be compatible with serverspec
62
- def has_gid?(compare_gid)
63
- gid == compare_gid
64
- end
65
-
66
- def local
67
- return nil if group_info.nil? || group_info.size == 0
68
-
69
- # the default case should be one group
70
- return group_info[0][:local] if group_info.size == 1
71
-
72
- # return array if we got multiple gids
73
- group_info.map { |grp| grp[:local] }
74
- end
75
-
76
- def to_s
77
- "Group #{@group}"
78
- end
79
-
80
- private
81
-
82
- def group_info
83
- return @cache if !@cache.nil?
84
- @cache = @group_provider.group_info(@group, @domain) if !@group_provider.nil?
85
- end
86
- end
87
-
88
- class GroupInfo
89
- attr_reader :inspec
90
- def initialize(inspec)
91
- @inspec = inspec
92
- end
93
- end
94
-
95
- # implements generic unix groups via /etc/group
96
- class UnixGroup < GroupInfo
97
- def group_info(group, _domain = nil)
98
- inspec.etc_group.where(name: group).entries.map { |grp|
99
- {
100
- name: grp['name'],
101
- gid: grp['gid'],
102
- }
103
- }
104
- end
105
- end
106
-
107
- class WindowsGroup < GroupInfo
108
- def group_info(compare_group, compare_domain = nil)
109
- cmd = inspec.command('Get-WmiObject Win32_Group | Select-Object -Property Caption, Domain, Name, SID, LocalAccount | ConvertTo-Json')
110
-
111
- # cannot rely on exit code for now, successful command returns exit code 1
112
- # return nil if cmd.exit_status != 0, try to parse json
113
- begin
114
- groups = JSON.parse(cmd.stdout)
115
- rescue JSON::ParserError => _e
116
- return nil
117
- end
118
-
119
- # ensure we have an array of groups
120
- groups = [groups] if !groups.is_a?(Array)
121
-
122
- # reduce list
123
- groups.each_with_object([]) do |grp, grp_collection|
124
- # map object
125
- grp_info = {
126
- name: grp['Name'],
127
- domain: grp['Domain'],
128
- caption: grp['Caption'],
129
- gid: nil,
130
- sid: grp['SID'],
131
- local: grp['LocalAccount'],
132
- }
133
- return grp_collection.push(grp_info) if grp_info[:name].casecmp(compare_group) == 0 && (compare_domain.nil? || grp_info[:domain].casecmp(compare_domain) == 0)
134
- end
135
- end
136
- end
137
- end