inspec 1.31.0 → 1.45.9

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 (194) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/CHANGELOG.md +2599 -1
  4. data/Gemfile +0 -1
  5. data/README.md +24 -34
  6. data/Rakefile +0 -31
  7. data/docs/dsl_inspec.md +10 -0
  8. data/docs/matchers.md +29 -0
  9. data/docs/plugin_kitchen_inspec.md +18 -24
  10. data/docs/profiles.md +101 -81
  11. data/docs/resources/aide_conf.md.erb +71 -0
  12. data/docs/resources/apache_conf.md.erb +19 -33
  13. data/docs/resources/apt.md.erb +22 -36
  14. data/docs/resources/audit_policy.md.erb +9 -24
  15. data/docs/resources/auditd.md.erb +78 -0
  16. data/docs/resources/auditd_conf.md.erb +20 -34
  17. data/docs/resources/auditd_rules.md.erb +8 -24
  18. data/docs/resources/bash.md.erb +4 -26
  19. data/docs/resources/bond.md.erb +25 -40
  20. data/docs/resources/bridge.md.erb +5 -25
  21. data/docs/resources/bsd_service.md.erb +5 -25
  22. data/docs/resources/command.md.erb +35 -50
  23. data/docs/resources/cpan.md.erb +62 -0
  24. data/docs/resources/cran.md.erb +54 -0
  25. data/docs/resources/crontab.md.erb +9 -23
  26. data/docs/resources/csv.md.erb +12 -27
  27. data/docs/resources/dh_params.md +1 -0
  28. data/docs/resources/directory.md.erb +5 -25
  29. data/docs/resources/docker.md.erb +61 -58
  30. data/docs/resources/docker_container.md.erb +23 -19
  31. data/docs/resources/docker_image.md.erb +20 -16
  32. data/docs/resources/elasticsearch.md.erb +245 -0
  33. data/docs/resources/etc_fstab.md.erb +120 -0
  34. data/docs/resources/etc_group.md.erb +29 -45
  35. data/docs/resources/etc_hosts.md.erb +68 -0
  36. data/docs/resources/etc_hosts_allow.md.erb +68 -0
  37. data/docs/resources/etc_hosts_deny.md.erb +68 -0
  38. data/docs/resources/file.md.erb +227 -216
  39. data/docs/resources/firewalld.md.erb +104 -0
  40. data/docs/resources/gem.md.erb +21 -35
  41. data/docs/resources/group.md.erb +16 -30
  42. data/docs/resources/grub_conf.md.erb +9 -24
  43. data/docs/resources/host.md.erb +32 -49
  44. data/docs/resources/http.md.erb +38 -44
  45. data/docs/resources/iis_app.md.erb +25 -35
  46. data/docs/resources/iis_site.md.erb +26 -40
  47. data/docs/resources/inetd_conf.md.erb +27 -42
  48. data/docs/resources/ini.md.erb +9 -23
  49. data/docs/resources/interface.md.erb +5 -25
  50. data/docs/resources/iptables.md.erb +15 -29
  51. data/docs/resources/json.md.erb +12 -27
  52. data/docs/resources/kernel_module.md.erb +47 -61
  53. data/docs/resources/kernel_parameter.md.erb +15 -29
  54. data/docs/resources/key_rsa.md.erb +3 -0
  55. data/docs/resources/launchd_service.md.erb +5 -25
  56. data/docs/resources/limits_conf.md.erb +15 -29
  57. data/docs/resources/login_def.md.erb +15 -30
  58. data/docs/resources/mount.md.erb +18 -33
  59. data/docs/resources/mssql_session.md.erb +9 -12
  60. data/docs/resources/mysql_conf.md.erb +28 -32
  61. data/docs/resources/mysql_session.md.erb +15 -29
  62. data/docs/resources/nginx.md.erb +78 -0
  63. data/docs/resources/nginx_conf.md.erb +127 -0
  64. data/docs/resources/npm.md.erb +19 -35
  65. data/docs/resources/ntp_conf.md.erb +20 -37
  66. data/docs/resources/oneget.md.erb +15 -30
  67. data/docs/resources/oracledb_session.md.erb +9 -11
  68. data/docs/resources/os.md.erb +29 -43
  69. data/docs/resources/os_env.md.erb +23 -44
  70. data/docs/resources/package.md.erb +34 -36
  71. data/docs/resources/parse_config.md.erb +5 -25
  72. data/docs/resources/parse_config_file.md.erb +31 -43
  73. data/docs/resources/{etc_passwd.md.erb → passwd.md.erb} +24 -39
  74. data/docs/resources/pip.md.erb +20 -35
  75. data/docs/resources/port.md.erb +43 -57
  76. data/docs/resources/postgres_conf.md.erb +17 -31
  77. data/docs/resources/postgres_hba_conf.md.erb +26 -38
  78. data/docs/resources/postgres_ident_conf.md.erb +25 -37
  79. data/docs/resources/postgres_session.md.erb +15 -29
  80. data/docs/resources/powershell.md.erb +27 -42
  81. data/docs/resources/processes.md.erb +17 -33
  82. data/docs/resources/rabbitmq_config.md.erb +9 -24
  83. data/docs/resources/registry_key.md.erb +27 -42
  84. data/docs/resources/runit_service.md.erb +5 -25
  85. data/docs/resources/security_policy.md.erb +12 -27
  86. data/docs/resources/service.md.erb +27 -42
  87. data/docs/resources/{etc_shadow.md.erb → shadow.md.erb} +41 -47
  88. data/docs/resources/ssh_config.md.erb +19 -34
  89. data/docs/resources/sshd_config.md.erb +19 -34
  90. data/docs/resources/ssl.md.erb +39 -54
  91. data/docs/resources/sys_info.md.erb +12 -26
  92. data/docs/resources/systemd_service.md.erb +5 -25
  93. data/docs/resources/sysv_service.md.erb +5 -25
  94. data/docs/resources/upstart_service.md.erb +5 -25
  95. data/docs/resources/user.md.erb +29 -44
  96. data/docs/resources/users.md.erb +12 -26
  97. data/docs/resources/vbscript.md.erb +9 -24
  98. data/docs/resources/virtualization.md.erb +8 -23
  99. data/docs/resources/windows_feature.md.erb +15 -30
  100. data/docs/resources/windows_hotfix.md.erb +50 -0
  101. data/docs/resources/windows_task.md.erb +12 -26
  102. data/docs/resources/wmi.md.erb +9 -24
  103. data/docs/resources/x509_certificate.md.erb +4 -0
  104. data/docs/resources/xinetd_conf.md.erb +65 -80
  105. data/docs/resources/xml.md.erb +61 -0
  106. data/docs/resources/yaml.md.erb +12 -27
  107. data/docs/resources/yum.md.erb +37 -51
  108. data/docs/resources/zfs_dataset.md.erb +15 -26
  109. data/docs/resources/zfs_pool.md.erb +9 -20
  110. data/docs/ruby_usage.md +0 -1
  111. data/examples/meta-profile/README.md +1 -1
  112. data/examples/profile-sensitive/README.md +29 -0
  113. data/examples/profile-sensitive/controls/sensitive-failures.rb +9 -0
  114. data/examples/profile-sensitive/controls/sensitive.rb +9 -0
  115. data/examples/profile-sensitive/inspec.yml +8 -0
  116. data/inspec.gemspec +3 -3
  117. data/lib/bundles/inspec-artifact/cli.rb +5 -5
  118. data/lib/bundles/inspec-compliance/README.md +24 -22
  119. data/lib/bundles/inspec-compliance/api/login.rb +152 -0
  120. data/lib/bundles/inspec-compliance/api.rb +46 -16
  121. data/lib/bundles/inspec-compliance/cli.rb +58 -165
  122. data/lib/bundles/inspec-compliance/target.rb +2 -3
  123. data/lib/bundles/inspec-habitat/cli.rb +7 -2
  124. data/lib/bundles/inspec-habitat/profile.rb +44 -20
  125. data/lib/bundles/inspec-init/templates/profile/README.md +1 -1
  126. data/lib/bundles/inspec-init/templates/profile/controls/example.rb +1 -1
  127. data/lib/bundles/inspec-supermarket/api.rb +1 -1
  128. data/lib/inspec/backend.rb +8 -0
  129. data/lib/inspec/cli.rb +1 -1
  130. data/lib/inspec/control_eval_context.rb +16 -6
  131. data/lib/inspec/dependencies/requirement.rb +22 -8
  132. data/lib/inspec/dependencies/resolver.rb +1 -1
  133. data/lib/inspec/exceptions.rb +4 -0
  134. data/lib/inspec/file_provider.rb +38 -9
  135. data/lib/inspec/metadata.rb +17 -3
  136. data/lib/inspec/objects/attribute.rb +16 -7
  137. data/lib/inspec/objects/control.rb +10 -2
  138. data/lib/inspec/plugins/resource.rb +34 -5
  139. data/lib/inspec/profile.rb +10 -1
  140. data/lib/inspec/profile_context.rb +3 -1
  141. data/lib/inspec/resource.rb +17 -5
  142. data/lib/inspec/rspec_json_formatter.rb +48 -14
  143. data/lib/inspec/rule.rb +4 -0
  144. data/lib/inspec/runner.rb +72 -30
  145. data/lib/inspec/shell.rb +24 -19
  146. data/lib/inspec/version.rb +1 -1
  147. data/lib/matchers/matchers.rb +40 -0
  148. data/lib/resources/aide_conf.rb +162 -0
  149. data/lib/resources/auditd.rb +231 -0
  150. data/lib/resources/auditd_rules.rb +3 -1
  151. data/lib/resources/command.rb +1 -1
  152. data/lib/resources/cpan.rb +60 -0
  153. data/lib/resources/cran.rb +66 -0
  154. data/lib/resources/docker.rb +8 -1
  155. data/lib/resources/docker_container.rb +19 -2
  156. data/lib/resources/elasticsearch.rb +172 -0
  157. data/lib/resources/etc_fstab.rb +102 -0
  158. data/lib/resources/etc_group.rb +1 -1
  159. data/lib/resources/etc_hosts.rb +81 -0
  160. data/lib/resources/etc_hosts_allow_deny.rb +122 -0
  161. data/lib/resources/file.rb +87 -10
  162. data/lib/resources/firewalld.rb +144 -0
  163. data/lib/resources/groups.rb +0 -1
  164. data/lib/resources/host.rb +30 -15
  165. data/lib/resources/http.rb +178 -22
  166. data/lib/resources/mssql_session.rb +3 -3
  167. data/lib/resources/mysql_conf.rb +10 -0
  168. data/lib/resources/mysql_session.rb +1 -1
  169. data/lib/resources/nginx.rb +97 -0
  170. data/lib/resources/nginx_conf.rb +134 -1
  171. data/lib/resources/oracledb_session.rb +9 -8
  172. data/lib/resources/os_env.rb +7 -4
  173. data/lib/resources/package.rb +14 -2
  174. data/lib/resources/packages.rb +1 -1
  175. data/lib/resources/pip.rb +28 -20
  176. data/lib/resources/port.rb +251 -3
  177. data/lib/resources/postgres.rb +1 -1
  178. data/lib/resources/postgres_session.rb +1 -1
  179. data/lib/resources/processes.rb +106 -20
  180. data/lib/resources/registry_key.rb +11 -2
  181. data/lib/resources/service.rb +5 -24
  182. data/lib/resources/ssh_conf.rb +1 -1
  183. data/lib/resources/ssl.rb +4 -3
  184. data/lib/resources/toml.rb +2 -2
  185. data/lib/resources/windows_hotfix.rb +35 -0
  186. data/lib/resources/xinetd.rb +4 -6
  187. data/lib/resources/xml.rb +27 -0
  188. data/lib/source_readers/inspec.rb +3 -3
  189. data/lib/utils/find_files.rb +2 -1
  190. data/lib/utils/nginx_parser.rb +10 -1
  191. data/lib/utils/object_traversal.rb +35 -10
  192. data/lib/utils/parser.rb +21 -3
  193. metadata +48 -18
  194. data/docs/cli.md +0 -392
