inspec 2.2.35 → 2.2.41

Sign up to get free protection for your applications and to get access to all the features.
@@ -42,10 +42,10 @@ end
42
42
 
43
43
  That said, InSpec is not RSpec. Some key differences:
44
44
 
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.
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
 
@@ -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
- verifier:
12
- name: inspec
11
+ ```YML
12
+ verifier:
13
+ name: inspec
14
+ ```
13
15
 
14
16
  Use a compliance profile from the Chef Compliance server:
15
17
 
16
- suites:
17
- - name: compliance
18
- run_list:
19
- - recipe[ssh-hardening::default]
20
- verifier:
21
- inspec_tests:
22
- - compliance://base/ssh
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
- $ inspec compliance login https://compliance.test --user admin --insecure --token ''
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
- suites:
33
- - name: supermarket
34
- run_list:
35
- - recipe[ssh-hardening::default]
36
- verifier:
37
- inspec_tests:
38
- - supermarket://dev-sec/ssh-baseline
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
- suites:
43
- - name: local
44
- run_list:
45
- - recipe[my_cookbook::default]
46
- verifier:
47
- inspec_tests:
48
- - test/integration/default
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.
@@ -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
- examples/profile
14
- ├── README.md
15
- ├── controls
16
- ├── example.rb
17
- └── control_etc.rb
18
- ├── libraries
19
- │ └── extension.rb
20
- |── files
21
- │ └── extras.conf
22
- └── inspec.yml
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
- * Use `name` to specify a unique name for the profile. Required.
41
- * Use `title` to specify a human-readable name for the profile.
42
- * Use `maintainer` to specify the profile maintainer.
43
- * Use `copyright` to specify the copyright holder.
44
- * Use `copyright_email` to specify support contact information for the profile, typically an email address.
45
- * Use `license` to specify the license for the profile.
46
- * Use `summary` to specify a one line summary for the profile.
47
- * Use `description` to specify a multiple line description of the profile.
48
- * Use `version` to specify the profile version.
49
- * Use `inspec_version` to place SemVer constraints on the version of InSpec that the profile can run under.
50
- * Use `supports` to specify a list of supported platform targets.
51
- * Use `depends` to define a list of profiles on which this profile depends.
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
- name: ssh
56
- title: Basic SSH
57
- maintainer: Chef Software, Inc.
58
- copyright: Chef Software, Inc.
59
- copyright_email: support@chef.io
60
- license: Proprietary, All rights reserved
61
- summary: Verify that SSH Server and SSH Client are configured securely
62
- version: 1.0.0
63
- supports:
64
- - os-family: linux
65
- depends:
66
- - name: profile
67
- path: ../path/to/profile
68
- inspec_version: "~> 2.1"
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
- $ inspec check examples/profile
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
- name: ssh
81
- supports:
82
- - os-name: debian
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
- name: ssh
87
- supports:
88
- - os-name: ubuntu
89
- release: 14.04
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
- name: ssh
94
- supports:
95
- - os-family: redhat
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
- name: ssh
100
- supports:
101
- - platform: aws
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
- name: ssh
106
- supports:
107
- - os-name: debian
108
- - os-name: ubuntu
109
- release: 14.04
110
- - os-family: redhat
111
- - platform: aws
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
- depends:
125
- - name: linux-baseline
126
- url: https://github.com/dev-sec/linux-baseline/archive/master.tar.gz
127
- - name: ssh-baseline
128
- url: https://github.com/dev-sec/ssh-baseline/archive/master.tar.gz
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
- depends:
137
- - name: my-profile
138
- path: /absolute/path
139
- - name: another
140
- path: ../relative/path
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
- depends:
147
- - name: my-profile
148
- url: https://my.domain/path/to/profile.tgz
149
- - name: profile-via-git
150
- url: https://github.com/myusername/myprofile-repo/archive/master.tar.gz
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
- depends:
159
- - name: git-profile
160
- git: http://url/to/repo
161
- branch: desired_branch
162
- tag: desired_version
163
- commit: pinned_commit
164
- version: semver_via_tags
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
- depends:
173
- - name: supermarket-profile
174
- supermarket: supermarket-username/supermarket-profile
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
- depends:
185
- - name: linux
186
- compliance: base/linux
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
- * myapp-1
207
- * myapp-2
208
- * myapp-3
209
- * baseline-1
210
- * baseline-2
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
- * myapp-1
242
- * myapp-2
243
- * myapp-3
244
- * baseline-2
245
- * baseline-4
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
- require_resource(profile: 'my_dep', resource: 'my_res',
263
- as: 'my_res2')
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 Yaml file located on the local machine, and then run `inspec exec` and specify the path to that Yaml file using the `--attrs` attribute.
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
- # define these attributes on the top-level of your file and re-use them across all tests!
275
- val_user = attribute('user', default: 'alice', description: 'An identification for the user')
276
- val_password = attribute('password', description: 'A value for the password')
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
- control 'system-users' do
279
- impact 0.8
280
- desc '
281
- This test assures that the user "Bob" has a user installed on the system, along with a
282
- specified password.
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
- describe val_user do
286
- it { should eq 'bob' }
287
- end
325
+ val_user do
326
+ it { should eq 'bob' }
327
+ end
288
328
 
289
- describe val_password do
290
- it { should eq 'secret' }
291
- end
292
- end
329
+ describe val_password do
330
+ it { should eq 'secret' }
331
+ end
332
+ end
333
+ ```
293
334
 
294
- And a Yaml file named `profile-attribute.yml`:
335
+ And a YAML file named `profile-attribute.yml`:
295
336
 
296
- user: bob
297
- password: secret
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
- $ inspec exec examples/profile-attribute --attrs examples/profile-attribute.yml
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
- examples/profile
314
- ├── controls
315
- ├── example.rb
316
- |── files
317
- │ └── services.yml
318
- └── inspec.yml
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
- - service_name: httpd-alpha
323
- port: 80
324
- - service_name: httpd-beta
325
- port: 8080
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
- my_services = yaml(content: inspec.profile.file('services.yml')).params
378
+ ```Ruby
379
+ my_services = yaml(content: inspec.profile.file('services.yml')).params
330
380
 
331
- my_services.each do |s|
332
- describe service(s['service_name']) do
333
- it { should be_running }
334
- end
381
+ my_services.each do |s|
382
+ describe service(s['service_name']) do
383
+ it { should be_running }
384
+ end
335
385
 
336
- describe port(s['port']) do
337
- it { should be_listening }
338
- end
339
- end
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
- describe file('/tmp/test.txt') do
350
- it { should be_file }
351
- end
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
- describe file('/tmp/test.txt') do
356
- it 'should be a file' do
357
- expect(subject).to(be_file)
358
- end
359
- end
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
- File /tmp/test.txt
364
- ✔ should be a file
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
- describe 'test file' do
369
- subject { file('/tmp/test.txt') }
370
- it 'should be a file' do
371
- expect(subject).to(be_file)
372
- end
373
- end
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
- test file
378
- ✔ should be a file
436
+ ```text
437
+ test file
438
+ ✔ should be a file
439
+ ```