inspec 2.2.35 → 2.2.41
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -10
- data/README.md +7 -5
- data/bin/inspec +0 -0
- data/docs/dsl_inspec.md +35 -39
- data/docs/glossary.md +15 -15
- data/docs/habitat.md +10 -9
- data/docs/inspec_and_friends.md +4 -4
- data/docs/matchers.md +1 -9
- data/docs/plugin_kitchen_inspec.md +34 -24
- data/docs/profiles.md +217 -156
- data/docs/reporters.md +13 -4
- data/docs/resources/command.md.erb +28 -0
- data/docs/resources/registry_key.md.erb +5 -2
- data/docs/resources/xinetd_conf.md.erb +1 -1
- data/docs/ruby_usage.md +4 -3
- data/lib/bundles/inspec-init.rb +4 -0
- data/lib/bundles/inspec-init/cli.rb +9 -72
- data/lib/bundles/inspec-init/renderer.rb +79 -0
- data/lib/inspec/base_cli.rb +25 -12
- data/lib/inspec/objects/describe.rb +8 -1
- data/lib/inspec/plugins/resource.rb +2 -2
- data/lib/inspec/version.rb +1 -1
- data/lib/resources/command.rb +17 -2
- data/lib/resources/package.rb +26 -2
- metadata +3 -2
data/docs/inspec_and_friends.md
CHANGED
@@ -42,10 +42,10 @@ end
|
|
42
42
|
|
43
43
|
That said, InSpec is not RSpec. Some key differences:
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
45
|
+
* In InSpec, `describe` blocks should not be nested; instead use `control` blocks to describe a higher-level grouping of tests.
|
46
|
+
* The RSpec `shared_example` construct is not supported. Instead, create a simple custom resource that executes repetitious tasks.
|
47
|
+
* InSpec is aimed at compliance practitioners and infrastructure testers, so our focus is providing a few, well-supported, easy-to-use [universal matchers](https://www.inspec.io/docs/reference/matchers/), such as `cmp`. In contrast, RSpec is a tool designed for software engineers. It thus supports a very large range of matchers, to enable testing of software engineering constructs such as exceptions, Object Oriented Programming relationships, and so on.
|
48
|
+
* While InSpec uses parts of the RSpec project and codebase, it is a separate project from InSpec. Rspec's release schedule and feature set are beyond the control of the InSpec team. While it is possible to use many of the RSpec core features within InSpec profiles, InSpec can only guarantee that the features described at [docs.inspec.io](https://docs.inspec.io) will function correctly. Some RSpec core functionality may be removed in future versions of InSpec as needed to ensure stability in the InSpec project.
|
49
49
|
|
50
50
|
## Serverspec
|
51
51
|
|
data/docs/matchers.md
CHANGED
@@ -32,8 +32,6 @@ describe file('/proc/cpuinfo') do
|
|
32
32
|
end
|
33
33
|
```
|
34
34
|
|
35
|
-
<br>
|
36
|
-
|
37
35
|
## cmp
|
38
36
|
|
39
37
|
Unlike `eq`, `cmp` is a matcher for less-restrictive comparisons. It will
|
@@ -72,6 +70,7 @@ describe auditd_conf do
|
|
72
70
|
its('log_format') { should cmp 'RAW' }
|
73
71
|
end
|
74
72
|
```
|
73
|
+
|
75
74
|
* Recognize versions embedded in strings
|
76
75
|
|
77
76
|
```ruby
|
@@ -107,7 +106,6 @@ end
|
|
107
106
|
expected: 0345
|
108
107
|
got: 0444
|
109
108
|
```
|
110
|
-
<br>
|
111
109
|
|
112
110
|
## eq
|
113
111
|
|
@@ -132,8 +130,6 @@ its('Port') { should eq 22 }
|
|
132
130
|
|
133
131
|
For less restrictive comparisons, please use `cmp`.
|
134
132
|
|
135
|
-
<br>
|
136
|
-
|
137
133
|
## include
|
138
134
|
|
139
135
|
Verifies if a value is included in a list.
|
@@ -144,8 +140,6 @@ describe passwd do
|
|
144
140
|
end
|
145
141
|
```
|
146
142
|
|
147
|
-
<br>
|
148
|
-
|
149
143
|
## be_in
|
150
144
|
|
151
145
|
Verifies that an item is included in a list.
|
@@ -156,8 +150,6 @@ describe resource do
|
|
156
150
|
end
|
157
151
|
```
|
158
152
|
|
159
|
-
<br>
|
160
|
-
|
161
153
|
## match
|
162
154
|
|
163
155
|
Check if a string matches a regular expression.
|
@@ -8,43 +8,53 @@ Use InSpec as a Kitchen verifier with `kitchen-inspec`.
|
|
8
8
|
|
9
9
|
Add the InSpec verifier to the `.kitchen.yml` file:
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
```YML
|
12
|
+
verifier:
|
13
|
+
name: inspec
|
14
|
+
```
|
13
15
|
|
14
16
|
Use a compliance profile from the Chef Compliance server:
|
15
17
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
```YML
|
19
|
+
suites:
|
20
|
+
- name: compliance
|
21
|
+
run_list:
|
22
|
+
- recipe[ssh-hardening::default]
|
23
|
+
verifier:
|
24
|
+
inspec_tests:
|
25
|
+
- compliance://base/ssh
|
26
|
+
```
|
23
27
|
|
24
28
|
and then run the following command:
|
25
29
|
|
26
|
-
|
30
|
+
```bash
|
31
|
+
$ inspec compliance login https://compliance.test --user admin --insecure --token ''
|
32
|
+
```
|
27
33
|
|
28
34
|
where `--insecure` is required when using self-signed certificates.
|
29
35
|
|
30
36
|
Use a compliance profile from the Chef Supermarket:
|
31
37
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
38
|
+
```YML
|
39
|
+
suites:
|
40
|
+
- name: supermarket
|
41
|
+
run_list:
|
42
|
+
- recipe[ssh-hardening::default]
|
43
|
+
verifier:
|
44
|
+
inspec_tests:
|
45
|
+
- supermarket://dev-sec/ssh-baseline
|
46
|
+
```
|
39
47
|
|
40
48
|
Use InSpec tests from the local file system:
|
41
49
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
50
|
+
```YML
|
51
|
+
suites:
|
52
|
+
- name: local
|
53
|
+
run_list:
|
54
|
+
- recipe[my_cookbook::default]
|
55
|
+
verifier:
|
56
|
+
inspec_tests:
|
57
|
+
- test/integration/default
|
58
|
+
```
|
49
59
|
|
50
60
|
Check out [Detect and correct with Test Kitchen](https://learn.chef.io/modules/detect-correct-kitchen#/) on Learn Chef Rally for a hands-on look at how to use Test Kitchen to run InSpec profiles.
|
data/docs/profiles.md
CHANGED
@@ -10,16 +10,18 @@ InSpec supports the creation of complex test and compliance profiles, which orga
|
|
10
10
|
|
11
11
|
A profile should have the following structure::
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
13
|
+
```YAML
|
14
|
+
examples/profile
|
15
|
+
├── README.md
|
16
|
+
├── controls
|
17
|
+
│ ├── example.rb
|
18
|
+
│ └── control_etc.rb
|
19
|
+
├── libraries
|
20
|
+
│ └── extension.rb
|
21
|
+
|── files
|
22
|
+
│ └── extras.conf
|
23
|
+
└── inspec.yml
|
24
|
+
```
|
23
25
|
|
24
26
|
where:
|
25
27
|
|
@@ -37,79 +39,92 @@ Also check out [Explore InSpec resources](https://learn.chef.io/modules/explore-
|
|
37
39
|
|
38
40
|
Each profile must have an `inspec.yml` file that defines the following information:
|
39
41
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
42
|
+
* Use `name` to specify a unique name for the profile. Required.
|
43
|
+
* Use `title` to specify a human-readable name for the profile.
|
44
|
+
* Use `maintainer` to specify the profile maintainer.
|
45
|
+
* Use `copyright` to specify the copyright holder.
|
46
|
+
* Use `copyright_email` to specify support contact information for the profile, typically an email address.
|
47
|
+
* Use `license` to specify the license for the profile.
|
48
|
+
* Use `summary` to specify a one line summary for the profile.
|
49
|
+
* Use `description` to specify a multiple line description of the profile.
|
50
|
+
* Use `version` to specify the profile version.
|
51
|
+
* Use `inspec_version` to place SemVer constraints on the version of InSpec that the profile can run under.
|
52
|
+
* Use `supports` to specify a list of supported platform targets.
|
53
|
+
* Use `depends` to define a list of profiles on which this profile depends.
|
52
54
|
|
53
55
|
`name` is required; all other profile settings are optional. For example:
|
54
56
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
57
|
+
```YAML
|
58
|
+
name: ssh
|
59
|
+
title: Basic SSH
|
60
|
+
maintainer: Chef Software, Inc.
|
61
|
+
copyright: Chef Software, Inc.
|
62
|
+
copyright_email: support@chef.io
|
63
|
+
license: Proprietary, All rights reserved
|
64
|
+
summary: Verify that SSH Server and SSH Client are configured securely
|
65
|
+
version: 1.0.0
|
66
|
+
supports:
|
67
|
+
- os-family: linux
|
68
|
+
depends:
|
69
|
+
- name: profile
|
70
|
+
path: ../path/to/profile
|
71
|
+
inspec_version: "~> 2.1"
|
72
|
+
```
|
69
73
|
|
70
74
|
## Verify Profiles
|
71
75
|
|
72
76
|
Use the `inspec check` command to verify the implementation of a profile:
|
73
77
|
|
74
|
-
|
78
|
+
```bash
|
79
|
+
$ inspec check examples/profile
|
80
|
+
```
|
75
81
|
|
76
82
|
# Platform Support
|
77
83
|
|
78
84
|
Use the `supports` setting in the `inspec.yml` file to specify one (or more) platforms for which a profile is targeting. The list of supported platforms may contain simple names, names and versions, or detailed flags, and may be combined arbitrarily. For example, to target anything running Debian Linux:
|
79
85
|
|
80
|
-
|
81
|
-
|
82
|
-
|
86
|
+
```YAML
|
87
|
+
name: ssh
|
88
|
+
supports:
|
89
|
+
- os-name: debian
|
90
|
+
```
|
83
91
|
|
84
92
|
and to target only Ubuntu version 14.04
|
85
93
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
94
|
+
```YAML
|
95
|
+
name: ssh
|
96
|
+
supports:
|
97
|
+
- os-name: ubuntu
|
98
|
+
release: 14.04
|
99
|
+
```
|
90
100
|
|
91
101
|
and to target the entire RedHat platform (including CentOS and Oracle Linux):
|
92
102
|
|
93
|
-
|
94
|
-
|
95
|
-
|
103
|
+
```YAML
|
104
|
+
name: ssh
|
105
|
+
supports:
|
106
|
+
- os-family: redhat
|
107
|
+
```
|
96
108
|
|
97
109
|
and to target anything running on Amazon AWS:
|
98
110
|
|
99
|
-
|
100
|
-
|
101
|
-
|
111
|
+
```YAML
|
112
|
+
name: ssh
|
113
|
+
supports:
|
114
|
+
- platform: aws
|
115
|
+
```
|
102
116
|
|
103
117
|
and to target all of these examples in a single `inspec.yml` file:
|
104
118
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
119
|
+
```YAML
|
120
|
+
name: ssh
|
121
|
+
supports:
|
122
|
+
- os-name: debian
|
123
|
+
- os-name: ubuntu
|
124
|
+
release: 14.04
|
125
|
+
- os-family: redhat
|
126
|
+
- platform: aws
|
127
|
+
```
|
113
128
|
|
114
129
|
# Profile Dependencies
|
115
130
|
|
@@ -121,11 +136,13 @@ For hands-on examples, check out [Create a custom InSpec profile](https://learn.
|
|
121
136
|
|
122
137
|
Before a profile can use controls from another profile, the to-be-included profile needs to be specified in the including profile’s `inspec.yml` file in the `depends` section. For each profile to be included, a location for the profile from where to be fetched and a name for the profile should be included. For example:
|
123
138
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
139
|
+
```YAML
|
140
|
+
depends:
|
141
|
+
- name: linux-baseline
|
142
|
+
url: https://github.com/dev-sec/linux-baseline/archive/master.tar.gz
|
143
|
+
- name: ssh-baseline
|
144
|
+
url: https://github.com/dev-sec/ssh-baseline/archive/master.tar.gz
|
145
|
+
```
|
129
146
|
|
130
147
|
InSpec supports a number of dependency sources.
|
131
148
|
|
@@ -133,21 +150,25 @@ InSpec supports a number of dependency sources.
|
|
133
150
|
|
134
151
|
The `path` setting defines a profile that is located on disk. This setting is typically used during development of profiles and when debugging profiles.
|
135
152
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
153
|
+
```YAML
|
154
|
+
depends:
|
155
|
+
- name: my-profile
|
156
|
+
path: /absolute/path
|
157
|
+
- name: another
|
158
|
+
path: ../relative/path
|
159
|
+
```
|
141
160
|
|
142
161
|
### url
|
143
162
|
|
144
163
|
The `url` setting specifies a profile that is located at an HTTP- or HTTPS-based URL. The profile must be accessible via a HTTP GET operation and must be a valid profile archive (zip, tar, or tar.gz format).
|
145
164
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
165
|
+
```YAML
|
166
|
+
depends:
|
167
|
+
- name: my-profile
|
168
|
+
url: https://my.domain/path/to/profile.tgz
|
169
|
+
- name: profile-via-git
|
170
|
+
url: https://github.com/myusername/myprofile-repo/archive/master.tar.gz
|
171
|
+
```
|
151
172
|
|
152
173
|
### git
|
153
174
|
|
@@ -155,13 +176,15 @@ A `git` setting specifies a profile that is located in a git repository, with op
|
|
155
176
|
|
156
177
|
For example:
|
157
178
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
179
|
+
```YAML
|
180
|
+
depends:
|
181
|
+
- name: git-profile
|
182
|
+
git: http://url/to/repo
|
183
|
+
branch: desired_branch
|
184
|
+
tag: desired_version
|
185
|
+
commit: pinned_commit
|
186
|
+
version: semver_via_tags
|
187
|
+
```
|
165
188
|
|
166
189
|
### supermarket
|
167
190
|
|
@@ -169,9 +192,11 @@ A `supermarket` setting specifies a profile that is located in a cookbook hosted
|
|
169
192
|
|
170
193
|
For example:
|
171
194
|
|
172
|
-
|
173
|
-
|
174
|
-
|
195
|
+
```YAML
|
196
|
+
depends:
|
197
|
+
- name: supermarket-profile
|
198
|
+
supermarket: supermarket-username/supermarket-profile
|
199
|
+
```
|
175
200
|
|
176
201
|
Available Supermarket profiles can be listed with `inspec supermarket profiles`.
|
177
202
|
|
@@ -181,9 +206,11 @@ A `compliance` setting specifies a profile that is located on the Chef Automate
|
|
181
206
|
|
182
207
|
For example:
|
183
208
|
|
184
|
-
|
185
|
-
|
186
|
-
|
209
|
+
```YAML
|
210
|
+
depends:
|
211
|
+
- name: linux
|
212
|
+
compliance: base/linux
|
213
|
+
```
|
187
214
|
|
188
215
|
## Vendoring Dependencies
|
189
216
|
|
@@ -199,15 +226,17 @@ Once defined in the `inspec.yml`, controls from the included profiles can be use
|
|
199
226
|
|
200
227
|
With the `include_controls` command in a profile, all controls from the named profile will be executed every time the including profile is executed.
|
201
228
|
|
229
|
+
```YAML
|
202
230
|
![Include Controls](/images/profile_inheritance/include_controls.png)
|
231
|
+
```
|
203
232
|
|
204
233
|
In the example above, every time `my-app-profile` is executed, all the controls from `my-baseline` are also executed. Therefore, the following controls would be executed:
|
205
234
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
235
|
+
* myapp-1
|
236
|
+
* myapp-2
|
237
|
+
* myapp-3
|
238
|
+
* baseline-1
|
239
|
+
* baseline-2
|
211
240
|
|
212
241
|
This is a great reminder that having a good naming convention for your controls is helpful to avoid confusion when
|
213
242
|
including controls from other profiles!
|
@@ -216,7 +245,9 @@ including controls from other profiles!
|
|
216
245
|
|
217
246
|
What if one of the controls from the included profile does not apply to your environment? Luckily, it is not necessary to maintain a slightly-modified copy of the included profile just to delete a control. The `skip_control` command tells InSpec to not run a particular control.
|
218
247
|
|
248
|
+
```YAML
|
219
249
|
![Include Controls with Skip](/images/profile_inheritance/include_controls_with_skip.png)
|
250
|
+
```
|
220
251
|
|
221
252
|
In the above example, all controls from `my-app-profile` and `my-baseline` profile will be executed every time `my-app-profile` is executed **except** for control `baseline-2` from the `my-baseline` profile.
|
222
253
|
|
@@ -226,7 +257,9 @@ Let's say a particular control from an included profile should still be run, but
|
|
226
257
|
|
227
258
|
When a control is included, it can also be modified!
|
228
259
|
|
260
|
+
```YAML
|
229
261
|
![Include Controls with Modification](/images/profile_inheritance/include_controls_with_mod.png)
|
262
|
+
```
|
230
263
|
|
231
264
|
In the above example, all controls from `my-baseline` are executed along with all the controls from the including profile, `my-app-profile`. However, should control `baseline-1` fail, it will be raised with an impact of `0.5` instead of the originally-intended impact of `1.0`.
|
232
265
|
|
@@ -234,21 +267,25 @@ In the above example, all controls from `my-baseline` are executed along with al
|
|
234
267
|
|
235
268
|
If there are only a handful of controls that should be executed from an included profile, it's not necessarily to skip all the unneeded controls, or worse, copy/paste those controls bit-for-bit into your profile. Instead, use the `require_controls` command.
|
236
269
|
|
270
|
+
```YAML
|
237
271
|
![Require Controls](/images/profile_inheritance/require_controls.png)
|
272
|
+
```
|
238
273
|
|
239
274
|
Whenever `my-app-profile` is executed, in addition to its own controls, it will run only the controls specified in the `require_controls` block. In the case, the following controls would be executed:
|
240
275
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
276
|
+
* myapp-1
|
277
|
+
* myapp-2
|
278
|
+
* myapp-3
|
279
|
+
* baseline-2
|
280
|
+
* baseline-4
|
246
281
|
|
247
282
|
Controls `baseline-1`, `baseline-3`, and `baseline-5` would not be run, just as if they were manually skipped. This method of including specific controls ensures only the controls specified are executed; if new controls are added to a later version of `my-baseline`, they would not be run.
|
248
283
|
|
249
284
|
And, just the way its possible to modify controls when using `include_controls`, controls can be modified as well.
|
250
285
|
|
286
|
+
```YAML
|
251
287
|
![Require Controls with Modification](/images/profile_inheritance/require_controls_with_mod.png)
|
288
|
+
```
|
252
289
|
|
253
290
|
As with the prior example, only `baseline-2` and `baseline-4` are executed, but if `baseline-2` fails, it will report with an impact of `0.5` instead of the originally-intended `1.0` impact.
|
254
291
|
|
@@ -259,46 +296,54 @@ for use in your profile. If two of your dependencies provide a resource with
|
|
259
296
|
the same name, you can use the `require_resource` DSL function to
|
260
297
|
disambiguate the two:
|
261
298
|
|
262
|
-
|
263
|
-
|
299
|
+
```YAML
|
300
|
+
require_resource(profile: 'my_dep', resource: 'my_res',
|
301
|
+
as: 'my_res2')
|
302
|
+
```
|
264
303
|
|
265
304
|
This will allow you to reference the resource `my_res` from the
|
266
305
|
profile `my_dep` using the name `my_res2`.
|
267
306
|
|
268
307
|
# Profile Attributes
|
269
308
|
|
270
|
-
Attributes may be used in profiles to define secrets, such as user names and passwords, that should not otherwise be stored in plain-text in a cookbook. First specify a variable in the control for each secret, then add the secret to a
|
309
|
+
Attributes may be used in profiles to define secrets, such as user names and passwords, that should not otherwise be stored in plain-text in a cookbook. First specify a variable in the control for each secret, then add the secret to a YAML file located on the local machine, and then run `inspec exec` and specify the path to that Yaml file using the `--attrs` attribute.
|
271
310
|
|
272
311
|
For example, a control:
|
273
312
|
|
274
|
-
|
275
|
-
|
276
|
-
|
313
|
+
```Ruby
|
314
|
+
# define these attributes on the top-level of your file and re-use them across all tests!
|
315
|
+
val_user = attribute('user', default: 'alice', description: 'An identification for the user')
|
316
|
+
val_password = attribute('password', description: 'A value for the password')
|
277
317
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
318
|
+
control 'system-users' do
|
319
|
+
impact 0.8
|
320
|
+
desc '
|
321
|
+
This test assures that the user "Bob" has a user installed on the system, along with a
|
322
|
+
specified password.
|
323
|
+
'
|
284
324
|
|
285
|
-
|
286
|
-
|
287
|
-
|
325
|
+
val_user do
|
326
|
+
it { should eq 'bob' }
|
327
|
+
end
|
288
328
|
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
329
|
+
describe val_password do
|
330
|
+
it { should eq 'secret' }
|
331
|
+
end
|
332
|
+
end
|
333
|
+
```
|
293
334
|
|
294
|
-
And a
|
335
|
+
And a YAML file named `profile-attribute.yml`:
|
295
336
|
|
296
|
-
|
297
|
-
|
337
|
+
```YAML
|
338
|
+
user: bob
|
339
|
+
password: secret
|
340
|
+
```
|
298
341
|
|
299
342
|
The following command runs the tests and applies the secrets specified in `profile-attribute.yml`:
|
300
343
|
|
301
|
-
|
344
|
+
```bash
|
345
|
+
$ inspec exec examples/profile-attribute --attrs examples/profile-attribute.yml
|
346
|
+
```
|
302
347
|
|
303
348
|
See the full example in the InSpec open source repository: [Example InSpec Profile with Attributes](https://github.com/chef/inspec/tree/master/examples/profile-attribute)
|
304
349
|
|
@@ -310,33 +355,39 @@ To access these files, they must be stored in the `files` directory at the root
|
|
310
355
|
|
311
356
|
Here is an example for reading and testing a list of ports. The folder structure is:
|
312
357
|
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
358
|
+
```YAML
|
359
|
+
examples/profile
|
360
|
+
├── controls
|
361
|
+
│ ├── example.rb
|
362
|
+
│── files
|
363
|
+
│ └── services.yml
|
364
|
+
└── inspec.yml
|
365
|
+
```
|
319
366
|
|
320
367
|
With `services.yml` containing:
|
321
368
|
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
369
|
+
```YAML
|
370
|
+
- service_name: httpd-alpha
|
371
|
+
port: 80
|
372
|
+
- service_name: httpd-beta
|
373
|
+
port: 8080
|
374
|
+
```
|
326
375
|
|
327
376
|
The tests in `example.rb` can now access this file:
|
328
377
|
|
329
|
-
|
378
|
+
```Ruby
|
379
|
+
my_services = yaml(content: inspec.profile.file('services.yml')).params
|
330
380
|
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
381
|
+
my_services.each do |s|
|
382
|
+
describe service(s['service_name']) do
|
383
|
+
it { should be_running }
|
384
|
+
end
|
335
385
|
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
386
|
+
describe port(s['port']) do
|
387
|
+
it { should be_listening }
|
388
|
+
end
|
389
|
+
end
|
390
|
+
```
|
340
391
|
|
341
392
|
For a more complete example that uses a profile file, see [Explore InSpec resources](https://learn.chef.io/modules/explore-inspec-resources#/) on Learn Chef Rally.
|
342
393
|
|
@@ -346,33 +397,43 @@ Users familiar with the RSpec testing framework may know that there are two ways
|
|
346
397
|
|
347
398
|
InSpec will continue to support both methods of writing tests. Consider this `file` test:
|
348
399
|
|
349
|
-
|
350
|
-
|
351
|
-
|
400
|
+
```Ruby
|
401
|
+
describe file('/tmp/test.txt') do
|
402
|
+
it { should be_file }
|
403
|
+
end
|
404
|
+
```
|
352
405
|
|
353
406
|
This can be re-written with `expect` syntax
|
354
407
|
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
408
|
+
```Ruby
|
409
|
+
describe file('/tmp/test.txt') do
|
410
|
+
it 'should be a file' do
|
411
|
+
expect(subject).to(be_file)
|
412
|
+
end
|
413
|
+
end
|
414
|
+
```
|
360
415
|
|
361
416
|
The output of both of the above examples looks like this:
|
362
417
|
|
363
|
-
|
364
|
-
|
418
|
+
```text
|
419
|
+
File /tmp/test.txt
|
420
|
+
✔ should be a file
|
421
|
+
```
|
365
422
|
|
366
423
|
In addition, you can make use of the `subject` keyword to further control your output if you choose:
|
367
424
|
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
425
|
+
```Ruby
|
426
|
+
describe 'test file' do
|
427
|
+
subject { file('/tmp/test.txt') }
|
428
|
+
it 'should be a file' do
|
429
|
+
expect(subject).to(be_file)
|
430
|
+
end
|
431
|
+
end
|
432
|
+
```
|
374
433
|
|
375
434
|
... which will render the following output:
|
376
435
|
|
377
|
-
|
378
|
-
|
436
|
+
```text
|
437
|
+
test file
|
438
|
+
✔ should be a file
|
439
|
+
```
|