data/inspec.gemspec CHANGED
@@ -24,9 +24,9 @@ Gem::Specification.new do |spec|
24
24
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
25
25
  spec.require_paths = ['lib']
26
26
 
27
- spec.required_ruby_version = '>= 2.1'
27
+ spec.required_ruby_version = '>= 2.3'
28
28
 
29
- spec.add_dependency 'train', '>=0.24.0', '<1.0'
29
+ spec.add_dependency 'train', '~> 0.29', '>= 0.29.1'
30
30
  spec.add_dependency 'thor', '~> 0.19'
31
31
  spec.add_dependency 'json', '>= 1.8', '< 3.0'
32
32
  spec.add_dependency 'rainbow', '~> 2'
@@ -40,7 +40,7 @@ Gem::Specification.new do |spec|
40
40
  spec.add_dependency 'sslshake', '~> 1.2'
41
41
  spec.add_dependency 'parallel', '~> 1.9'
42
42
  spec.add_dependency 'faraday', '>=0.9.0'
43
- spec.add_dependency 'toml', '~> 0.1'
43
+ spec.add_dependency 'tomlrb', '~> 1.2'
44
44
  spec.add_dependency 'addressable', '~> 2.4'
45
45
  spec.add_dependency 'parslet', '~> 1.5'
46
46
  spec.add_dependency 'semverse'
@@ -79,17 +79,17 @@ module Artifact
79
79
  KEY_BITS=2048
80
80
  KEY_ALG=OpenSSL::PKey::RSA
81
81
 
82
- INSPEC_PROFILE_VERSION_1='INSPEC-PROFILE-1'.freeze
83
- INSPEC_REPORT_VERSION_1='INSPEC-REPORT-1'.freeze
82
+ INSPEC_PROFILE_VERSION_1='INSPEC-PROFILE-1'
83
+ INSPEC_REPORT_VERSION_1='INSPEC-REPORT-1'
84
84
 
85
85
  ARTIFACT_DIGEST=OpenSSL::Digest::SHA512
86
- ARTIFACT_DIGEST_NAME='SHA512'.freeze
86
+ ARTIFACT_DIGEST_NAME='SHA512'
87
87
 
88
88
  VALID_PROFILE_VERSIONS=Set.new [INSPEC_PROFILE_VERSION_1]
89
89
  VALID_PROFILE_DIGESTS=Set.new [ARTIFACT_DIGEST_NAME]
90
90
 
91
- SIGNED_PROFILE_SUFFIX='iaf'.freeze
92
- SIGNED_REPORT_SUFFIX='iar'.freeze
91
+ SIGNED_PROFILE_SUFFIX='iaf'
92
+ SIGNED_REPORT_SUFFIX='iar'
93
93
 
94
94
  # rubocop:disable Metrics/ClassLength
95
95
  class CLI < Inspec::BaseCLI
@@ -2,18 +2,17 @@
2
2
 
3
3
  This extensions offers the following features:
4
4
 
5
- - list available profiles in Chef Compliance
6
- - execute profiles directly from Chef Compliance locally
7
- - upload a local profile to Chef Compliance
5
+ - list available profiles in Chef Automate/Chef Compliance
6
+ - execute profiles directly from Chef Automate/Chef Compliance locally
7
+ - upload a local profile to Chef Automate/Chef Compliance
8
8
 
9
9
  To use the CLI, this InSpec add-on adds the following commands:
10
10
 
11
- * `$ inspec compliance login` - authentication of the API token against Chef Compliance
12
- * `$ inspec compliance login_automate` - authentication of the API token against Chef Automate
13
- * `$ inspec compliance profiles` - list all available Chef Compliance profiles
14
- * `$ inspec exec compliance://profile` - runs a Chef Compliance profile
15
- * `$ inspec compliance upload path/to/local/profile` - uploads a local profile to Chef Compliance
16
- * `$ inspec compliance logout` - logout of Chef Compliance
11
+ * `$ inspec compliance login` - authentication of the API token against Chef Automate/Chef Compliance
12
+ * `$ inspec compliance profiles` - list all available Compliance profiles
13
+ * `$ inspec exec compliance://profile` - runs a Compliance profile
14
+ * `$ inspec compliance upload path/to/local/profile` - uploads a local profile to Chef Automate/Chef Compliance
15
+ * `$ inspec compliance logout` - logout of Chef Automate/Chef Compliance
17
16
 
18
17
  Compliance profiles can be executed in two mays:
19
18
 
@@ -31,8 +30,7 @@ Commands:
31
30
  inspec compliance download PROFILE # downloads a profile from Chef Compliance
32
31
  inspec compliance exec PROFILE # executes a Chef Compliance profile
33
32
  inspec compliance help [COMMAND] # Describe subcommands or one specific subcommand
34
- inspec compliance login SERVER # Log in to a Chef Compliance SERVER
35
- inspec compliance login_automate SERVER # Log in to an Automate SERVER
33
+ inspec compliance login SERVER # Log in to a Chef Automate/Chef Compliance SERVER
36
34
  inspec compliance logout # user logout from Chef Compliance
37
35
  inspec compliance profiles # list all available profiles in Chef Compliance
38
36
  inspec compliance upload PATH # uploads a local profile to Chef Compliance
@@ -41,29 +39,22 @@ Commands:
41
39
 
42
40
  ### Login with Chef Automate
43
41
 
44
- You need a Chef Automate server up and running. Compliance features need to [be activated](https://docs.chef.io/install_chef_automate.html#compliance), too.
45
-
46
- Now, you need a user token. You can retrieve that via [UI](https://docs.chef.io/api_delivery.html) or [CLI](https://docs.chef.io/ctl_delivery.html#delivery-token).
42
+ You will need an access token for authentication. You can retrieve one via [UI](https://docs.chef.io/api_delivery.html) or [CLI](https://docs.chef.io/ctl_delivery.html#delivery-token).
47
43
 
48
44
  ```
49
- inspec compliance login_automate https://automate.compliance.test --insecure --user 'admin' --ent 'brewinc' --usertoken 'zuop..._KzE'
45
+ $ inspec compliance login https://automate.compliance.test --insecure --user 'admin' --ent 'brewinc' --token 'zuop..._KzE'
50
46
  ```
51
47
 
52
48
  ### Login with Chef Compliance
53
49
 
54
- Before you start using the compliance plugin, you need a running [Chef Compliance](https://www.chef.io/compliance/) server. Please login and gather the access token:
50
+ You will need an access token for authentication. You can retrieve one via:
55
51
 
56
52
  ![Chef Compliance Token](images/cc-token.png)
57
53
 
58
54
  You can choose the access token (`--token`) or the refresh token (`--refresh_token`)
59
55
 
60
56
  ```
61
- # login to chef compliance server
62
57
  $ inspec compliance login https://compliance.test --user admin --insecure --token '...'
63
-
64
- # display the chef compliance server version
65
- $ inspec compliance version
66
- Chef Compliance version: 1.0.11
67
58
  ```
68
59
 
69
60
  ### List available profiles via Chef Compliance / Automate
@@ -131,7 +122,7 @@ Available profiles:
131
122
  * cis/cis-ubuntu14.04lts-level2
132
123
  ```
133
124
 
134
- ### Run a profile from Chef Compliance / Automate on Workstation
125
+ ### Run a profile from Chef Compliance / Chef Automate on Workstation
135
126
 
136
127
  ```
137
128
  $ inspec exec compliance://admin/profile
@@ -148,6 +139,17 @@ Finished in 0.02862 seconds (files took 0.62628 seconds to load)
148
139
  5 examples, 0 failures, 1 pending
149
140
  ```
150
141
 
142
+ Exec a specific version(2.0.1) of a profile when logged in with Automate:
143
+
144
+ ```
145
+ $ inspec exec compliance://admin/apache-baseline#2.0.1
146
+ ```
147
+
148
+ Download a specific version(2.0.2) of a profile when logged in with Automate:
149
+ ```
150
+ $ inspec compliance download compliance://admin/apache-baseline#2.0.2
151
+ ```
152
+
151
153
  ### To Logout from Chef Compliance
152
154
 
153
155
  ```
@@ -0,0 +1,152 @@
1
+ # encoding: utf-8
2
+ # author: Christoph Hartmann
3
+ # author: Dominik Ricter
4
+ # author: Jerry Aldrich
5
+
6
+ module Compliance
7
+ class API
8
+ module Login
9
+ class CannotDetermineServerType < StandardError; end
10
+
11
+ def login(options)
12
+ raise ArgumentError, 'Please specify a server using `inspec compliance login https://SERVER`' unless options['server']
13
+
14
+ options['server'] = URI("https://#{options['server']}").to_s if URI(options['server']).scheme.nil?
15
+
16
+ options['server_type'] = Compliance::API.determine_server_type(options['server'], options['insecure'])
17
+
18
+ case options['server_type']
19
+ when :automate
20
+ config = Login::AutomateServer.login(options)
21
+ when :compliance
22
+ config = Login::ComplianceServer.login(options)
23
+ else
24
+ raise CannotDetermineServerType, "Unable to determine if #{options['server']} is a Chef Automate or Chef Compliance server"
25
+ end
26
+
27
+ puts "Stored configuration for Chef #{config['server_type'].capitalize}: #{config['server']}' with user: '#{config['user']}'"
28
+ end
29
+
30
+ module AutomateServer
31
+ def self.login(options)
32
+ verify_thor_options(options)
33
+
34
+ options['url'] = options['server'] + '/compliance'
35
+ token = options['dctoken'] || options['token']
36
+ store_access_token(options, token)
37
+ end
38
+
39
+ def self.store_access_token(options, token)
40
+ token_type = if options['token']
41
+ 'usertoken'
42
+ else
43
+ 'dctoken'
44
+ end
45
+
46
+ config = Compliance::Configuration.new
47
+
48
+ config.clean
49
+
50
+ config['automate'] = {}
51
+ config['automate']['ent'] = options['ent']
52
+ config['automate']['token_type'] = token_type
53
+ config['server'] = options['url']
54
+ config['user'] = options['user']
55
+ config['insecure'] = options['insecure'] || false
56
+ config['server_type'] = options['server_type'].to_s
57
+ config['token'] = token
58
+ config['version'] = Compliance::API.version(config)
59
+
60
+ config.store
61
+ config
62
+ end
63
+
64
+ # Automate login requires `--ent`, `--user`, and either `--token` or `--dctoken`
65
+ def self.verify_thor_options(o)
66
+ error_msg = []
67
+
68
+ error_msg.push('Please specify a user using `--user=\'USER\'`') if o['user'].nil?
69
+ error_msg.push('Please specify an enterprise using `--ent=\'automate\'`') if o['ent'].nil?
70
+
71
+ if o['token'].nil? && o['dctoken'].nil?
72
+ error_msg.push('Please specify a token using `--token=\'AUTOMATE_TOKEN\'` or `--dctoken=\'DATA_COLLECTOR_TOKEN\'`')
73
+ end
74
+
75
+ raise ArgumentError, error_msg.join("\n") unless error_msg.empty?
76
+ end
77
+ end
78
+
79
+ module ComplianceServer
80
+ def self.login(options)
81
+ compliance_verify_thor_options(options)
82
+
83
+ options['url'] = options['server'] + '/api'
84
+
85
+ if options['user'] && options['token']
86
+ compliance_store_access_token(options, options['token'])
87
+ elsif options['user'] && options['password']
88
+ compliance_login_user_pass(options)
89
+ elsif options['refresh_token']
90
+ compliance_login_refresh_token(options)
91
+ end
92
+ end
93
+
94
+ def self.compliance_login_user_pass(options)
95
+ success, msg, token = Compliance::API.get_token_via_password(
96
+ options['url'],
97
+ options['user'],
98
+ options['password'],
99
+ options['insecure'],
100
+ )
101
+
102
+ raise msg unless success
103
+ compliance_store_access_token(options, token)
104
+ end
105
+
106
+ def self.compliance_login_refresh_token(options)
107
+ success, msg, token = Compliance::API.get_token_via_refresh_token(
108
+ options['url'],
109
+ options['refresh_token'],
110
+ options['insecure'],
111
+ )
112
+
113
+ raise msg unless success
114
+ compliance_store_access_token(options, token)
115
+ end
116
+
117
+ def self.compliance_store_access_token(options, token)
118
+ config = Compliance::Configuration.new
119
+ config.clean
120
+
121
+ config['user'] = options['user'] if options['user']
122
+ config['server'] = options['url']
123
+ config['insecure'] = options['insecure'] || false
124
+ config['server_type'] = options['server_type'].to_s
125
+ config['token'] = token
126
+ config['version'] = Compliance::API.version(config)
127
+
128
+ config.store
129
+ config
130
+ end
131
+
132
+ # Compliance login requires `--user` or `--refresh_token`
133
+ # If `--user` then either `--password`, `--token`, or `--refresh-token`, is required
134
+ def self.compliance_verify_thor_options(o)
135
+ error_msg = []
136
+
137
+ error_msg.push('Please specify a server using `inspec compliance login https://SERVER`') if o['server'].nil?
138
+
139
+ if o['user'].nil? && o['refresh_token'].nil?
140
+ error_msg.push('Please specify a `--user=\'USER\'` or a `--refresh-token=\'TOKEN\'`')
141
+ end
142
+
143
+ if o['user'] && o['password'].nil? && o['token'].nil? && o['refresh_token'].nil?
144
+ error_msg.push('Please specify either a `--password`, `--token`, or `--refresh-token`')
145
+ end
146
+
147
+ raise ArgumentError, error_msg.join("\n") unless error_msg.empty?
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
@@ -5,21 +5,28 @@
5
5
  require 'net/http'
6
6
  require 'uri'
7
7
 
8
+ require_relative 'api/login'
9
+
8
10
  module Compliance
9
- class ServerConfigurationMissing < StandardError
10
- end
11
+ class ServerConfigurationMissing < StandardError; end
11
12
 
12
13
  # API Implementation does not hold any state by itself,
13
14
  # everything will be stored in local Configuration store
14
15
  class API # rubocop:disable Metrics/ClassLength
16
+ extend Compliance::API::Login
17
+
15
18
  # return all compliance profiles available for the user
19
+ # the user is either specified in the options hash or by default
20
+ # the username of the account is used that is logged in
16
21
  def self.profiles(config)
22
+ owner = config['owner'] || config['user']
23
+
17
24
  # Chef Compliance
18
25
  if is_compliance_server?(config)
19
26
  url = "#{config['server']}/user/compliance"
20
27
  # Chef Automate
21
28
  elsif is_automate_server?(config)
22
- url = "#{config['server']}/profiles/#{config['user']}"
29
+ url = "#{config['server']}/profiles/#{owner}"
23
30
  else
24
31
  raise ServerConfigurationMissing
25
32
  end
@@ -42,9 +49,8 @@ module Compliance
42
49
  elsif is_automate_server_pre_080?(config)
43
50
  mapped_profiles = profiles.values.flatten
44
51
  else
45
- owner_id = config['user']
46
52
  mapped_profiles = profiles.map { |e|
47
- e['owner_id'] = owner_id
53
+ e['owner_id'] = owner
48
54
  e
49
55
  }
50
56
  end
@@ -82,10 +88,19 @@ module Compliance
82
88
 
83
89
  # verifies that a profile
84
90
  def self.exist?(config, profile)
85
- _msg, profiles = Compliance::API.profiles(config)
91
+ owner, id, ver = profile_split(profile)
92
+
93
+ # ensure that we do not manipulate the configuration object
94
+ user_config = config.dup
95
+ user_config['owner'] = owner
96
+ _msg, profiles = Compliance::API.profiles(user_config)
97
+
86
98
  if !profiles.empty?
87
- index = profiles.index { |p| "#{p['owner_id']}/#{p['name']}" == profile }
88
- !index.nil? && index >= 0
99
+ profiles.any? do |p|
100
+ p['owner_id'] == owner &&
101
+ p['name'] == id &&
102
+ (ver.nil? || p['version'] == ver)
103
+ end
89
104
  else
90
105
  false
91
106
  end
@@ -97,10 +112,10 @@ module Compliance
97
112
  url = "#{config['server']}/owners/#{owner}/compliance/#{profile_name}/tar"
98
113
  # Chef Automate pre 0.8.0
99
114
  elsif is_automate_server_pre_080?(config)
100
- url = "#{config['server']}/#{config['user']}"
115
+ url = "#{config['server']}/#{owner}"
101
116
  # Chef Automate
102
117
  else
103
- url = "#{config['server']}/profiles/#{config['user']}"
118
+ url = "#{config['server']}/profiles/#{owner}"
104
119
  end
105
120
 
106
121
  headers = get_headers(config)
@@ -179,14 +194,21 @@ module Compliance
179
194
  end
180
195
 
181
196
  def self.target_url(config, profile)
182
- if is_automate_server?(config)
183
- owner, id = profile.split('/')
184
- target = "#{config['server']}/profiles/#{owner}/#{id}/tar"
197
+ owner, id, ver = profile_split(profile)
198
+
199
+ return "#{config['server']}/owners/#{owner}/compliance/#{id}/tar" unless is_automate_server?(config)
200
+
201
+ if ver.nil?
202
+ "#{config['server']}/profiles/#{owner}/#{id}/tar"
185
203
  else
186
- owner, id = profile.split('/')
187
- target = "#{config['server']}/owners/#{owner}/compliance/#{id}/tar"
204
+ "#{config['server']}/profiles/#{owner}/#{id}/version/#{ver}/tar"
188
205
  end
189
- target
206
+ end
207
+
208
+ def self.profile_split(profile)
209
+ owner, id = profile.split('/')
210
+ id, version = id.split('#')
211
+ [owner, id, version]
190
212
  end
191
213
 
192
214
  # returns a parsed url for `admin/profile` or `compliance://admin/profile`
@@ -227,5 +249,13 @@ module Compliance
227
249
  return nil unless config['version'].is_a?(Hash)
228
250
  config['version']['version']
229
251
  end
252
+
253
+ def self.determine_server_type(url, insecure)
254
+ if Compliance::HTTP.get(url + '/compliance/version', nil, insecure).code == '401'
255
+ :automate
256
+ elsif Compliance::HTTP.get(url + '/api/version', nil, insecure).code == '200'
257
+ :compliance
258
+ end
259
+ end
230
260
  end
231
261
  end