InSpec docs reorganization (#6844)

* Cloud platform docs

Signed-off-by: Ian Maddaus <ian.maddaus@progress.com>

* Profiles docs

Signed-off-by: Ian Maddaus <ian.maddaus@progress.com>

* Move related tools

Signed-off-by: Ian Maddaus <ian.maddaus@progress.com>

* Edit inspec exec

Signed-off-by: Ian Maddaus <ian.maddaus@progress.com>

* Rewrite landing page

Signed-off-by: Ian Maddaus <ian.maddaus@progress.com>

* Rewrite config page

Signed-off-by: Ian Maddaus <ian.maddaus@progress.com>

* More changes

Signed-off-by: Ian Maddaus <ian.maddaus@progress.com>

* Reorganize pages in menu

Signed-off-by: Ian Maddaus <ian.maddaus@progress.com>

* Reorganizing profile signing page

Signed-off-by: Ian Maddaus <ian.maddaus@progress.com>

* Fix link

Signed-off-by: Ian Maddaus <ian.maddaus@progress.com>

---------

Signed-off-by: Ian Maddaus <ian.maddaus@progress.com>
This commit is contained in:
Ian Maddaus 2023-11-16 04:34:17 -05:00 committed by GitHub
parent a84498ca5f
commit 9735125ec5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 3082 additions and 2485 deletions

View file

@ -15,6 +15,30 @@ identifier = "inspec"
parent = "inspec"
weight = 20
[[menu.inspec]]
title = "Profiles"
identifier = "inspec/profiles"
parent = "inspec"
weight = 40
[[menu.inspec]]
title = "Cloud Platforms"
identifier = "inspec/cloud"
parent = "inspec"
weight = 50
[[menu.inspec]]
title = "Chef Tools"
identifier = "inspec/chef"
parent = "inspec"
weight = 480
[[menu.inspec]]
title = "Related Projects"
identifier = "inspec/friends"
parent = "inspec"
weight = 490
[[menu.inspec]]
title = "Chef InSpec Reference"
identifier = "inspec/reference"

View file

@ -14,37 +14,71 @@ gh_repo = "inspec"
weight = 10
+++
Chef InSpec is an open-source framework for testing and auditing your applications and infrastructure. Chef InSpec works by comparing the actual state of your system with the desired state that you express in easy-to-read and easy-to-write Chef InSpec code. Chef InSpec detects violations and displays findings in the form of a report, but puts you in control of remediation.
Chef InSpec is an open-source framework for testing and auditing your applications and infrastructure.
It compares the actual state of your system with the desired state that you express in easy-to-read and easy-to-write Chef InSpec code.
It detects violations and displays findings in the form of a report, but puts you in control of remediation.
## Getting started with Chef InSpec
Chef InSpec is a run-time framework and rule language used to specify compliance, security, and policy requirements.
It includes a collection of resources that help you write auditing controls quickly and easily.
Below are some of the core concepts that make up Chef InSpec.
## How does Chef InSpec work?
### Create a profile
Chef InSpec uses profiles to audit infrastructure. An [InSpec profile](/inspec/profile/) organizes multiple controls into a reusable artifact.
You can describe your profiles with metadata, version them, pin them to specific versions of InSpec, define specific platforms that a profile can test, and define profile dependencies.
[Profiles](/inspec/profiles/) are the core of the Chef InSpec testing experience. Use Chef InSpec
profiles to manage everything you need to run a security or compliance scan--attributes,
metadata, and the tests themselves.
A control defines a regulatory recommendation or requirement for the state of a system. Each profile can have many controls and each control audits different aspects of a system.
### Add your tests
Chef InSpec resources allow you to test specific parts of your infrastructure.
Chef InSpec has {{% inspec/inspec_count_resources %}} [resources](/inspec/resources/) ready to use--from Apache2 to ZFS pool.
This includes resources for testing [AWS, Azure, AliCloud, and GCP cloud infrastructure](/inspec/cloud/), and you can create your own [custom resources](profiles/custom_resources) if we don't have a resource that meets your needs.
You can create tests three different ways: By composing your own tests, by
including tests from the [Chef Supermarket](https://supermarket.chef.io/)
or by adding tests from the [Dev-Sec Project](http://dev-sec.io/) as dependencies.
You can also customize your tests--pulling in the tests from our Supermarket and
change them to suit your unique needs with the easy-to-read and easy-to-write Chef
InSpec language.
[InSpec reporters](/inspec/reporters/) format and deliver the results of an InSpec audit run.
You can output results to the standard output; to text formats like JSON, HTML, or plain text; or send the results directly to [Chef Automate](/automate/).
### Target your system
## Use cases
Run your tests wherever your infrastructure is--locally or in the cloud. Chef
InSpec is designed for platforms and treats operating systems as special cases.
Run your tests wherever your infrastructure is---locally or in the cloud.
Chef InSpec is designed for platforms and treats operating systems as special cases.
Chef InSpec helps you, whether you use Windows Server on your own hardware or
run Linux in Docker containers in the cloud. As for the cloud, you can use Chef
InSpec to target applications and services running on AWS and Azure.
InSpec to target applications and services running on Alibaba, AWS, Azure, and GCP.
### Resources
## Additional Resources
Chef InSpec has {{% inspec/inspec_count_resources %}} [resources](/inspec/resources/) ready to use--from Apache2 to ZFS pool.
If you need a solution that we havent provided, you can write your own [custom
resource](/inspec/dsl_resource/).
### Open-source profiles
The InSpec community created several open-source profiles that are free to use.
Use the `inspec supermarket profiles` command to list the available profiles, or view them in [Chef Supermarket](https://supermarket.chef.io/tools?q=&type=compliance_profile). This includes the [DevSec Hardening Framework](https://dev-sec.io/), a set of server hardening profiles.
### Premium profiles
Chef offers [premium CIS- and STIG-based profiles](https://www.chef.io/products/chef-premium-content) for compliance scanning across a range of enterprise assets.
### Learning
- [Learn Chef: Test Expectations with Chef InSpec](https://learn.chef.io/courses/course-v1:chef+Inspec101+Perpetual/about)
- [Learn Chef: Extending InSpec: InSpec Wrappers and Custom Resources](https://learn.chef.io/courses/course-v1:chef+InSpec201+Perpetual/about)
- [Chef InSpec webinars](https://www.chef.io/webinars?products=chef-inspec&page=1)
- [Chef Resource Library](https://www.chef.io/resources?products=chef-inspec&page=1)
### Community
- [Chef InSpec on Discourse](https://discourse.chef.io/c/inspec/10)
- [Chef InSpec in the Chef Blog](https://www.chef.io/blog/category/chef-inspec)
- [Chef InSpec Community Resources](https://community.chef.io/tools/chef-inspec)
### Support
- [Chef Support](https://www.chef.io/support)
- [Chef Help Center](https://community.progress.com/s/products/chef)
### GitHub repositories
- [inspec GitHub organization](https://github.com/inspec)
- [inspec repository](https://github.com/inspec/inspec/)
- [inspec-alicloud repository](https://github.com/inspec/inspec-alicloud/)
- [inspec-aws repository](https://github.com/inspec/inspec-aws/)
- [inspec-azure](https://github.com/inspec/inspec-azure/)
- [inspec-gcp repository](https://github.com/inspec/inspec-gcp/)
- [inspec-k8s repository](https://github.com/inspec/inspec-k8s/)
- [inspec train repository](https://github.com/inspec/train)

View file

@ -6,8 +6,8 @@ gh_repo = "inspec"
[menu]
[menu.inspec]
title = "Audit Log"
identifier = "inspec/reference/audit_logging.md InSpec audit log"
parent = "inspec/reference"
identifier = "inspec/Audit Log"
parent = "inspec"
weight = 60
+++
@ -48,4 +48,4 @@ The following options are available inside `inspec exec` and `inspec shell` to c
## More information
For details of the audit log format and implementation, refer to the (Train documentation)[https://github.com/inspec/train/blob/main/docs/audit_log.md].
For details of the audit log format and implementation, refer to the [Train documentation](https://github.com/inspec/train/blob/main/docs/audit_log.md).

View file

@ -275,99 +275,6 @@ Run all test files at the specified locations.
The subcommand loads the given profiles, fetches their dependencies if needed, then connects to the target and executes any controls in the profiles. One or more reporters are used to generate the output.
```ruby
exit codes:
0 normal exit, all tests passed
1 usage or general error
2 error in plugin system
3 fatal deprecation encountered
5 invalid profile signature
6 mandatory profile signing mode enabled and no signature found
100 normal exit, at least one test failed
101 normal exit, at least one test skipped but none failed
172 chef license not accepted
```
### Examples
Below are some examples of using `exec` with different test locations.
Chef Automate:
```ruby
inspec automate login
inspec exec compliance://username/linux-baselinem
```
`inspec compliance` is a backwards compatible alias for `inspec automate` and works the same way:
```ruby
inspec compliance login
```
Chef Supermarket:
```ruby
inspec exec supermarket://username/linux-baseline
inspec exec supermarket://username/linux-baseline --supermarket_url="https://privatesupermarket.example.com"
```
Local profile (executes all tests in `controls/`):
```ruby
inspec exec /path/to/profile
```
Local single test (doesn't allow inputs or custom resources):
```ruby
inspec exec /path/to/a_test.rb
```
Git via SSH:
```ruby
inspec exec git@github.com:dev-sec/linux-baseline.git
```
Git via HTTPS (.git suffix is required):
```ruby
inspec exec https://github.com/dev-sec/linux-baseline.git
```
Private Git via HTTPS (.git suffix is required):
```ruby
inspec exec https://api_token@github.com/dev-sec/linux-baseline.git
```
Private Git via HTTPS and cached credentials (.git suffix is required):
```bash
git config credential.helper cache
git ls-remote https://github.com/dev-sec/linux-baseline.git
inspec exec https://github.com/dev-sec/linux-baseline.git
```
Web-hosted file (also supports .zip):
```bash
inspec exec https://webserver/linux-baseline.tar.gz
```
Web-hosted file with basic authentication (supports .zip):
```bash
inspec exec https://username:password@webserver/linux-baseline.tar.gz
```
Web-hosted signed profile:
```bash
inspec exec https://username:password@webserver/linux-baseline.iaf
```
### Syntax
This subcommand has the following syntax:
@ -390,7 +297,7 @@ This subcommand has the following additional options:
For more information, see [Signed InSpec Profiles](/inspec/signing/).
`--attrs=one two three`
: Legacy name for --input-file - deprecated.
: Legacy name for `--input-file` - deprecated.
`--audit-log-location=AUDIT_LOG_LOCATION`
: The directory that the audit log saves diagnostic log files to.
@ -409,7 +316,7 @@ This subcommand has the following additional options:
`--backend-cache`
`--no-backend-cache`
: Allow caching for backend command output. (default: true).
: Allow caching for backend command output. (default: `true`).
`--bastion-host=BASTION_HOST`
: Specifies the bastion host if applicable.
@ -450,7 +357,7 @@ This subcommand has the following additional options:
: Exit with code 101 if any tests fail and 100 if any are skipped (default). If disabled, exit 0 on skips and 1 for failures.
`--docker-url`
: Provides path to Docker API endpoint (Docker). Defaults to unix:///var/run/docker.sock on Unix systems and tcp://localhost:2375 on Windows.
: Provides path to Docker API endpoint (Docker). Defaults to `unix:///var/run/docker.sock` on Unix systems and `tcp://localhost:2375` on Windows.
`--enable-password=ENABLE_PASSWORD`
: Password for enable mode on Cisco IOS devices.
@ -460,13 +367,13 @@ This subcommand has the following additional options:
: Filter empty profiles (profiles without controls) from the report.
`--filter-waived-controls`
: Do not execute waived controls in InSpec at all. Must use with --waiver-file. Ignores the `run` setting of the waiver file.
: Do not execute waived controls in InSpec at all. Must use with `--waiver-file`. Ignores the `run` setting of the waiver file.
`--host=HOST`
: Specify a remote host which is tested.
`--input=name1=value1 name2=value2`
: Specify one or more inputs directly on the command line, as --input NAME=VALUE. Accepts single-quoted YAML and JSON structures.
: Specify one or more inputs directly on the command line, as `--input NAME=VALUE`. Accepts single-quoted YAML and JSON structures.
`--input-file=one two three`
: Load one or more input files, a YAML file with values for the profile to use.
@ -490,7 +397,7 @@ This subcommand has the following additional options:
: Specify the login port for a remote scan.
`--podman-url`
: Provides the path to the Podman API endpoint. Defaults to unix:///run/user/$UID/podman/podman.sock for rootless container, unix:///run/podman/podman.sock for rootful container (for this you need to execute inspec as root user).
: Provides the path to the Podman API endpoint. Defaults to `unix:///run/user/$UID/podman/podman.sock` for rootless container, `unix:///run/podman/podman.sock` for rootful container (for this you need to execute inspec as root user).
`--profiles-path=PROFILES_PATH`
: Folder which contains referenced profiles.
@ -503,7 +410,7 @@ This subcommand has the following additional options:
`--reporter-backtrace-inclusion`
`--no-reporter-backtrace-inclusion`
: Include a code backtrace in report data (default: true).
: Include a code backtrace in report data (default: `true`).
`--reporter-include-source`
: Include full source code of controls in the CLI report.
@ -588,6 +495,115 @@ This subcommand has the following additional options:
`--enhanced-outcomes`
: Includes enhanced outcome of controls in report data.
### Exit codes
`0`
: normal exit, all tests passed
`1`
: usage or general error
`2`
: error in plugin system
`3`
: fatal deprecation encountered
`5`
: invalid profile signature
`6`
: mandatory profile signing mode enabled and no signature found
`100`
: normal exit, at least one test failed
`101`
: normal exit, at least one test skipped but none failed
`172`
: Chef license not accepted
### Examples
Below are some examples of using `exec` with different test locations.
Chef Automate:
```ruby
inspec automate login
inspec exec compliance://username/linux-baselinem
```
`inspec compliance` is a backwards compatible alias for `inspec automate` and works the same way:
```ruby
inspec compliance login
```
Chef Supermarket:
```ruby
inspec exec supermarket://username/linux-baseline
inspec exec supermarket://username/linux-baseline --supermarket_url="https://privatesupermarket.example.com"
```
Local profile (executes all tests in `controls/`):
```ruby
inspec exec /path/to/profile
```
Local single test (doesn't allow inputs or custom resources):
```ruby
inspec exec /path/to/a_test.rb
```
Git via SSH:
```ruby
inspec exec git@github.com:dev-sec/linux-baseline.git
```
Git via HTTPS (.git suffix is required):
```ruby
inspec exec https://github.com/dev-sec/linux-baseline.git
```
Private Git via HTTPS (.git suffix is required):
```ruby
inspec exec https://api_token@github.com/dev-sec/linux-baseline.git
```
Private Git via HTTPS and cached credentials (.git suffix is required):
```bash
git config credential.helper cache
git ls-remote https://github.com/dev-sec/linux-baseline.git
inspec exec https://github.com/dev-sec/linux-baseline.git
```
Web-hosted file (also supports .zip):
```bash
inspec exec https://webserver/linux-baseline.tar.gz
```
Web-hosted file with basic authentication (supports .zip):
```bash
inspec exec https://username:password@webserver/linux-baseline.tar.gz
```
Web-hosted signed profile:
```bash
inspec exec https://username:password@webserver/linux-baseline.iaf
```
## habitat
Create a Chef Habitat package.

View file

@ -0,0 +1,19 @@
+++
title = "Using Chef InSpec on Cloud Platforms"
draft = false
gh_repo = "inspec"
[menu]
[menu.inspec]
title = "Overview"
identifier = "inspec/cloud/"
parent = "inspec/cloud"
weight = 10
+++
Chef InSpec provides resources for auditing the following cloud platforms:
- [Alibaba Cloud](alicloud)
- [AWS](aws)
- [Azure](azure)
- [GCP](gcp)

View file

@ -0,0 +1,30 @@
+++
title = "Chef InSpec and Alibaba Cloud"
draft = false
gh_repo = "inspec"
[menu]
[menu.inspec]
title = "AliCloud"
identifier = "inspec/cloud/alibaba"
parent = "inspec/cloud"
+++
Chef InSpec has resources for auditing Alibaba.
You will need to install AliCloud SDK version 0.8.0 and require AliCloud credentials to use the Chef InSpec AliCloud resources.
## Set AliCloud credentials
You can configure AliCloud credentials in an [.envrc file](https://github.com/inspec/inspec-alicloud/blob/main/.envrc_example) or export them in your shell.
```bash
# Example configuration
export ALICLOUD_ACCESS_KEY="anaccesskey"
export ALICLOUD_SECRET_KEY="asecretkey"
export ALICLOUD_REGION="eu-west-1"
```
## Alibaba resources
{{< inspec/inspec_resources platform="alicloud" >}}

View file

@ -0,0 +1,87 @@
+++
title = "Chef InSpec and AWS"
draft = false
gh_repo = "inspec"
[menu]
[menu.inspec]
title = "AWS"
identifier = "inspec/cloud/aws"
parent = "inspec/cloud"
+++
Chef InSpec has resources for auditing AWS.
## Initialize an InSpec profile for auditing AWS
With Chef InSpec 4 or greater, you can create a profile for testing AWS resources with `inspec init profile`:
```bash
$ inspec init profile --platform aws <PROFILE_NAME>
Create new profile at /Users/me/<PROFILE_NAME>
* Creating directory libraries
* Creating file README.md
* Creating directory controls
* Creating file controls/example.rb
* Creating file inspec.yml
* Creating file inputs.yml
* Creating file libraries/.gitkeep
```
Assuming the `inputs.yml` file contains your AWS project ID, you can execute this sample profile using the following command:
```bash
inspec exec <PROFILE_NAME> --input-file=<PROFILE_NAME>/inputs.yml -t gcp://
```
## Set AWS credentials
Chef InSpec uses the standard AWS authentication mechanisms. Typically, you will create an IAM user specifically for auditing activities.
1. Create an IAM user in the AWS console, with your choice of username. Check the box marked "Programmatic Access."
1. On the Permissions screen, choose Direct Attach. Select the AWS-managed IAM profile named "ReadOnlyAccess." If you wish to restrict the user further, you may do so; see individual Chef InSpec resources to identify which permissions are required.
1. After generating the key, record the access key ID and secret key.
### Provide credentials with environment variables
You may provide the credentials to Chef InSpec by setting the following environment variables: `AWS_REGION`, `AWS_ACCESS_KEY_ID`, and `AWS_SECRET_ACCESS_KEY`. You may also use `AWS_PROFILE`, or if you are using MFA, `AWS_SESSION_TOKEN`. See the [AWS Command Line Interface Docs](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html) for details.
Once you have your environment variables set, you can verify your credentials by running:
```bash
$ inspec detect -t aws://
== Platform Details
Name: aws
Families: cloud, api
Release: aws-sdk-v2.10.125
```
### Provide credentials using Chef InSpec target option
Look for a file in your home directory named `~/.aws/credentials`. If it does not exist, create it. Choose a name for your profile; here, we're using the name 'auditing'. Add your credentials as a new profile, in INI format:
```bash
[auditing]
aws_access_key_id = AKIA....
aws_secret_access_key = 1234....abcd
```
You may now run Chef InSpec using the `--target` / `-t` option, using the format `-t aws://region/profile`. For example, to connect to the Ohio region using a profile named 'auditing', use `-t aws://us-east-2/auditing`.
To verify your credentials, run:
```bash
$ inspec detect -t aws://
== Platform Details
Name: aws
Families: cloud, api
Release: aws-sdk-v2.10.125
```
## AWS resources
{{< inspec/inspec_resources platform="aws" >}}

View file

@ -0,0 +1,104 @@
+++
title = "Chef InSpec and Azure"
draft = false
gh_repo = "inspec"
[menu]
[menu.inspec]
title = "Azure"
identifier = "inspec/cloud/azure"
parent = "inspec/cloud"
+++
Chef InSpec has resources for auditing Azure.
## Initialize an InSpec profile for auditing Azure
With Chef InSpec 4 or greater, you can create a profile for testing AWS resources with `inspec init profile`:
```bash
$ inspec init profile --platform azure <PROFILE_NAME>
Create new profile at /Users/me/<PROFILE_NAME>
* Creating directory libraries
* Creating file README.md
* Creating directory controls
* Creating file controls/example.rb
* Creating file inspec.yml
* Creating file inputs.yml
* Creating file libraries/.gitkeep
```
Assuming the `inputs.yml` file contains your Azure project ID, you can execute this sample profile using the following command:
```bash
inspec exec <PROFILE_NAME> --input-file=<PROFILE_NAME>/inputs.yml -t gcp://
```
## Set Azure credentials
To use Chef InSpec Azure resources, you will need to create a Service Principal Name (SPN) for auditing an Azure subscription.
This can be done on the command line or from the Azure Portal:
- [Azure CLI](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-authenticate-service-principal-cli)
- [PowerShell](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-authenticate-service-principal)
- [Azure Portal](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal)
The information from the SPN can be specified either in the file `~/.azure/credentials`, as environment variables, or by using Chef InSpec target URIs.
### Set the Azure credentials file
By default, Chef InSpec is configured to look at `~/.azure/credentials`, and it should contain:
```powershell
[<SUBSCRIPTION_ID>]
client_id = "<CLIENT_ID>"
client_secret = "<CLIENT_SECRET>"
tenant_id = "<TENANT_ID>"
```
{{< note >}}
In the Azure web portal, these values are labeled differently:
- The client_id is referred to as the 'Application ID'
- The client_secret is referred to as the 'Key (Password Type)'
- The tenant_id is referred to as the 'Directory ID'
{{< /note >}}
With the credentials in place, you can now execute Chef InSpec.
```bash
inspec exec <PROFILE_NAME> -t azure://
```
### Provide credentials using environment variables
You may also set the Azure credentials via environment variables:
- `AZURE_SUBSCRIPTION_ID`
- `AZURE_CLIENT_ID`
- `AZURE_CLIENT_SECRET`
- `AZURE_TENANT_ID`
For example:
```bash
AZURE_SUBSCRIPTION_ID="2fbdbb02-df2e-11e6-bf01-fe55135034f3" \
AZURE_CLIENT_ID="58dc4f6c-df2e-11e6-bf01-fe55135034f3" \
AZURE_CLIENT_SECRET="Jibr4iwwaaZwBb6W" \
AZURE_TENANT_ID="6ad89b58-df2e-11e6-bf01-fe55135034f3" inspec exec my-profile -t azure://
```
### Provide credentials using Chef InSpec target option
If you have created a `~/.azure/credentials` file as above, you may also use the Chef InSpec command line `--target` / `-t` option to select a subscription ID. For example:
```bash
inspec exec my-profile -t azure://2fbdbb02-df2e-11e6-bf01-fe55135034f3
```
## Azure resources
{{< inspec/inspec_resources platform="azure" >}}

View file

@ -0,0 +1,76 @@
+++
title = "Chef InSpec and GCP"
draft = false
gh_repo = "inspec"
[menu]
[menu.inspec]
title = "GCP"
identifier = "inspec/cloud/gcp"
parent = "inspec/cloud"
+++
Chef InSpec has resources for auditing GCP.
## Initialize an InSpec profile for auditing GCP
With Chef InSpec 4 or greater, you can create a profile for testing GCP resources with `inspec init profile`:
```bash
$ inspec init profile --platform gcp my-profile
Create new profile at /Users/me/my-profile
* Creating directory libraries
* Creating file README.md
* Creating directory controls
* Creating file controls/example.rb
* Creating file inspec.yml
* Creating file inputs.yml
* Creating file libraries/.gitkeep
```
Assuming the `inputs.yml` file contains your GCP project ID, this sample profile can then be executed using the following command:
```bash
inspec exec my-profile --input-file=my-profile/inputs.yml -t gcp://
```
## Set GCP credentials
To use Chef InSpec GCP resources, you will need to install and configure the Google Cloud SDK.
Instructions for this pre-requisite can be found in the [Google CLoud SDK documentation](https://cloud.google.com/sdk/docs/).
### Set the GCP credentials file
While InSpec can use user accounts for authentication, [Google Cloud documentation](https://cloud.google.com/docs/authentication/) recommends using service accounts.
1. Create a [service account](https://cloud.google.com/docs/authentication/getting-started) with the scopes appropriate for your needs.
1. Download the credential JSON file, for example `project-credentials.json`, to your workspace and activate your service account with `gcloud auth activate-service-account`.
```bash
gcloud auth activate-service-account --key-file project-credentials.json
```
### Provide credentials using environment variables
You may also set the GCP credentials json file via the `GOOGLE_APPLICATION_CREDENTIALS` environment variable.
```bash
export GOOGLE_APPLICATION_CREDENTIALS='/Users/me/.config/gcloud/myproject-1-feb7993e8660.json'
```
Once you have your environment variables set, you can verify your credentials by running:
```bash
$ inspec detect -t gcp://
== Platform Details
Name: gcp
Families: cloud, api
Release: google-cloud-v
```
## GCP resources
{{< inspec/inspec_resources platform="gcp" >}}

View file

@ -1,207 +0,0 @@
+++
title = "Using Chef InSpec on Cloud Platforms"
draft = false
gh_repo = "inspec"
[menu]
[menu.inspec]
title = "Chef InSpec for the Cloud"
identifier = "inspec/Chef InSpec on Cloud Platforms"
parent = "inspec"
weight = 30
+++
As of Chef InSpec 2.0, we have expanded our platform support beyond individual machines and now include support for select AWS, Azure, GCP, and AliCloud resources.
Using InSpec, you can use several Chef InSpec resources to audit properties of your cloud infrastructure - for example, an Amazon Web Services S3 bucket.
## AWS Platform Support in InSpec
### Setting up AWS credentials for InSpec
Chef InSpec uses the standard AWS authentication mechanisms. Typically, you will create an IAM user specifically for auditing activities.
1. Create an IAM user in the AWS console, with your choice of username. Check the box marked "Programmatic Access."
1. On the Permissions screen, choose Direct Attach. Select the AWS-managed IAM Profile named "ReadOnlyAccess." If you wish to restrict the user further, you may do so; see individual Chef InSpec resources to identify which permissions are required.
1. After generating the key, record the Access Key ID and Secret Key.
#### Using Environment Variables to provide credentials
You may provide the credentials to Chef InSpec by setting the following environment variables: `AWS_REGION`, `AWS_ACCESS_KEY_ID`, and `AWS_SECRET_ACCESS_KEY`. You may also use `AWS_PROFILE`, or if you are using MFA, `AWS_SESSION_TOKEN`. See the [AWS Command Line Interface Docs](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html) for details.
Once you have your environment variables set, you can verify your credentials by running:
```bash
$ inspec detect -t aws://
== Platform Details
Name: aws
Families: cloud, api
Release: aws-sdk-v2.10.125
```
#### Using the Chef InSpec target option to provide credentials on AWS
Look for a file in your home directory named `~/.aws/credentials`. If it does not exist, create it. Choose a name for your profile; here, we're using the name 'auditing'. Add your credentials as a new profile, in INI format:
```bash
[auditing]
aws_access_key_id = AKIA....
aws_secret_access_key = 1234....abcd
```
You may now run Chef InSpec using the `--target` / `-t` option, using the format `-t aws://region/profile`. For example, to connect to the Ohio region using a profile named 'auditing', use `-t aws://us-east-2/auditing`.
To verify your credentials, run:
```bash
$ inspec detect -t aws://
== Platform Details
Name: aws
Families: cloud, api
Release: aws-sdk-v2.10.125
```
## Azure Platform Support in InSpec
### Setting up Azure credentials for InSpec
To use Chef InSpec Azure resources, you will need to create a Service Principal Name (SPN) for auditing an Azure subscription.
This can be done on the command line or from the Azure Portal:
- [Azure CLI](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-authenticate-service-principal-cli)
- [PowerShell](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-authenticate-service-principal)
- [Azure Portal](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal)
The information from the SPN can be specified either in the file `~/.azure/credentials`, as environment variables, or by using Chef InSpec target URIs.
#### Setting up the Azure Credentials File
By default, Chef InSpec is configured to look at `~/.azure/credentials`, and it should contain:
```powershell
[<SUBSCRIPTION_ID>]
client_id = "<CLIENT_ID>"
client_secret = "<CLIENT_SECRET>"
tenant_id = "<TENANT_ID>"
```
{{< note >}}
In the Azure web portal, these values are labeled differently:
- The client_id is referred to as the 'Application ID'
- The client_secret is referred to as the 'Key (Password Type)'
- The tenant_id is referred to as the 'Directory ID'
{{< /note >}}
With the credentials are in place, you may now execute InSpec:
```bash
inspec exec my-inspec-profile -t azure://
```
#### Using Environment variables to provide credentials
You may also set the Azure credentials via environment variables:
- `AZURE_SUBSCRIPTION_ID`
- `AZURE_CLIENT_ID`
- `AZURE_CLIENT_SECRET`
- `AZURE_TENANT_ID`
For example:
```bash
AZURE_SUBSCRIPTION_ID="2fbdbb02-df2e-11e6-bf01-fe55135034f3" \
AZURE_CLIENT_ID="58dc4f6c-df2e-11e6-bf01-fe55135034f3" \
AZURE_CLIENT_SECRET="Jibr4iwwaaZwBb6W" \
AZURE_TENANT_ID="6ad89b58-df2e-11e6-bf01-fe55135034f3" inspec exec my-profile -t azure://
```
#### Using the Chef InSpec target option to provide credentials on Azure
If you have created a `~/.azure/credentials` file as above, you may also use the Chef InSpec command line `--target` / `-t` option to select a subscription ID. For example:
```bash
inspec exec my-profile -t azure://2fbdbb02-df2e-11e6-bf01-fe55135034f3
```
## AliCloud Platform Support in InSpec
You will need to install AliCloud SDK version 0.8.0 and require AliCloud credentials to use the Chef InSpec AliCloud resources.
### Setting up AliCloud credentials for InSpec
You can configure AliCloud credentials in an [.envrc file](https://github.com/inspec/inspec-alicloud#:~:text=shell.%20(See%20example-,.envrc%20file,-)) or export them in your shell.
```bash
# Example configuration
export ALICLOUD_ACCESS_KEY="anaccesskey"
export ALICLOUD_SECRET_KEY="asecretkey"
export ALICLOUD_REGION="eu-west-1"
```
## GCP Platform Support in InSpec
### Setting up GCP credentials for InSpec
To use Chef InSpec GCP resources, you will need to install and configure the Google Cloud SDK. Instructions for this pre-requisite can be found in the
[Google CLoud SDK documentation](https://cloud.google.com/sdk/docs/). Be sure that your InSpec installation is the latest version. The minimal required InSpec version is 3.0.25.
### Create an InSpec profile that makes use of `inspec-gcp`
With a version of InSpec above 4.0.0, it is possible to create a profile with the following command:
```bash
$ inspec init profile --platform gcp my-profile
Create new profile at /Users/me/my-profile
* Creating directory libraries
* Creating file README.md
* Creating directory controls
* Creating file controls/example.rb
* Creating file inspec.yml
* Creating file inputs.yml
* Creating file libraries/.gitkeep
```
Assuming the `inputs.yml` file contains your GCP project ID, this sample profile can then be executed using the following command:
```bash
inspec exec my-profile --input-file=my-profile/inputs.yml -t gcp://
```
#### Setting up the GCP Credentials File
While InSpec can use user accounts for authentication, [Google Cloud documentation](https://cloud.google.com/docs/authentication/) recommends using service accounts. Following GCP best practices, first create a service account with the scopes appropriate for your needs. See [these instructions](https://cloud.google.com/docs/authentication/getting-started) on creating a service account.
Then, download the credential JSON file, e.g. `project-credentials.json`, to your workspace and run the following command to activate your service account:
```bash
gcloud auth activate-service-account --key-file project-credentials.json
```
#### Using Environment variables for providing credentials
You may also set the GCP credentials json file via the `GOOGLE_APPLICATION_CREDENTIALS` environment variable.
```bash
export GOOGLE_APPLICATION_CREDENTIALS='/Users/me/.config/gcloud/myproject-1-feb7993e8660.json'
```
Once you have your environment variables set, you can verify your credentials by running:
```bash
$ inspec detect -t gcp://
== Platform Details
Name: gcp
Families: cloud, api
Release: google-cloud-v
```

View file

@ -5,38 +5,38 @@ gh_repo = "inspec"
[menu]
[menu.inspec]
title = "Configuration"
identifier = "inspec/reference/config.md Configuration"
parent = "inspec/reference"
weight = 60
title = "Configure"
identifier = "inspec/config.md Configuration"
parent = "inspec"
weight = 30
+++
This documents the Chef InSpec configuration file format introduced in version 3.5 of InSpec and extended in later versions.
This documents how to create a configuration file for Chef InSpec. A config file is **optional**.
There are two config file versions, 1.1 and 1.2.
## Config File Location
By default, Chef InSpec looks for a config file in `~/.inspec/config.json`. Chef InSpec does not need a configuration file to run.
By default, Chef InSpec looks for a config file in `~/.inspec/config.json`.
You may also specify the location using `--config`. For example, to run the shell using a config file in `/etc/inspec`, use `inspec shell --config /etc/inspec/config.json`.
## Config File Format Versions
## Versions
Config files must contain a top-level key, `version`, which indicates the file format. This allows us to add new fields without breaking old installations.
There are two possible versions for this config file, `1.1` or `1.2`. Only version `1.2` accepts the `plugins` setting.
## Version 1.1
## Example
### Complete Example
```
```json
{
"version": "1.1",
"version": "1.2",
"cli_options":{
"color": "true"
},
"credentials": {
"ssh": {
"my-target": {
"host":"somewhere.there.com",
"host":"somewhere.example.com",
"user":"bob"
}
}
@ -44,81 +44,81 @@ Config files must contain a top-level key, `version`, which indicates the file f
"reporter": {
"automate" : {
"stdout" : false,
"url" : "https://YOUR_A2_URL/data-collector/v0/",
"token" : "YOUR_A2_API_TOKEN",
"url" : "https://AUTOMATE_URL/data-collector/v0/",
"token" : "AUTOMATE_API_TOKEN",
"insecure" : true,
"node_name" : "inspec_test_node",
"environment" : "prod"
}
}
},
"plugins": {
"inspec-training-wheels":{
"diameter":"4 inches"
},
"inspec-input-secrets":{
"security-tokens":[
"123456789",
"abcdef252875"
]
}
}
}
```
version
: Should have the value '1.1'.
### Properties
cli_options
`version`
: **required**
The file format version.
Allowed values: `1.1` or `1.2`
`cli_options`
: Any long-form command line option, without the leading dashes.
credentials
`credentials`
: Train-transport-specific options. Store the options keyed first by transport name, then by a name you'll use later on. The combination of transport name and your chosen name can be used in the `--target` option to `inspec exec`, as `--target transport-name://connection-name`.
For example, if the config file contains:
For example, if the config file contains:
```
{
"credentials": {
"winrm": {
"myconn": {
"user": "Administrator",
"host": "prod01.east.example.com",
"disable_sspi": true,
"connection_retries": 10
```json
{
"credentials": {
"winrm": {
"myconn": {
"user": "Administrator",
"host": "prod01.east.example.com",
"disable_sspi": true,
"connection_retries": 10
}
}
}
}
}
```
```
Then use `-t winrm://myconn` to connect to the host, with the given extra options.
Then use `-t winrm://myconn` to connect to the host, with the given extra options.
Each Train transport offers a variety of options. By using the credential set facility, you are able to easily set options that are not accessible via the Train URI.
Each Train transport offers a variety of options. By using the credential set facility, you are able to set options that are not accessible via the Train URI.
You may have as many credential sets in the config file as you require.
You may have as many credential sets in the config file as you require.
If you use a target URI and the portion after the `://` cannot be matched to credential set name, Chef InSpec will send the URI to Train to be parsed as a Train URI. Thus, you can still do `ssh://someuser@myhost.com`.
If you use a target URI and the portion after the `://` cannot be matched to credential set name, Chef InSpec will send the URI to Train to be parsed as a Train URI. Thus, you can still do `ssh://someuser@example.com`.
You can use a credential set, and then override individual options using command line options.
You can use a credential set, and then override individual options using command line options.
Credential sets are intended to work hand-in-hand with the underlying credentials storage facility of the transport. For example, if you have a `~/.ssh/config` file specifying that the sally-key.pem file should be used with the host `somehost.com`, and you have a credential set that specifies that host, then when Train tries to connect to that host, the SSH library will automatically use the SSH config file to use the indicated key.
Credential sets are intended to work hand-in-hand with the underlying credentials storage facility of the transport. For example, if you have a `~/.ssh/config` file specifying that the sally-key.pem file should be used with the host `example.com`, and you have a credential set that specifies that host, then when Train tries to connect to that host, the SSH library will automatically use the SSH config file to use the indicated key.
### reporter
`reporter`
: Formats and delivers the results of a Chef InSpec audit run. For information on configuring reporters, see the [InSpec reporters documentation](/inspec/reporters/).
You may also set output (reporter) options in the config file. See the [Reporters Page](/inspec/reporters/) for details.
`plugins`
## Version 1.2
: Provide configuration settings to plugins that you use with Chef InSpec.
Refer to the documentation of the plugin you are using for details regarding what settings are available.
Version 1.2 adds a top-level field, "plugins".
Each plugin will have a key-value are that it may use as it sees fit - Chef InSpec does not specify the structure.
### plugins
Set the config file to **version 1.2** to use this setting.
Use the `plugins` top-level configuration field to provide configuration settings to plugins that you use with Chef InSpec. Refer to the documentation of the plugin you are using for details regarding what settings are available.
To use this new feature, add a new top-level key in your config file named `plugins`. Then create a sub-key named for each plugin you wish to configure. Each plugin will have a key-value are that it may use as it sees fit - Chef InSpec does not specify the structure. Here is an example, using contrived plugins:
```
{
"version":"1.2",
"plugins": {
"inspec-training-wheels": {
"diameter": "4 inches"
},
"inspec-input-secrets": {
"security-tokens: [
"123456789".
"abcdef252875"
]
}
}
}
```
For more information on plugins, see the [Chef InSpec plugins documentation](/inspec/plugins/).

View file

@ -1,505 +1,4 @@
+++
title = "Chef InSpec Language"
draft = false
gh_repo = "inspec"
[menu]
[menu.inspec]
title = "Chef InSpec Language"
identifier = "inspec/reference/dsl_inspec.md Chef InSpec Language"
parent = "inspec/reference"
weight = 70
layout = "redirect"
redirect_url = "/inspec/profiles/controls"
+++
Chef InSpec is a run-time framework and rule language used to specify compliance, security, and policy requirements.
It includes a collection of resources that help you write auditing controls quickly and easily.
The syntax used by both open source and [Chef compliance](https://www.chef.io/products/chef-compliance) auditing is the same.
The open source [Chef InSpec resource](/inspec/resources/) framework is compatible with [Chef compliance](https://docs.chef.io/chef_compliance_phase/).
The Chef InSpec Language is a Ruby DSL for writing audit controls, which includes audit resources that you can invoke.
The following sections describe the syntax and show some simple examples of using the Chef InSpec resources.
## Syntax
The following resource tests |ssh| server configuration. For example, a simple control may described as:
```ruby
describe sshd_config do
its('Port') { should cmp 22 }
end
```
In various use cases like implementing IT compliance across different departments, it becomes handy to extend the control with metadata. Each control may define an additional ``impact``, ``title`` or ``desc``. An example looks like:
```ruby
control 'sshd-8' do
impact 0.6
title 'Server: Configure the service port'
desc 'Always specify which port the SSH server should listen.'
desc 'rationale', 'This ensures that there are no unexpected settings' # Requires Chef InSpec >=2.3.4
tag 'ssh','sshd','openssh-server'
tag cce: 'CCE-27072-8'
ref 'NSA-RH6-STIG - Section 3.5.2.1', url: 'https://www.nsa.gov/ia/_files/os/redhat/rhel5-guide-i731.pdf'
describe sshd_config do
its('Port') { should cmp 22 }
end
end
```
where
* `'sshd-8'` is the name of the control
* `impact`, `title`, and `desc` define metadata that fully describes the importance of the control, its purpose, with a succinct and complete description
* `desc` when given only one argument it sets the default description. As of Chef InSpec 2.3.4, when given 2 arguments (see: `'rationale'`) it will use the first argument as a header when rendering in Automate
* `impact` is a string, or numeric that measures the importance of the compliance results.
Valid strings for impact are `none`, `low`, `medium`, `high`, and `critical`. The values are based off CVSS 3.0.
A numeric value must be between `0.0` and `1.0`. The value ranges are:
* `0.0 to <0.01` these are controls with no impact, they only provide information
* `0.01 to <0.4` these are controls with low impact
* `0.4 to <0.7` these are controls with medium impact
* `0.7 to <0.9` these are controls with high impact
* `0.9 to 1.0` these are critical controls
* `tag` is optional meta-information with key or key-value pairs
* `ref` is a reference to an external document
* `describe` is a block that contains at least one test. A `control` block must contain at least one `describe` block, but may contain as many as required
* `sshd_config` is a Chef InSpec resource. For the full list of Chef InSpec resources, see Chef InSpec resource documentation
* `its('Port')` is the matcher; `{ should eq '22' }` is the test. A `describe` block must contain at least one matcher, but may contain as many as required
## Advanced concepts
### Checking if at least one condition passes with `describe.one`
With Chef InSpec, you can check if at least one of a collection of checks is true.
For example, if you configure a setting in two different locations, then you may want to test if either configuration A or configuration B is set.
Do this task with the `describe.one` block.
`describe.one` defines a set of `describe` blocks where only one block needs to pass.
```ruby
describe.one do
describe ConfigurationA do
its('setting_1') { should eq true }
end
describe ConfigurationB do
its('setting_2') { should eq true }
end
end
```
#### `describe.one` usage notes
* A `describe.one` block passes if one of its nested `describe` blocks has all assertions passing. A `describe.one` block needs an entire `describe` block to pass and not just a single assertion.
* Chef InSpec will always evaluate all the tests contained within `describe.one`. It does not short-circuit upon evaluating a passing `describe` block.
* Nesting a `describe.one` block inside another `describe.one` block is not supported.
### Sensitive resources
In some scenarios, you may be writing checks that involve resources with sensitive content, such as a file resource.
In case of failures, you may desire to suppress output.
Do this task by adding the `:sensitive` flag to the resource definition:
```ruby
describe file('/tmp/mysecretfile'), :sensitive do
its('content') { should match /secret_info/ }
end
```
## Examples
The following examples show simple compliance tests using a single `control` block.
### Test System Event Log
The following test shows how to audit machines running Windows 2012 R2 that password complexity is enabled:
```ruby
control 'windows-account-102' do
impact 'critical'
title 'Windows Password Complexity is Enabled'
desc 'Password must meet complexity requirement'
describe security_policy do
its('PasswordComplexity') { should cmp 1 }
end
end
```
### Test if PostgreSQL passwords are empty
The following test shows how to audit machines running PostgreSQL to ensure that passwords are not empty.
```ruby
control 'postgres-7' do
impact 1.0
title "Don't allow empty passwords"
describe postgres_session('user', 'pass').query("SELECT * FROM pg_shadow WHERE passwd IS NULL;") do
its('output') { should cmp '' }
end
end
```
### Test if MySQL passwords are in ENV
The following test shows how to audit machines running MySQL to ensure that passwords are not stored in `ENV`:
```ruby
control 'mysql-3' do
impact 1.0
title 'Do not store your MySQL password in your ENV'
desc '
Storing credentials in your ENV may easily expose
them to an attacker. Prevent this at all costs.
'
describe command('env') do
its('stdout') { should_not match /^MYSQL_PWD=/ }
end
end
```
### Test if `/etc/ssh` is a Directory
The following test shows how to audit machines to ensure that `/etc/ssh` is a directory:
```ruby
control 'basic-1' do
impact 1.0
title '/etc/ssh should be a directory'
desc '
In order for OpenSSH to function correctly, its
configuration path must be a folder.
'
describe file('/etc/ssh') do
it { should be_directory }
end
end
```
### Test if Apache running
The following test shows how to audit machines to ensure that Apache is enabled and running:
```ruby
control 'apache-1' do
impact 'medium'
title 'Apache2 should be configured and running'
describe service(apache.service) do
it { should be_enabled }
it { should be_running }
end
end
```
### Test if insecure packages are installed
The following test shows how to audit machines for insecure packages:
```ruby
control 'cis-os-services-5.1.3' do
impact 0.7
title '5.1.3 Ensure rsh client is not installed'
describe package('rsh') do
it { should_not be_installed }
end
describe package('rsh-redone-client') do
it { should_not be_installed }
end
end
```
### Test Windows Registry Keys
The following test shows how to audit machines to ensure Safe DLL Search Mode is enabled:
```ruby
control 'windows-base-101' do
impact 1.0
title 'Safe DLL Search Mode is Enabled'
desc '
@link: https://msdn.microsoft.com/en-us/library/ms682586(v=vs.85).aspx
'
describe registry_key('HKLM\\System\\CurrentControlSet\\Control\\Session Manager') do
it { should exist }
it { should_not have_property_value('SafeDllSearchMode', :type_dword, '0') }
end
end
```
### Use `only_if` to exclude a specific control
This example shows how to allow skipping certain controls if conditions are not
met by using `only_if`. In this example, the control will not be performed if
the `redis-cli` command does not exist. A optional message can say why it was skipped.
```ruby
control 'nutcracker-connect-redis-001' do
impact 'critical'
title 'Check if nutcracker can pass commands to redis'
desc 'execute redis-cli set key command, to check connectivity of the service'
only_if('redis is not installed.') do
command('redis-cli').exist?
end
describe command('redis-cli SET test_inspec "HELLO"') do
its('stdout') { should match /OK/ }
end
end
```
This example checks for if certain pip packages are installed, but only if '/root/.aws' exists:
```ruby
control 'pip-packages-installed' do
title 'Check if essential pips are installed'
only_if('aws-cli config not created.') do
directory('/root/.aws').exist?
end
%w(aws-mfa PyYAML awscli).each do |aws_pip_deps|
describe pip(aws_pip_deps) do
it { should be_installed }
end
end
end
```
Mixing this with other conditionals, such as checking existence of the files, can
help to test different test paths using Chef InSpec. With this way, you can skip
certain controls, which would 100% fail due to the way servers are prepared, but
you know that the same control suites are reused later in different circumstances
by different teams.
This example checks whether the Gnome Desktop is installed. If not installed, it resets the impact of the control to the new value which is passed as a hash with the impact key.
Here, it resets it to 0:
```ruby
control 'gnome-destkop-settings' do
impact 0.5
desc 'some good settings'
desc 'check', 'check the settings file for good things'
desc 'fix', 'set the good things in the file /etc/gnome/settings'
tag nist: 'CM-6'
only_if("The Gnome Desktop is not installed, this control is Not Applicable", impact: 0) {
package('gnome-desktop').installed?
}
describe gnome_settings do
it should_be set_well
end
end
```
Some notes about `only_if`:
* `only_if` applies to the entire `control`. If the results of the `only_if`
block evaluate to false, any Chef InSpec resources mentioned as part of a
`describe` block will not be run. Additionally, the contents of the describe
blocks will not be run. However, bare Ruby expressions and bare Chef InSpec
resources (not assocated with a describe block) preceding the only_if statement
will run
* `only_if` also accepts hash with impact key to reset the impact value of the control. Control's impact is helpful in determining it is enhanced outcome.
To illustrate:
```ruby
control "whatruns" do
command("do_something") # This will ALWAYS run
describe command("do_another_thing") do # This will not run
command("do_yet_another_thing") # This will not run
end
only_if { false }
command("do_something_else") # This will not run
end
```
* Only one `only_if` is permitted per `control` block. If multiple `only_if` blocks are present, only the last `only_if` block will be honored
* If used outside a control block, `only_if` skips all controls in the current file
* To implement complex logic, use Ruby 'or' (`||`) and 'and' (`&&`) inside your `only_if` block:
```ruby
only_if('ready for launch') do
rocket_is_ready && weather_is_clear
end
```
### Use **only_applicable_if** to test controls for applicability
The `only_applicable_if` block allows to test if a control is applicable or not. In this example, the control with `only_applicable_if` block checks the condition and marks the control as not applicable (N/A) if the results of the `only_applicable_if` block evaluates to `false`.
If **gnome-desktop** is not installed, the following control to test gnome settings marks control as **not applicable**.
```ruby
control 'gnome-destkop-settings' do
impact 0.5
desc 'some good settings'
desc 'check', 'check the settings file for good things'
desc 'fix', 'set the good things in the file /etc/gnome/settings'
tag nist: 'CM-6'
only_applicable_if("The Gnome Desktop is not installed, this control is Not Applicable") {
package('gnome-desktop').installed?
}
describe gnome_settings do
it should_be set_well
end
end
```
Run output:
```bash
inspec exec path/to/audit-gnome-settings-profile --enhanced-outcomes
Profile: InSpec Profile (audit-gnome-settings-profile)
Version: 0.1.0
Target: local://
Target ID: fa3923b9-f806-4cc2-960d-1ddefb4c7654
N/A gnome-destkop-settings: No-op
× No-op
N/A control due to only_applicable_if condition: The Gnome Desktop is not installed, this control is Not Applicable
Profile Summary: 0 successful controls, 0 control failure, 0 controls not reviewed, 1 controls not applicable, 0 controls have error
Test Summary: 0 successful, 1 failures, 0 skipped
```
Some notes about `only_applicable_if`:
* `only_applicable_if` applies to the entire `control`. If the results of the `only_applicable_if` block evaluates to `false`, any Chef InSpec resources mentioned as part of a `describe` block will not be run. Additionally, the contents of the describe blocks will not be run.
* If the results of the `only_applicable_if` block evaluates to `false`, it will invoke a failing test which will state the reason for N/A.
### Additional metadata for controls
The following example illustrates various ways to add tags and references to `control`
```ruby
control 'ssh-1' do
impact 1.0
title 'Allow only SSH Protocol 2'
desc '
Only SSH protocol version 2 connections should be permitted.
The default setting in /etc/ssh/sshd_config is correct, and can be
verified by ensuring that the following line appears: Protocol 2
'
tag 'production','development'
tag 'ssh','sshd','openssh-server'
tag cce: 'CCE-27072-8'
tag disa: 'RHEL-06-000227'
tag remediation: 'stig_rhel6/recipes/sshd-config.rb'
tag remediation: 'https://supermarket.chef.io/cookbooks/ssh-hardening'
ref 'NSA-RH6-STIG - Section 3.5.2.1', url: 'https://www.nsa.gov/ia/_files/os/redhat/rhel5-guide-i731.pdf'
ref 'http://people.redhat.com/swells/scap-security-guide/RHEL/6/output/ssg-centos6-guide-C2S.html'
describe ssh_config do
its('Protocol') { should cmp 2 }
end
end
```
## Using Ruby in InSpec
The Chef InSpec Language is a Ruby based language. This allows you to be flexible with
Ruby code in controls:
```ruby
json_obj = json('/file.json')
json_obj['keys'].each do |value|
..
end
```
Ruby allows a lot of freedoms, but should be limited in controls so that they
remain portable and easy to understand. Please see our [profile style guide](/inspec/style/).
Core and custom resources are written as regular Ruby classes which inherit from
`Inspec.resource`.
### Interactive Debugging with Pry
Here's a sample Chef InSpec control that uses Ruby variables to instantiate
a Chef InSpec resource once and use the content in multiple tests.
```ruby
control 'check-perl' do
impact 0.3
title 'Check perl compiled options and permissions'
perl_out = command('perl -V')
#require 'pry'; binding.pry;
describe perl_out do
its('exit_status') { should eq 0 }
its('stdout') { should match /USE_64_BIT_ALL/ }
its('stdout') { should match /useposix=true/ }
its('stdout') { should match /-fstack-protector/ }
end
# extract an array of include directories
perl_inc = perl_out.stdout.partition('@INC:').last.strip.split("\n")
# ensure include directories are only writable by 'owner'
perl_inc.each do |path|
describe directory(path.strip) do
it { should_not be_writable.by 'group' }
it { should_not be_writable.by 'other' }
end
end
end
```
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:
```ruby
[1] pry> perl_out.exit_status
=> 0
[2] pry> perl_out.stderr
=> ""
[3] pry> ls perl_out
Inspec::Plugins::Resource#methods: inspect
Inspec::Resources::Cmd#methods: command exist? exit_status result stderr stdout to_s
Inspec::Resource::Registry::Command#methods: inspec
instance variables: @__backend_runner__ @__resource_name__ @command @result
[4] pry> perl_out.stdout.partition('@INC:').last.strip.split("\n")
=> ["/Library/Perl/5.18/darwin-thread-multi-2level",
" /Library/Perl/5.18",
...REDACTED...
[5] pry> exit # or abort
```
You can use `pry` inside both the controls DSL and resources. Similarly,
for dev and test, you can use `inspec shell` which is based on `pry`,
for example:
```ruby
$ inspec shell
Welcome to the interactive InSpec Shell
To find out how to use it, type: help
inspec> command('ls ~/projects/github/inspec/docs').stdout
=> "README.md\nconfig.md\ndev\ndsl_inspec.md\ndsl_resource.md\nglossary.md\nhabitat.md\ninputs.md\ninspec_and_friends.md\nmatchers.md\nmigration.md\nplatforms.md\nplugin_kitchen_inspec.md\nplugins.md\nprofiles.md\nreporters.md\nresources\nshared\nshell.md\nstyle.md\nwaivers.md\n"
inspec> command('ls ~/projects/github/inspec/docs').stdout.split("\n").first
=> "README.md"
inspec> help command
Name: command
Description:
Use the command InSpec audit resource to test an arbitrary command that is run on the system.
Example:
describe command('ls -al /') do
it { should exist }
its('stdout') { should match /bin/ }
its('stderr') { should eq '' }
its('exit_status') { should eq 0 }
end
```

View file

@ -1,152 +1,4 @@
+++
title = "Resource DSL"
draft = false
gh_repo = "inspec"
[menu]
[menu.inspec]
title = "Custom Resources"
identifier = "inspec/reference/dsl_resource.md Custom Resources"
parent = "inspec/reference"
weight = 90
layout = "redirect"
redirect_url = "/inspec/profiles/custom_resources/"
+++
Chef InSpec provides a mechanism for defining custom resources. These become
available with their respective names and provide easy functionality to
profiles.
## Resource location
Resources may be added to profiles in the libraries folder:
```bash
$ tree examples/profile
examples/profile
...
├── libraries
│   └── example_config.rb
```
## Resource structure
The smallest possible resource takes this form:
```ruby
class Tiny < Inspec.resource(1)
name 'tiny'
end
```
Resources are written as a regular Ruby class which inherits from
Inspec.resource. The number (1) specifies the version this resource
plugin targets. As Chef InSpec evolves, this interface may change and may
require a higher version.
The following attributes can be configured:
- name - Identifier of the resource (required)
- desc - Description of the resource (optional)
- example - Example usage of the resource (optional)
- supports - (Chef InSpec 2.0+) Platform restrictions of the resource (optional)
The following methods are available to the resource:
- inspec - Contains a registry of all other resources to interact with the operating system or target in general.
- skip_resource - A resource may call this method to indicate that requirements aren't met. All tests that use this resource will be marked as skipped.
The additional methods may be defined within the resource:
- resource_id - An instance method. Place logic here to determine the unique identifier for a resource, and set it using the superclass method. Following is an example of its usage in an InSpec test:
```
# example_config resource can have unique conf file path as an identifier.
describe example_config do
its("resource_id") { should eq PATH_OF_CONF_FILE }
end
```
The following example shows a full resource using attributes and methods
to provide simple access to a configuration file:
```ruby
class ExampleConfig < Inspec.resource(1)
name 'example_config'
# Restrict to only run on the below platforms (if none were given, all OS's supported)
supports platform_family: 'fedora'
supports platform: 'centos', release: '6.9'
# Supports `*` for wildcard matcher in the release
supports platform: 'centos', release: '7.*'
desc '
Resource description ...
'
example '
describe example_config do
its("signal") { should eq "on" }
end
'
# Load the configuration file on initialization
def initialize(path = nil)
@path = path || '/etc/example.conf'
@params = SimpleConfig.new( read_content )
end
# Expose all parameters of the configuration file.
def method_missing(name)
@params[name]
end
def resource_id
value = example_method_to_determine_resource_id # define logic to determine resource_id value
super(value)
end
private
def read_content
f = inspec.file(@path)
# Test if the path exist and that it's a file
if f.file?
# Retrieve the file's contents
f.content
else
# If the file doesn't exist, skip all tests that use example_config
raise Inspec::Exceptions::ResourceSkipped, "Can't read config at #{@path}"
end
end
end
```
For a full example, see our [example resource](https://github.com/chef/inspec/blob/main/examples/profile/libraries/example_config.rb).
## Lazy Loading
Prior to InSpec v4.16, resources were pre-loaded for every invocation
of `inspec`. This was a heavy and unnecessary burden on the system and
exacerbated startup times (especially on Windows).
As of InSpec v4.16, resources are lazily loaded into the `inspec`
process upon use. This greatly speeds up the initial startup costs of
the `inspec` process and only loads what you need to use. For example, `inspec
--version` no longer runs for 10 seconds!.
### Overriding Core Resources
Lazy loading does change the way the resource registry is handled in
ways that might break some assumptions. Specifically,
`inspec.<resource>` isn't pre-populated with the core resources that
InSpec ships with. If you make a local/custom resource of the same
name, referring to the core resource via `inspec.<resource>` will not
resolve to the core resource.
As such, overriding core resources is not recommended best practice.
If you really do need to do this, it is easiest to make a local
resource with a new name and refer to the core resource directly.
Otherwise, you need to ensure that the core resource you want is
registered (via `require "inspec/resource/<name>"`) _before_ your
profile is run to ensure it is eagerly loaded and in the global
resource registry.

View file

@ -6,8 +6,8 @@ gh_repo = "inspec"
[menu]
[menu.inspec]
title = "Chef InSpec Glossary"
identifier = "inspec/glossary.md Chef InSpec Glossary"
parent = "inspec"
identifier = "inspec/reference/Chef InSpec Glossary"
parent = "inspec/reference"
weight = 50
+++
@ -172,7 +172,7 @@ end
When using a [plural resource](#plural-resource), a _`filter statement`_ is used to select individual test subjects using [filter criteria](#filter-criteria). A filter statement almost always is indicated by the keyword `where`, and may be repeated using method chaining.
A filter statement may use method call syntax (which allows basic criteria operations, such as equality, regex matching, and ruby `===` comparison) or block syntax (which allows arbitrary code).
A filter statement may use method call syntax (which allows basic criteria operations, such as equality, regex matching, and Ruby `===` comparison) or block syntax (which allows arbitrary code).
In this example, `where(...)` is the filter statement.

View file

@ -6,23 +6,22 @@ gh_repo = "inspec"
[menu]
[menu.inspec]
title = "Chef Habitat Integration"
identifier = "inspec/reference/habitat.md Habitat Integration"
parent = "inspec/reference"
weight = 120
identifier = "inspec/chef/Habitat Integration"
parent = "inspec/chef"
weight = 20
+++
Chef InSpec provides an easy method to create an executable Chef Habitat package for a Chef InSpec profile. When run via the Chef Habitat Supervisor, the package will run Chef InSpec with your profile and write out its findings to the supervisor log. This provides the ability to ship your compliance controls alongside your Chef Habitat-packaged application and continuously run InSpec, providing you *Continuous Compliance.*
## What is Chef Habitat
Chef Habitat by Chef Software is our new Application Automation tool that aims
Chef Habitat by Chef Software is our new application automation tool that aims
to make it easy, safe, and fast to build, deploy, and manage applications. From
build dependencies, runtime dependencies, dynamic configuration, and service
discovery (just to name a few), Chef Habitat packages the automation with the
application instead of relying on an underlying platform.
To learn more about Chef Habitat and try our demos and tutorials, visit
[https://www.habitat.sh](https://www.habitat.sh).
To learn more about Chef Habitat see the [Habitat documentation](/habitat/).
## Using the Chef Habitat Integration

View file

@ -1,450 +1,5 @@
+++
title = "Chef InSpec Inputs"
layout="redirect"
draft = false
gh_repo = "inspec"
[menu]
[menu.inspec]
title = "Inputs"
identifier = "inspec/reference/inputs.md Inputs"
parent = "inspec/reference"
weight = 30
+++
## What are Inputs?
Inputs are the "knobs" you can use to customize the behavior of Chef InSpec profiles.
If a profile supports inputs, you can set the inputs in a variety of ways, allowing
flexibility. Profiles that include other profiles can set inputs in the included
profile, enabling a multi-layered approach to configuring profiles.
### A Simple Example
Suppose you have a profile named `rock_critic`. In its profile metadata file (inspec.yml):
```yaml
# Optionally declare inputs in the profile metadata
# This lets you set up things like type checking, etc.
inputs:
- name: amplifier_max_volume
description: How loud the amplifiers can go
type: numeric
# More options, including value: and priority: are possible here
```
In the profile's control code:
```ruby
# Set a default value for an input. This is optional.
input('amplifier_max_volume', value: 10)
control 'Big Rock Show' do
describe input('amplifier_max_volume') do # This line reads the value of the input
it { should cmp 11 } # The UK'S LOUDEST BAND
end
end
```
When the above profile is executed by using `inspec exec rock_critic`, you would see something like:
```bash
× Big Rock Show: 10
× 10 is expected to cmp == 11
expected: 11
got: 10
(compared using `cmp` matcher)
Profile Summary: 0 successful controls, 1 control failure, 0 controls skipped
```
That result clearly won't do. Let's override the input's default value.
We can now run that profile with `inspec exec rock_critic --input amplifier_max_volume=11`:
```bash
✔ Big Rock Show: 11
✔ 11 is expected to cmp == 11
Profile Summary: 1 successful control, 0 control failures, 0 controls skipped
```
### Which profiles support inputs?
The best way for a profile to indicate it supports inputs is to list them in the
metadata file, `inspec.yml`. Any profile that has an `inputs` (or the deprecated
`attributes`) section in its `inspec.yml` metadata file is
[configuring](#configuring-inputs-in-profile-metadata) inputs.
That said, any profile that uses the DSL keyword `input()` (or the deprecated
`attribute()`) in the control source code supports inputs. These profiles are
*reading* (and possibly setting) input values and using them to make decisions.
### How can I set Inputs?
As installed (without specialized plugins), Chef InSpec supports several ways of setting inputs:
- Inline in control code, using `input('input_name', value: 42)`.
- In profile `inspec.yml` metadata files
- Using the CLI option `--input name1=value1 name2=value2...` to read directly from the command line
- Using the CLI option `--input-file somefile.yaml` to read inputs from files
- In kitchen-inspec, using the `verifier/inputs` settings
In addition, Chef InSpec supports Input Plugins, which can provide optional integrations to specific key-value stores.
### How does Input precedence work?
#### Simple Precedence
Briefly:
inline DSL < metadata < ( cli-input-file or kitchen-inspec ) < cli --input
In addition, for inherited profiles:
dependent profile metadata < wrapper profile metadata
This precedence lets you override input values on the command line, as well as
override child profile inline values from the parent profile.
This description matches the general behavior of InSpec v3, while also making
some edge cases easier to reason.
#### The Details of Input Precedence
Whenever an input provider sets a value on an input, a *priority value* is
assigned to the operation. Over the life of the input, multiple assignments with
varying priority values may occur. When the input is evaluated, the current value
is determined by finding the setting event with the highest priority.
Note that this approach does not rely on execution order, nor does it rely on
multiple named precedence levels. Each setting operation is preserved and this
allows the user to [debug](#debugging-inputs-with-the-event-log) the history of
the input values.
Some input providers allow you to set a priority when you set the value. For
example, to set a priority of 50 in a metadata file, use:
```yaml
inputs:
- name: very_important_input
value: 12
priority: 50
```
To set a priority in DSL, use:
```ruby
input('also_important', value: 42, priority: 45)
```
As packaged, Chef InSpec uses the following priority values:
| Input Provider | Priority | May change priority |
| -------------------------------------- | -------- | ------------------- |
| Inline DSL | 20 | Yes |
| Metadata | 30 | Yes |
| Metadata in a wrapper cookbook | 35 | Yes |
| CLI `--input-file` option | 40 | No |
| inspec-kitchen `inputs:` section | 40 | No |
| CLI `--input` option | 50 | No |
### What happened to "Attributes"?
When originally introduced, the Input facility was named *Attributes*. This name
was problematic, because:
- The Chef Infra tool uses the same word to describe its parameterization system.
- Chef Infra attributes have a completely different and much more complex precedence system.
- This caused confusion about passing Chef Infra attributes into InSpec when using Audit Cookbook and kitchen-inspec.
Based on these concerns, InSpec attributes have been renamed to InSpec inputs in Chef InSpec v4.
Support for using the DSL keyword `attribute()`, the metadata field `attributes:`, and the corresponding kitchen-inspec and audit cookbook values are anticipated to continue through Chef InSpec v5.
## Working with Inputs in Control Code
### Input Scope
Inputs are available throughout the InSpec profile DSL. You can use them anywhere.
```ruby
# some_controls.rb
input('outer_input', value: 1) # here
control 'control-1' do
input('control_dsl_input', value: 2) # here too
describe some_resource do
input('test_dsl_input', value: 3) # even here
it { should cmp input('expectation_dsl_input') } # and yes here too
end
end
```
### Setting Inputs in Control DSL
When you write `input('some_name', value: 'some_value')`, you are *setting* an
input value in the DSL. Because the `value:` option is present, a new value will
be set. You may also pass any other option listed in the
[input option reference](#input-options-reference).
### Reading Inputs in Control DSL
When you call `input('some_name')`, with or without additional options, the value
of the input will be resolved and returned. Note that this process may involve
sourcing the value from another provider, using the value set in DSL, or overriding
the value provided in the same call.
```ruby
# You can use the value in a Ruby variable
some_var = input('some_input_name')
# Or more directly in a resource parameter
describe file(input('important_path')) do
it { should exist }
end
# Or as the resource itself (this could be a string, here)
describe input('some_setting') do
it { should cmp 'correct_value' }
end
# Or as the expected value
describe file('/etc/httpd/httpd.conf') do
its('owner') { should_not cmp input('webserver_user') }
end
```
The value returned can be used anywhere a Ruby value is used.
## Configuring Inputs in Profile Metadata
Each Chef InSpec profile has a metadata file at the top level named `inspec.yml`.
In that file, you may add a section for inputs. You may define inputs there,
clearly setting options including values, type checking, and whether the input is
required.
```yaml
name: my_profile
inputs:
- name: webserver_user # Name is the only required field
- name: favorite_fruit
value: banana # You can set a value; priority is 30 for metadata
- name: meaning_of_life
type: Numeric
value: 42
required: true
priority: 70
sensitive: true
```
All [input options](#input-options-reference) are supported in metadata files.
There are two major advantages to defining inputs in profile metadata:
1. The inputs and their configuration are listed explicitly in simple YAML in
one place - a consumer of your profile does not need to read through the control
code to find the inputs.
1. You can set inputs in other profiles that you depend on using profile inheritance.
### Using inputs with Profile inheritance
When your profile relies on another profile using the `depends` key in the metadata file, you can set — that is, override — the value of the input in the dependent profile by including the `profile` option and naming the dependent profile.
```yaml
# child inspec.yml
name: child
inputs:
- name: favorite_food
value: pizza
```
```yaml
# wrapper inspec.yml
name: wrapper
depends:
- name: child
path: ../child
inputs:
- name: favorite_food
value: broccoli
profile: child # <----- REQUIRED to override the value in InSpec 4
```
In Chef InSpec 4+, every input is namespaced. For example, you could have an
input named `wrapper/favorite_food` and one named `child/favorite_food`. If no
explicit profile option is set within the `wrapper` profile metadata file, then
`wrapper` is assumed to be the profile.
## Setting Input values using `--input-file`
You may also provide inputs and values via YAML files on the command line. The
format can be seen below:
```yaml
an_input: a_value
another_input: another_value
```
CLI-input-file-set inputs have a priority of 40.
As of Chef InSpec 4.3.2, this mechanism has the following limitations:
1. No [input options](#input-options-reference) may be set - only the name and value.
1. Because the CLI is outside the scope of any individual profile and the inputs
don't take options, the inputs are clumsily copied into every profile,
effectively making the CLI mechanism global.
## Setting Input values using `--input`
You may also provide inputs and values directly on the command line:
```yaml
inspec exec my_profile --input input_name=input_value
```
To set multiple inputs, say:
```yaml
inspec exec my_profile --input input_name1=input_value1 name2=value2
```
If a CLI input value resembles a number, it will be converted to an Integer or
Float. Scientific notation is not currently recognized.
```yaml
inspec exec my_profile --input amplifier_volume=-11
inspec exec my_profile --input water_depth=11.5
```
You may set inputs with complex values, such as arrays and hashes using either
YAML or JSON syntax. Just be sure to protect the string from the shell using single
quotes.
```yaml
inspec exec my_profile --input alphabet='[a,b,c]'
inspec exec my_profile --input fruits='{a: apples, b: bananas, c: cantelopes}'
inspec exec my_profile --input json_fruit='{"a": "apples", "g": ["grape01", "grape02"] }'
```
Do not repeat the `--input` flag; that will override the previous setting.
CLI-set inputs have a priority of 50.
As of Chef InSpec 4.12, this mechanism has the following limitations:
1. No [input options](#input-options-reference) may be set - only the name and
value.
1. Because the CLI is outside the scope of any individual profile and the inputs
don't take options, the inputs are clumsily copied into every profile,
effectively making the CLI mechanism global.
## Setting Input values using Plugins
Inputs can also be set by custom input plugins, which retrieve values from external sources like secret stores or databases. Please check [RubyGems.org](https://rubygems.org/) for available InSpec input plugins.
### Disabling Caching for Inputs
Especially with plugins, it can be desirable to re-evaluate inputs every time and not cache them. By default, an existing input value is reused which can lead to problems if the retrieved values are expected to change. An example for this is using `kitchen-inspec` with input plugins to connect to a Vault server for password retrieval.
To disable input caching, you can disable the cache from your Ruby code:
```ruby
Inspec::InputRegistry.instance.cache_inputs = false
```
## Input Options Reference
### Name
Required `String`. This option identifies the input.
Allowed in: All. When used in DSL and Metadata, the name is unique within the
current profile. When used in CLI input files, and kitchen-inspec,
the input is copied across all profiles using the same name.
### Description
Optional `String`. Human-meaningful explanation of the input.
Allowed in: DSL, Metadata
### Value
Optional, any Ruby or YAML type. This is the value that will be available when
you read the input. See the [Reading Inputs](#reading-inputs-in-control-dsl) section
for more information.
Allowed in: All
### Type
Optional, `String`. This value must be one of `String`, `Numeric`, `Regexp`,
`Array`, `Hash`, `Boolean`, or `Any`. If provided, the value of the input will
be checked to see if it is of the corresponding type. Note that `Regexp` indicates
that the input value itself should be a regular expression, not that it should
match any particular regular expression.
Allowed in: DSL, Metadata
### Required
Optional, `true` or `false`. If `true`, a control using the input will be failed
if it [reads](#reading-inputs-in-control-dsl) the value when none has been set.
Allowed in: DSL, Metadata
### Priority
Optional, `Integer`, 0-100. Higher values make this assignment have higher
precedence. This is an advanced feature.
Allowed in: DSL, Metadata
### Profile
Optional, `String`. Allows you to set an input in another profile from your profile.
Allowed in: DSL, Metadata
### Sensitive
Optional, `true` or `false`. If `true`, the value of the input will be used normally
during the `exec` run, but the value will be obscured as "***" in the "inputs" or
"attributes" section of any [Reporter](/inspec/reporters/) that explicitly lists
inputs (the `json` reporter is one such reporter). Note that this will not obscure
input values that are used as test results.
Allowed in: Metadata
### Pattern
Optional, `Regexp`. This feature validates the input by matching it with the provided regular expression.
Allowed in: DSL, Metadata
## Advanced Topics
### Debugging Inputs with the Event Log
If it is difficult to determine why a particular value is being used, you can use
the Event Log to determine what is happening.
First, use the `input_object()` DSL method. This method is like `input()` in that
it looks up an input, but instead of evaluating the current value, it returns
the underlying `Inspec::Input` object.
```ruby
puts input_object('troublesome_input').diagnostic_string
# Or
require 'pp'
pp input_object('troublesome_input').events
```
`diagnostic_string` assembles the Event Log into a printable log message for
convenience.
The Event Log contains entries for every time that the value changed, as well as
one for when the input was first created. When possible, stack probing is used
to determine file and line numbers. Most importantly, you will see priority numbers;
remember that highest priority wins; order only matters to break a tie.
redirect_url="/inspec/profiles/inputs/"
+++

View file

@ -5,10 +5,10 @@ gh_repo = "inspec"
[menu]
[menu.inspec]
title = "Chef InSpec and Friends"
identifier = "inspec/inspec_and_friends.md Chef InSpec and friends"
parent = "inspec"
weight = 40
title = "RSpec and Serverspec"
identifier = "inspec/friends/inspec_and_friends.md Chef InSpec and friends"
parent = "inspec/friends"
weight = 10
+++
This page looks at projects that are similar to Chef InSpec to explain how they

View file

@ -74,7 +74,7 @@ Replace `<value>` with one of the following options.
## License key
Set a license key for Chef InSpec using one of three methods.
You can add a license key to Chef InSpec using one of three methods:
- [interactive license dialog](#interactive-license-dialog)
- [command line option](#command-line-option-1)

View file

@ -22,8 +22,6 @@ Chef InSpec uses **matchers**, a testing framework based on [RSpec](https://rspe
You can use any matcher provided by [RSpec::Expectations](https://relishapp.com/rspec/rspec-expectations/docs); however, these matchers are not [supported by InSpec](/inspec/inspec_and_friends/#rspec).
See [Test Expectations with Chef InSpec](https://learn.chef.io/courses/course-v1:chef+Inspec101+Perpetual/about) on Learn Chef to learn more about Chef InSpec's built-in matchers.
## be
Use the `be` matcher with comparison operators, and use numbers and not strings for these comparisons. For example:

View file

@ -1,14 +1,14 @@
+++
title = "Chef InSpec Migration Guide"
title = "Serverspec Migration Guide"
draft = false
gh_repo = "inspec"
[menu]
[menu.inspec]
title = "Migration from Serverspec"
identifier = "inspec/reference/migration.md Migration from Serverspec"
parent = "inspec/reference"
weight = 130
identifier = "inspec/friends/migration.md Migration from Serverspec"
parent = "inspec/friends"
weight = 20
+++
## How is Chef InSpec different from Serverspec
@ -21,7 +21,7 @@ Chef InSpec is a framework that allows you to run infrastructure testing as well
## Which Serverspec resources are available in InSpec?
The following resources are available in InSpec:
The following resources are available in Chef InSpec:
| Serverspec | Chef InSpec |
|:------------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------:|

View file

@ -1,14 +1,14 @@
+++
title = "InSpec Parallel"
title = "Chef InSpec Parallel"
draft = false
gh_repo = "inspec"
[menu]
[menu.inspec]
title = "InSpec Parallel"
title = "Parallel"
identifier = "inspec/parallel.md InSpec Parallel"
parent = "inspec"
weight = 25
weight = 80
+++
Chef InSpec Parallel can automatically manage multiple profile executions in parallel on a system targeting several remote systems and environments.

View file

@ -6,23 +6,25 @@ gh_repo = "inspec"
[menu]
[menu.inspec]
title = "kitchen-inspec"
identifier = "inspec/reference/plugin_kitchen_inspec.md kitchen-inspec"
parent = "inspec/reference"
weight = 110
identifier = "inspec/chef/kitchen-inspec"
parent = "inspec/chef"
weight = 10
+++
Use Chef InSpec as a Kitchen verifier with `kitchen-inspec`.
Use Chef InSpec as a [Test Kitchen](https://kitchen.ci/) verifier with `kitchen-inspec`.
For hands-on examples, learn how to use Test Kitchen to run Chef InSpec profiles on the Learn Chef course [Validate Infrastructure Code with Test Kitchen](https://learn.chef.io/courses/course-v1:chef+LocalDev101+Perpetual/about).
Add the Chef InSpec verifier to the `.kitchen.yml` file:
```YML
```yaml
verifier:
name: inspec
```
Use a compliance profile from the Chef Compliance server:
```YML
```yaml
suites:
- name: compliance
run_list:
@ -38,7 +40,9 @@ and then run the following command:
inspec automate login https://compliance.test --user admin --insecure --token ''
```
where `--insecure` is required when using self-signed certificates.
where:
- `--insecure` is required when using self-signed certificates.
`inspec compliance` is a backwards compatible alias for `inspec automate` and works the same way:
@ -48,7 +52,7 @@ inspec compliance login https://compliance.test --user admin --insecure --token
Use a compliance profile from the Chef Supermarket:
```YML
```yaml
suites:
- name: supermarket
run_list:
@ -60,7 +64,7 @@ suites:
Use Chef InSpec tests from the local file system:
```YML
```yaml
suites:
- name: local
run_list:
@ -69,7 +73,3 @@ suites:
inspec_tests:
- test/integration/default
```
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 Chef
InSpec profiles.

View file

@ -6,27 +6,25 @@ gh_repo = "inspec"
[menu]
[menu.inspec]
title = "Plugins"
identifier = "inspec/reference/plugins.md Plugins"
parent = "inspec/reference"
weight = 100
identifier = "inspec/Plugins"
parent = "inspec"
weight = 90
+++
## What are Chef InSpec Plugins?
## What are Chef InSpec plugins?
Chef InSpec Plugins are optional software components that extend the capabilities
of InSpec. For example, [`inspec-iggy`](https://github.com/inspec/inspec-iggy)
is a Plugin project that aims to generate Chef InSpec controls from
infrastructure-as-code files. Plugins are distributed as RubyGems, and Chef InSpec
manages their installation. Chef InSpec Plugins always begin with the prefix
'inspec-'.
Chef InSpec plugins are optional software components that extend the capabilities of InSpec.
For example, [`inspec-iggy`](https://github.com/inspec/inspec-iggy) is a plugin project that aims to generate Chef InSpec controls from infrastructure-as-code files.
Plugins are distributed as RubyGems, and Chef InSpec manages their installation.
Chef InSpec plugins always begin with the prefix 'inspec-'.
## What are Train Plugins?
## What are Train plugins?
Train Plugins allow Chef InSpec to speak to new kinds of targets (typically new
Train plugins allow Chef InSpec to speak to new kinds of targets (typically new
remote targets or APIs, but you could treat the local system in a new way if you
wished to). For example, if you wanted to audit a Kubernetes cluster, you might
want a transport that can talk to the supervisor API. You would develop a Train
Plugin for that, and install it using the Chef InSpec command line. Train Plugins
plugin for that, and install it using the Chef InSpec command line. Train plugins
always begin with the prefix 'train-'.
## What can plugins do?
@ -40,7 +38,7 @@ Currently, each plugin can offer one or more of these capabilities:
- DSL extensions at the file, control, describe block, or test level
- DSL extensions for custom resources
## How do I find out which plugins are available?
## Find available plugins
The Chef InSpec CLI can tell you which plugins are available:
@ -48,7 +46,7 @@ The Chef InSpec CLI can tell you which plugins are available:
inspec plugin search inspec-
```
## How do I install and manage plugins?
## Install and manage plugins
The Chef InSpec command line now offers a new subcommand just for managing plugins.
@ -61,24 +59,20 @@ inspec plugin install train-some-plugin
For more details on what the `plugin` command can do, run `inspec plugin help`.
## How do I use a different Gem server?
## Use a different Gem server
You can specify an alternate source by passing the base of your Gem repository to
the `--source` parameter:
```bash
inspec plugin search --source https://my.private.server inspec-private
inspec plugin install --source https://my.private.server inspec-private-plugin
inspec plugin search --source https://private.example.com inspec-private
inspec plugin install --source https:/private.example.com inspec-private-plugin
```
## How do I write a plugin?
## Write a plugin
### Chef InSpec Plugins
For details on creating a Chef InSpec plugin, see the
[InSpec developer documentation](https://github.com/inspec/inspec/blob/main/dev-docs/plugins.md)
For details on how to author a Chef InSpec Plugin, see the
[developer documentation](https://github.com/inspec/inspec/blob/main/dev-docs/plugins.md)
### Train Plugins
For details on how to author a Train Plugin, see the
[developer documentation](https://github.com/inspec/train/blob/main/docs/plugins.md)
For details on creating a Train plugin, see the
[Train developer documentation](https://github.com/inspec/train/blob/main/docs/plugins.md)

View file

@ -1,565 +0,0 @@
+++
title = "About Chef InSpec Profiles"
draft = false
gh_repo = "inspec"
[menu]
[menu.inspec]
title = "Profiles"
identifier = "inspec/reference/profiles.md Profiles"
parent = "inspec/reference"
weight = 20
+++
Chef InSpec supports the creation of complex test and compliance profiles, which
organize controls to support dependency management and code reuse. Each profile
is a standalone structure with its own distribution and execution flow.
## Profile Structure
A profile should have the following structure:
```yaml
examples/profile
├── README.md
├── controls
│ ├── example.rb
│ └── control_etc.rb
├── libraries
│ └── extension.rb
|── files
│ └── extras.conf
└── inspec.yml
```
where:
- `inspec.yml` includes the profile description (required)
- `controls` is the directory in which all tests are located (required)
- `libraries` is the directory in which all Chef InSpec resource extensions are located (optional)
- `files` is the directory with additional files that a profile can access (optional)
- `README.md` should be used to explain the profile, its scope, and usage
See a complete example profile in the Chef InSpec open source repository:
[Example Chef InSpec Profile](https://github.com/chef/inspec/tree/main/examples/profile)
Also check out [Explore Chef InSpec resources](https://learn.chef.io/modules/explore-inspec-resources#/)
on Learn Chef Rally to learn more about how profiles are structured with hands-on-examples.
## inspec.yml
Each profile must have an `inspec.yml` file that defines the following information:
- Use `name` to specify a unique name for the profile. Required.
- Use `title` to specify a human-readable name for the profile.
- Use `maintainer` to specify the profile maintainer.
- Use `copyright` to specify the copyright holder.
- Use `copyright_email` to specify support contact information for the profile, typically an email address.
- Use `license` to specify the license for the profile.
- Use `summary` to specify a one line summary for the profile.
- Use `description` to specify a multiple line description of the profile.
- Use `version` to specify the profile version.
- Use `inspec_version` to place SemVer constraints on the version of Chef InSpec that the profile can run under.
- Use `supports` to specify a list of supported platform targets.
- Use `depends` to define a list of profiles on which this profile depends.
- Use `inputs` to define a list of inputs you can use in your controls.
- Use `gem_dependencies` to specify a list of profile gem dependencies that is required to be installed for the profile to function correctly.
`name` is required; all other profile settings are optional. For example:
```yaml
name: ssh
title: Basic SSH
maintainer: Chef Software, Inc.
copyright: Chef Software, Inc.
copyright_email: support@chef.io
license: Proprietary, All rights reserved
summary: Verify that SSH Server and SSH Client are configured securely
version: 1.0.0
supports:
- platform-family: linux
depends:
- name: profile
path: ../path/to/profile
gem_dependencies:
- name: "gem-name"
version: ">= 2.0.0"
inspec_version: "~> 2.1"
```
The `inspec.yml` also supports embedded ERB in the file. For example:
```yaml
name: dummy
title: InSpec Profile
maintainer: The Authors
copyright: The Authors
copyright_email: you@example.com
license: Apache-2.0
summary: An InSpec Compliance Profile
version: 0.1.0
depends:
- name: inherit
url: "https://artifactory.com/artifactory/example-repo-local/inspec/0.4.1.tar.gz"
username: <%= ENV['USERNAME'] %>
password: <%= ENV['API_KEY'] %>
```
## Verify Profiles
Use the `inspec check` command to verify the implementation of a profile:
```bash
inspec check examples/profile
```
## Platform Support
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 the following:
- Use `platform-family` to restrict to a specific platform family.
- Use `platform-name` to restrict on a specific platform name. `platform-name` supports asterisk (`*`) wildcard use.
- Use `release` to restrict to a specific platform version, and use together with `platform-name`. `release` supports asterisk (`*`) wildcard use.
- Use `platform` to restrict on either platform-name or platform-family.
To get a list of all valid values for `platform-name` and `platform-family`, run `inspec schema platforms`, which returns the supported list in JSON format.
For compatibility we support `os-name` and `os-family`. We recommend all users
to change `os-name` to `platform-name` and `os-family` to `platform-family`.
With Chef InSpec 2.0, we introduced new families to help distinguish the cloud
platforms. The new families can restrict the platform family to `os`, `aws`, `azure` or `gcp`.
For example, to target anything running Debian Linux, use:
```yaml
name: ssh
supports:
- platform-name: debian
```
To target only Ubuntu version 20.04, use:
```yaml
name: ssh
supports:
- platform-name: ubuntu
release: 20.04
```
To target the entire release of Ubuntu version 20.x, use:
```yaml
name: ssh
supports:
- platform-name: ubuntu
release: 20.*
```
To target the Red Hat and derivative platforms such as CentOS and Oracle Linux, use:
```yaml
name: ssh
supports:
- platform-family: redhat
```
To target the entire Windows 2019 platform family, including Datacenter and Core Servers, use:
```yaml
name: ssh
supports:
- platform-name: windows_server_2019*
```
To target anything running on Amazon AWS, use:
```yaml
name: ssh
supports:
- platform: aws
```
To target all of these examples in a single `inspec.yml` file, use:
```yaml
name: ssh
supports:
- platform-name: debian
- platform-name: ubuntu
release: 20.04
- platform-family: redhat
- platform: aws
```
## Profile Dependencies
A Chef InSpec profile can bring in the controls and custom resources from another
Chef InSpec profile. Additionally, when inheriting the controls of another profile,
a profile can skip or even modify those included controls.
For hands-on examples, check out [Test Expectations with Chef InSpec](https://learn.chef.io/courses/course-v1:chef+Inspec101+Perpetual/about)
on Learn Chef Rally.
### Defining the Dependencies
Before a profile can use controls from another profile, the to-be-included profile
needs to be specified in the including profiles `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:
```yaml
depends:
- name: linux-baseline
url: https://github.com/dev-sec/linux-baseline/archive/master.tar.gz
- name: ssh-baseline
url: https://github.com/dev-sec/ssh-baseline/archive/master.tar.gz
```
Chef InSpec supports a number of dependency sources.
#### path
The `path` setting defines a profile that is located on disk. This setting is
typically used during development of profiles and when debugging profiles.
```yaml
depends:
- name: my-profile
path: /absolute/path
- name: another
path: ../relative/path
```
#### url
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).
```yaml
depends:
- name: my-profile
url: https://my.domain/path/to/profile.tgz
- name: profile-via-git
url: https://github.com/username/myprofile-repo/archive/master.tar.gz
```
`url` also supports basic authentication.
```yaml
depends:
- name: my-profile
url: https://my.domain/path/to/profile.tgz
username: user
password: password
```
#### git
A `git` setting specifies a profile that is located in a git repository, with
optional settings for branch, tag, commit, version, and relative_path. The source
location is translated into a URL upon resolution. This type of dependency supports
version constraints via semantic versioning as git tags.
```yaml
depends:
- name: git-profile
git: http://url/to/repo
branch: desired_branch
tag: desired_version
commit: pinned_commit
version: semver_via_tags
relative_path: relative/optional/path/to/profile
```
#### supermarket
A `supermarket` setting specifies a profile that is located in a cookbook hosted
on Chef Supermarket. The source location is translated into a URL upon resolution.
For example:
```yaml
depends:
- name: supermarket-profile
supermarket: supermarket-username/supermarket-profile
```
Available Supermarket profiles can be listed with `inspec supermarket profiles`.
#### compliance
A `compliance` setting specifies a profile that is located on the Chef Automate
or Chef Compliance server.
For example:
```yaml
depends:
- name: linux
compliance: base/linux
```
## Gem Dependencies
Any profile with ruby gem dependencies that need to be installed can be specified using the `gem_dependencies` settings in the `inspec.yml` metadata file.
For example, if you required any ruby library in a custom resource that needs a specific gem to be installed, then you can specify those gems in the metadata file. Chef InSpec will prompt to install the gems to `~/.inspec/gems` when you run your profile the first time. To skip the prompt and automatically install, pass the `--auto-install-gems` option to `inspec exec`.
```yaml
gem_dependencies:
- name: "mongo"
version: ">= 2.3.12"
```
## Vendoring Dependencies
When you execute a local profile, the `inspec.yml` file will be read in order to
source any profile dependencies. It will then cache the dependencies locally and
generate an `inspec.lock` file.
If you add or update dependencies in `inspec.yml`, dependencies may be re-vendored
and the lockfile updated with `inspec vendor --overwrite`
## Using Controls from an Included Profile
Once defined in the `inspec.yml`, controls from the included profiles can be used!
Lets look at some examples.
### Including All Controls from a Profile
With the `include_controls` command in a profile, all controls from the named
profile will be executed every time the including profile is executed.
![Include Controls](/images/inspec/include_controls.png)
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:
- myapp-1
- myapp-2
- myapp-3
- baseline-1
- baseline-2
This is a great reminder that having a good naming convention for your controls
is helpful to avoid confusion when
including controls from other profiles!
### Skipping a Control from a Profile
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 Chef InSpec to not run a particular control.
![Include Controls with Skip](/images/inspec/include_controls_with_skip.png)
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.
### Modifying a Control
Let's say a particular control from an included profile should still be run, but
the impact isn't appropriate? Perhaps the test should still run, but if it fails,
it should be treated as low severity instead of high severity?
When a control is included, it can also be modified!
![Include Controls with Modification](/images/inspec/include_controls_with_mod.png)
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`.
### Selectively Including Controls from a Profile
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.
![Require Controls](/images/inspec/require_controls.png)
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:
- myapp-1
- myapp-2
- myapp-3
- baseline-2
- baseline-4
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.
And, just the way its possible to modify controls when using `include_controls`,
controls can be modified as well.
![Require Controls with Modification](/images/inspec/require_controls_with_mod.png)
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.
## Including or Selecting controls from a profile with same name and different version.
When an inspec profile has dependency on another profile to it's specific version, then the controls can be included or selected by using profile name with version separated by `-`.
Here, the Profile - A has following dependency:
```yaml
name: profile-a
depends:
- name: ssh
git: https://github.com/dev-sec/ssh-baseline.git
tag: 2.6.0
```
And Profile - B has following dependency:
```yaml
name: profile-b
depends:
- name: ssh
git: https://github.com/dev-sec/ssh-baseline.git
tag: 2.7.0
```
Controls of these profiles can be included or required in a profile in a following manner:
```ruby
include_controls "ssh-2.6.0"
include_controls "ssh-2.7.0"
```
OR
```ruby
require_controls "ssh-2.6.0"
require_controls "ssh-2.7.0"
```
## Using Resources from an Included Profile
By default, all of the custom resources from a listed dependency are available
for use in your profile. If two of your dependencies provide a resource with
the same name, you can use the `require_resource` DSL function to
disambiguate the two:
```yaml
require_resource(profile: 'my_dep', resource: 'my_res',
as: 'my_res2')
```
This will allow you to reference the resource `my_res` from the
profile `my_dep` using the name `my_res2`.
## Profile Inputs
Our documentation regarding [Inputs](/inspec/inputs/) is now on a dedicated page.
## Profile files
A Chef InSpec profile may contain additional files that can be accessed during
tests. A profile file enables you to separate the logic of your tests from the
data your tests check for, for example, the list of ports you require to be open.
To access these files, they must be stored in the `files` directory at the root
of a profile. They are accessed by their name relative to this folder with
`inspec.profile.file(...)`.
Here is an example for reading and testing a list of ports. The folder structure is:
```yaml
examples/profile
├── controls
│ ├── example.rb
│── files
│ └── services.yml
└── inspec.yml
```
With `services.yml` containing:
```yaml
- service_name: httpd-alpha
port: 80
- service_name: httpd-beta
port: 8080
```
The tests in `example.rb` can now access this file:
```ruby
my_services = yaml(content: inspec.profile.file('services.yml')).params
my_services.each do |s|
describe service(s['service_name']) do
it { should be_running }
end
describe port(s['port']) do
it { should be_listening }
end
end
```
For a more complete example that uses a profile file, see
[Explore Chef InSpec resources](https://learn.chef.io/modules/explore-inspec-resources#/) on Learn Chef Rally.
## "should" vs. "expect" syntax
Users familiar with the RSpec testing framework may know that there are two ways
to write test statements: `should` and `expect`. The RSpec community decided that
`expect` is the preferred syntax. However, Chef InSpec recommends the `should`
syntax as it tends to read more easily to those users who are not as technical.
Chef InSpec will continue to support both methods of writing tests. Consider
this `file` test:
```Ruby
describe file('/tmp/test.txt') do
it { should be_file }
end
```
This can be re-written with `expect` syntax
```Ruby
describe file('/tmp/test.txt') do
it 'should be a file' do
expect(subject).to(be_file)
end
end
```
The output of both of the above examples looks like this:
```bash
File /tmp/test.txt
✔ should be a file
```
In addition, you can make use of the `subject` keyword to further control your
output if you choose:
```Ruby
describe 'test file' do
subject { file('/tmp/test.txt') }
it 'should be a file' do
expect(subject).to(be_file)
end
end
```
... which will render the following output:
```bash
test file
✔ should be a file
```

View file

@ -0,0 +1,110 @@
+++
title = "About Chef InSpec Profiles"
draft = false
gh_repo = "inspec"
[menu]
[menu.inspec]
title = "About Profiles"
identifier = "inspec/profiles/Overview"
parent = "inspec/profiles"
weight = 10
+++
A Chef InSpec profile organizes multiple controls into a reusable artifact that can be described and versioned.
Each profile is a standalone structure with its own distribution and execution flow.
Chef InSpec supports complex test and compliance profiles, which organize controls to support dependency management and code reuse.
For hands-on examples, check out [Test Expectations with Chef InSpec](https://learn.chef.io/courses/course-v1:chef+Inspec101+Perpetual/about) on Learn Chef to learn more about how profiles are structured.
## Initialize a new profile
Use the InSpec CLI to generate a new profile.
```sh
inspec init profile <PROFILE NAME>
```
### Platforms
You can an initialize profiles that are configured for Google Cloud, Azure, or AWS using the `--platform` option.
```sh
inspec init profile --platform <PLATFORM> <PROFILE NAME>
```
Replace:
- `<PROFILE NAME>` with the name of your profile
- `<PLATFORM>` with one of the following:
- `aws`
- `azure`
- `gcp`
## Profile structure
A profile has following structure:
```yaml
profile
├── README.md
├── controls
│ ├── example.rb
│ └── control_etc.rb
├── libraries
│ └── extension.rb
|── files
│ └── extras.conf
└── inspec.yml
```
`inspec.yml`
: The [`inspec.yml` file](inspec_yml) describes the profile.
Required
`controls`
: The [`controls` directory](controls) contains all tests.
Required
`libraries`
: The `libraries` directory contains all Chef InSpec [resource extensions](custom_resources).
Optional
`files`
: The [`files` directory](files) contains additional files that a profile can access.
Optional
`README.md`
: The `README.md` explains the profile, its scope, and usage.
Optional
## Verify profiles
Use the `inspec check` command to verify the implementation of a profile:
```bash
inspec check examples/profile
```
## Execute a profile
Use the `exec` subcommand to execute a profile.
```sh
inspec exec <PROFILE>
```
`inspec exec` accepts profiles from several sources, including a local directory, Git repositories, and web-hosted tar files.
See the [`inspec exec` documentation](/inspec/cli#exec) for more information.
You can format the results of an audit using [InSpec reporters](/inspec/reporters/).
## Example profiles
See the `inspec` repository for some [example profiles](https://github.com/inspec/inspec/tree/main/examples).

View file

@ -0,0 +1,549 @@
+++
title = "InSpec Profile Controls"
draft = false
gh_repo = "inspec"
[menu]
[menu.inspec]
title = "Controls"
identifier = "inspec/profiles/controls"
parent = "inspec/profiles"
weight = 30
+++
Controls define the regulatory recommendations or requirements for the state of a system.
Controls are written in Ruby using the InSpec DSL, which is a Ruby DSL for writing audit controls and includes audit resources that you can invoke.
## Controls location
Add the controls to the `controls` directory at the root of a profile.
```text
examples/profile
├── controls
│ └── example.rb
└── inspec.yml
```
## Syntax
The following resource tests |ssh| server configuration. For example, a simple control may described as:
```ruby
describe sshd_config do
its('Port') { should cmp 22 }
end
```
In various use cases like implementing IT compliance across different departments, it becomes handy to extend the control with metadata. Each control may define an additional `impact`, `title` or `desc`. An example looks like:
```ruby
control 'sshd-8' do
impact 0.6
title 'Server: Configure the service port'
desc 'Always specify which port the SSH server should listen.'
desc 'rationale', 'This ensures that there are no unexpected settings'
tag 'ssh','sshd','openssh-server'
tag cce: 'CCE-27072-8'
ref 'NSA-RH6-STIG - Section 3.5.2.1', url: 'https://www.nsa.gov/ia/_files/os/redhat/rhel5-guide-i731.pdf'
describe sshd_config do
its('Port') { should cmp 22 }
end
end
```
### Control properties
Name
: The name of the control is a unique control ID that's initialized at the beginning of the control block.
`sshd-8` is the control name in the example above.
`impact`
: The importance of the compliance results.
Data type: String, Float
Possible string values (based on CVSS 3.0):
- `none`
- `low`
- `medium`
- `high`
- `critical`
Numeric values must be between `0.0` and `1.0`. The value ranges are:
- `0.0 to <0.01` these are controls with no impact, they only provide information
- `0.01 to <0.4` these are controls with low impact
- `0.4 to <0.7` these are controls with medium impact
- `0.7 to <0.9` these are controls with high impact
- `0.9 to 1.0` these are critical controls
`title`
: A human-readable title for the control block.
Optional
`desc`
: A human-readable description of the what the control block does.
`desc` may include two arguments. The first argument is used as a header when rendering in Chef Automate. For example:
`desc 'rationale', 'This ensures that there are no unexpected settings'`
Optional
`tag`
: Meta-information with key or key-value pairs.
Optional
`ref`
: A reference to an external document
`describe`
: A describe block invokes an [InSpec resource](/inspec/resources/) or [custom resource](/inspec/profiles/custom_resources/) and encloses tests that apply to that resource. Group multiple related describe blocks under one control.
## Advanced concepts
### Check if at least one condition passes
Use `describe.one` to define a set of `describe` blocks where only one block needs to pass.
For example, if you configure a setting in two different locations, then you may want to test if either configuration A or configuration B is set.
```ruby
describe.one do
describe ConfigurationA do
its('setting_1') { should eq true }
end
describe ConfigurationB do
its('setting_2') { should eq true }
end
end
```
`describe.one` has the following conditions:
- A `describe.one` block passes if one of its nested `describe` blocks has all assertions passing. A `describe.one` block needs an entire `describe` block to pass and not just a single assertion.
- Chef InSpec will always evaluate all the tests contained within `describe.one`. It does not short-circuit upon evaluating a passing `describe` block.
- Nesting a `describe.one` block inside another `describe.one` block is not supported.
### Sensitive resources
Use the `:sensitive` flag in resource definition to suppress the output an audit.
For example, you may write checks that involve resources with sensitive content, such as a file resource.
```ruby
describe file('/tmp/mysecretfile'), :sensitive do
its('content') { should match /secret_info/ }
end
```
## Examples
The following examples show simple compliance tests using a single `control` block.
### Test password complexity
The following test shows how to audit machines running Windows 2012 R2 that password complexity is enabled:
```ruby
control 'windows-account-102' do
impact 'critical'
title 'Windows Password Complexity is Enabled'
desc 'Password must meet complexity requirement'
describe security_policy do
its('PasswordComplexity') { should cmp 1 }
end
end
```
### Test if PostgreSQL passwords are empty
The following test shows how to audit machines running PostgreSQL to ensure that passwords are not empty.
```ruby
control 'postgres-7' do
impact 1.0
title "Don't allow empty passwords"
describe postgres_session('user', 'pass').query("SELECT * FROM pg_shadow WHERE passwd IS NULL;") do
its('output') { should cmp '' }
end
end
```
### Test if MySQL passwords are in ENV
The following test shows how to audit machines running MySQL to ensure that passwords are not stored in `ENV`:
```ruby
control 'mysql-3' do
impact 1.0
title 'Do not store your MySQL password in your ENV'
desc '
Storing credentials in your ENV may easily expose
them to an attacker. Prevent this at all costs.
'
describe command('env') do
its('stdout') { should_not match /^MYSQL_PWD=/ }
end
end
```
### Test if `/etc/ssh` is a directory
The following test shows how to audit machines to ensure that `/etc/ssh` is a directory:
```ruby
control 'basic-1' do
impact 1.0
title '/etc/ssh should be a directory'
desc '
In order for OpenSSH to function correctly, its
configuration path must be a folder.
'
describe file('/etc/ssh') do
it { should be_directory }
end
end
```
### Test if Apache running
The following test shows how to audit machines to ensure that Apache is enabled and running:
```ruby
control 'apache-1' do
impact 'medium'
title 'Apache2 should be configured and running'
describe service(apache.service) do
it { should be_enabled }
it { should be_running }
end
end
```
### Test if insecure packages are installed
The following test shows how to audit machines for insecure packages:
```ruby
control 'cis-os-services-5.1.3' do
impact 0.7
title '5.1.3 Ensure rsh client is not installed'
describe package('rsh') do
it { should_not be_installed }
end
describe package('rsh-redone-client') do
it { should_not be_installed }
end
end
```
### Test Windows Registry Keys
The following test shows how to audit machines to ensure Safe DLL Search Mode is enabled:
```ruby
control 'windows-base-101' do
impact 1.0
title 'Safe DLL Search Mode is Enabled'
desc '
@link: https://msdn.microsoft.com/en-us/library/ms682586(v=vs.85).aspx
'
describe registry_key('HKLM\\System\\CurrentControlSet\\Control\\Session Manager') do
it { should exist }
it { should_not have_property_value('SafeDllSearchMode', :type_dword, '0') }
end
end
```
### Use `only_if` to exclude a specific control
This example shows how to allow skipping certain controls if conditions are not
met by using `only_if`. In this example, the control will not be performed if
the `redis-cli` command does not exist. A optional message can say why it was skipped.
```ruby
control 'nutcracker-connect-redis-001' do
impact 'critical'
title 'Check if nutcracker can pass commands to redis'
desc 'execute redis-cli set key command, to check connectivity of the service'
only_if('redis is not installed.') do
command('redis-cli').exist?
end
describe command('redis-cli SET test_inspec "HELLO"') do
its('stdout') { should match /OK/ }
end
end
```
This example checks for if certain pip packages are installed, but only if '/root/.aws' exists:
```ruby
control 'pip-packages-installed' do
title 'Check if essential pips are installed'
only_if('aws-cli config not created.') do
directory('/root/.aws').exist?
end
%w(aws-mfa PyYAML awscli).each do |aws_pip_deps|
describe pip(aws_pip_deps) do
it { should be_installed }
end
end
end
```
Mixing this with other conditionals, such as checking existence of the files, can
help to test different test paths using Chef InSpec. With this way, you can skip
certain controls, which would 100% fail due to the way servers are prepared, but
you know that the same control suites are reused later in different circumstances
by different teams.
This example checks whether the Gnome Desktop is installed. If not installed, it resets the impact of the control to the new value which is passed as a hash with the impact key.
Here, it resets it to 0:
```ruby
control 'gnome-destkop-settings' do
impact 0.5
desc 'some good settings'
desc 'check', 'check the settings file for good things'
desc 'fix', 'set the good things in the file /etc/gnome/settings'
tag nist: 'CM-6'
only_if("The Gnome Desktop is not installed, this control is Not Applicable", impact: 0) {
package('gnome-desktop').installed?
}
describe gnome_settings do
it should_be set_well
end
end
```
Some notes about `only_if`:
- `only_if` applies to the entire `control`. If the results of the `only_if`
block evaluate to false, any Chef InSpec resources mentioned as part of a
`describe` block will not be run. Additionally, the contents of the describe
blocks will not be run. However, bare Ruby expressions and bare Chef InSpec
resources (not assocated with a describe block) preceding the only_if statement
will run
- `only_if` also accepts hash with impact key to reset the impact value of the control. Control's impact is helpful in determining it is enhanced outcome.
To illustrate:
```ruby
control "whatruns" do
command("do_something") # This will ALWAYS run
describe command("do_another_thing") do # This will not run
command("do_yet_another_thing") # This will not run
end
only_if { false }
command("do_something_else") # This will not run
end
```
- Only one `only_if` is permitted per `control` block. If multiple `only_if` blocks are present, only the last `only_if` block will be honored
- If used outside a control block, `only_if` skips all controls in the current file
- To implement complex logic, use Ruby 'or' (`||`) and 'and' (`&&`) inside your `only_if` block:
```ruby
only_if('ready for launch') do
rocket_is_ready && weather_is_clear
end
```
### Test controls for applicability using `only_applicable_if`
The `only_applicable_if` block allows to test if a control is applicable or not. In this example, the control with `only_applicable_if` block checks the condition and marks the control as not applicable (N/A) if the results of the `only_applicable_if` block evaluates to `false`.
If **gnome-desktop** is not installed, the following control to test gnome settings marks control as **not applicable**.
```ruby
control 'gnome-destkop-settings' do
impact 0.5
desc 'some good settings'
desc 'check', 'check the settings file for good things'
desc 'fix', 'set the good things in the file /etc/gnome/settings'
tag nist: 'CM-6'
only_applicable_if("The Gnome Desktop is not installed, this control is Not Applicable") {
package('gnome-desktop').installed?
}
describe gnome_settings do
it should_be set_well
end
end
```
Run output:
```bash
inspec exec path/to/audit-gnome-settings-profile --enhanced-outcomes
Profile: InSpec Profile (audit-gnome-settings-profile)
Version: 0.1.0
Target: local://
Target ID: fa3923b9-f806-4cc2-960d-1ddefb4c7654
N/A gnome-destkop-settings: No-op
× No-op
N/A control due to only_applicable_if condition: The Gnome Desktop is not installed, this control is Not Applicable
Profile Summary: 0 successful controls, 0 control failure, 0 controls not reviewed, 1 controls not applicable, 0 controls have error
Test Summary: 0 successful, 1 failures, 0 skipped
```
Some notes about `only_applicable_if`:
- `only_applicable_if` applies to the entire `control`. If the results of the `only_applicable_if` block evaluates to `false`, any Chef InSpec resources mentioned as part of a `describe` block will not be run. Additionally, the contents of the describe blocks will not be run.
- If the results of the `only_applicable_if` block evaluates to `false`, it will invoke a failing test which will state the reason for N/A.
### Additional metadata
The following example illustrates various ways to add tags and references to `control`
```ruby
control 'ssh-1' do
impact 1.0
title 'Allow only SSH Protocol 2'
desc '
Only SSH protocol version 2 connections should be permitted.
The default setting in /etc/ssh/sshd_config is correct, and can be
verified by ensuring that the following line appears: Protocol 2
'
tag 'production','development'
tag 'ssh','sshd','openssh-server'
tag cce: 'CCE-27072-8'
tag disa: 'RHEL-06-000227'
tag remediation: 'stig_rhel6/recipes/sshd-config.rb'
tag remediation: 'https://supermarket.chef.io/cookbooks/ssh-hardening'
ref 'NSA-RH6-STIG - Section 3.5.2.1', url: 'https://www.nsa.gov/ia/_files/os/redhat/rhel5-guide-i731.pdf'
ref 'http://people.redhat.com/swells/scap-security-guide/RHEL/6/output/ssg-centos6-guide-C2S.html'
describe ssh_config do
its('Protocol') { should cmp 2 }
end
end
```
## Using Ruby in InSpec
The Chef InSpec Language is a Ruby based language. This allows you to be flexible with
Ruby code in controls:
```ruby
json_obj = json('/file.json')
json_obj['keys'].each do |value|
..
end
```
Ruby allows a lot of freedoms, but should be limited in controls so that they
remain portable and easy to understand. Please see our [profile style guide](/inspec/style/).
Core and custom resources are written as regular Ruby classes which inherit from
`Inspec.resource`.
### Interactive Debugging with Pry
Here's a sample Chef InSpec control that uses Ruby variables to instantiate
a Chef InSpec resource once and use the content in multiple tests.
```ruby
control 'check-perl' do
impact 0.3
title 'Check perl compiled options and permissions'
perl_out = command('perl -V')
#require 'pry'; binding.pry;
describe perl_out do
its('exit_status') { should eq 0 }
its('stdout') { should match /USE_64_BIT_ALL/ }
its('stdout') { should match /useposix=true/ }
its('stdout') { should match /-fstack-protector/ }
end
# extract an array of include directories
perl_inc = perl_out.stdout.partition('@INC:').last.strip.split("\n")
# ensure include directories are only writable by 'owner'
perl_inc.each do |path|
describe directory(path.strip) do
it { should_not be_writable.by 'group' }
it { should_not be_writable.by 'other' }
end
end
end
```
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:
```ruby
[1] pry> perl_out.exit_status
=> 0
[2] pry> perl_out.stderr
=> ""
[3] pry> ls perl_out
Inspec::Plugins::Resource#methods: inspect
Inspec::Resources::Cmd#methods: command exist? exit_status result stderr stdout to_s
Inspec::Resource::Registry::Command#methods: inspec
instance variables: @__backend_runner__ @__resource_name__ @command @result
[4] pry> perl_out.stdout.partition('@INC:').last.strip.split("\n")
=> ["/Library/Perl/5.18/darwin-thread-multi-2level",
" /Library/Perl/5.18",
...REDACTED...
[5] pry> exit # or abort
```
You can use `pry` inside both the controls DSL and resources. Similarly,
for dev and test, you can use `inspec shell` which is based on `pry`,
for example:
```ruby
$ inspec shell
Welcome to the interactive InSpec Shell
To find out how to use it, type: help
inspec> command('ls ~/projects/github/inspec/docs').stdout
=> "README.md\nconfig.md\ndev\ndsl_inspec.md\ndsl_resource.md\nglossary.md\nhabitat.md\ninputs.md\ninspec_and_friends.md\nmatchers.md\nmigration.md\nplatforms.md\nplugin_kitchen_inspec.md\nplugins.md\nprofiles.md\nreporters.md\nresources\nshared\nshell.md\nstyle.md\nwaivers.md\n"
inspec> command('ls ~/projects/github/inspec/docs').stdout.split("\n").first
=> "README.md"
inspec> help command
Name: command
Description:
Use the command InSpec audit resource to test an arbitrary command that is run on the system.
Example:
describe command('ls -al /') do
it { should exist }
its('stdout') { should match /bin/ }
its('stderr') { should eq '' }
its('exit_status') { should eq 0 }
end
```

View file

@ -0,0 +1,199 @@
+++
title = "InSpec Custom Resources"
draft = false
gh_repo = "inspec"
[menu]
[menu.inspec]
title = "Custom Resources"
identifier = "inspec/profiles/libraries"
parent = "inspec/profiles"
weight = 40
+++
You can extend the functionality of Chef InSpec profiles by creating custom resources.
For hands-on examples, check out [Extending InSpec: InSpec Wrappers and Custom Resources](https://learn.chef.io/courses/course-v1:chef+InSpec201+Perpetual/about) on Learn Chef.
## Resource location
Create custom resources in a profile's libraries directory.
```bash
examples/profile
...
├── libraries
│   └── example_config.rb
```
## Resource structure
The smallest possible resource takes this form:
```ruby
class Tiny < Inspec.resource(1)
name 'tiny'
end
```
Resources are written as a regular Ruby class which inherits from
Inspec.resource. The number (1) specifies the version this resource
plugin targets. As Chef InSpec evolves, this interface may change and may
require a higher version.
### Resource attributes
Use the following attributes to configure a resource.
`name`
: Identifier of the resource.
Required
`desc`
: Description of the resource
Optional
`example`
: Example usage of the resource
Optional
`supports`
: Platform restrictions of the resource
Optional
### Resource methods
The following methods are available to the resource.
`inspec`
: Contains a registry of all other resources to interact with the operating system or target in general.
`skip_resource`
: A resource may call this method to indicate that requirements aren't met. All tests that use this resource will be marked as skipped.
The additional methods may be defined within the resource:
`resource_id`
: An instance method. Place logic here to determine the unique identifier for a resource, and set it using the superclass method.
Following is an example of its usage in an InSpec test:
```ruby
# example_config resource can have unique conf file path as an identifier.
describe example_config do
its("resource_id") { should eq PATH_OF_CONF_FILE }
end
```
### Example
The following example shows a full resource using attributes and methods
to provide simple access to a configuration file:
```ruby
class ExampleConfig < Inspec.resource(1)
name 'example_config'
# Restrict to only run on the below platforms (if none were given, all OS's supported)
supports platform_family: 'fedora'
supports platform: 'centos', release: '6.9'
# Supports `*` for wildcard matcher in the release
supports platform: 'centos', release: '7.*'
desc '
Resource description ...
'
example '
describe example_config do
its("signal") { should eq "on" }
end
'
# Load the configuration file on initialization
def initialize(path = nil)
@path = path || '/etc/example.conf'
@params = SimpleConfig.new( read_content )
end
# Expose all parameters of the configuration file.
def method_missing(name)
@params[name]
end
def resource_id
value = example_method_to_determine_resource_id # define logic to determine resource_id value
super(value)
end
private
def read_content
f = inspec.file(@path)
# Test if the path exist and that it's a file
if f.file?
# Retrieve the file's contents
f.content
else
# If the file doesn't exist, skip all tests that use example_config
raise Inspec::Exceptions::ResourceSkipped, "Can't read config at #{@path}"
end
end
end
```
For a full example, see our [example resource](https://github.com/chef/inspec/blob/main/examples/profile/libraries/example_config.rb).
## Alternate custom resource names
If you have a profile that includes another profile with custom resources as a dependency, the custom resources from the dependent profile are included by default.
If two custom resource names conflict, you can use the `require_resource` InSpec DSL function to rename a custom resource in control code.
```ruby
require_resource(
profile: '<DEPENDENCY_NAME>',
resource: '<RESOURCE_NAME>',
as: '<ALTERNATE_RESOURCE_NAME>'
)
```
where:
- `<DEPENDENCY_NAME>` is the dependent profile
- `<RESOURCE_NAME>` is the resource name in the dependent profile
- `<ALTERNATE_RESOURCE_NAME>` is an alternate name for that resource
## Lazy Loading
Prior to InSpec v4.16, resources were pre-loaded for every invocation
of `inspec`. This was a heavy and unnecessary burden on the system and
exacerbated startup times (especially on Windows).
As of InSpec v4.16, resources are lazily loaded into the `inspec`
process upon use. This greatly speeds up the initial startup costs of
the `inspec` process and only loads what you need to use. For example, `inspec
--version` no longer runs for 10 seconds!.
### Overriding Core Resources
Lazy loading does change the way the resource registry is handled in
ways that might break some assumptions. Specifically,
`inspec.<resource>` isn't pre-populated with the core resources that
InSpec ships with. If you make a local/custom resource of the same
name, referring to the core resource via `inspec.<resource>` will not
resolve to the core resource.
As such, overriding core resources is not recommended best practice.
If you really do need to do this, it is easiest to make a local
resource with a new name and refer to the core resource directly.
Otherwise, you need to ensure that the core resource you want is
registered (via `require "inspec/resource/<name>"`) _before_ your
profile is run to ensure it is eagerly loaded and in the global
resource registry.

View file

@ -0,0 +1,362 @@
+++
title = "InSpec Profile Dependencies"
draft = false
gh_repo = "inspec"
[menu]
[menu.inspec]
title = "Dependencies"
identifier = "inspec/profiles/depends"
parent = "inspec/profiles"
weight = 50
+++
A Chef InSpec profile can bring in the controls and custom resources from another
Chef InSpec profile. Additionally, when inheriting the controls of another profile,
a profile can skip or even modify those included controls.
For hands-on examples, check out [Extending InSpec: InSpec Wrappers and Custom Resources](https://learn.chef.io/courses/course-v1:chef+InSpec201+Perpetual/about) on Learn Chef.
## Define dependencies
Before a profile can use controls from another profile, the to-be-included profile
needs to be specified in the including profiles `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:
```yaml
depends:
- name: linux-baseline
url: https://github.com/dev-sec/linux-baseline/archive/master.tar.gz
- name: ssh-baseline
url: https://github.com/dev-sec/ssh-baseline/archive/master.tar.gz
```
Chef InSpec supports a number of dependency sources.
### path
The `path` setting defines a profile that is located on disk. This setting is
typically used during development of profiles and when debugging profiles.
```yaml
depends:
- name: my-profile
path: /absolute/path
- name: another
path: ../relative/path
```
### url
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).
```yaml
depends:
- name: my-profile
url: https://example.com/path/to/profile.tgz
- name: profile-via-git
url: https://github.com/username/myprofile-repo/archive/master.tar.gz
```
`url` also supports basic authentication.
```yaml
depends:
- name: my-profile
url: https://example.com/path/to/profile.tgz
username: user
password: password
```
### git
A `git` setting specifies a profile that is located in a Git repository, with
optional settings for `branch`, `tag`, `commit`, `version`, and `relative_path`. The source
location is translated into a URL upon resolution. This type of dependency supports
version constraints via semantic versioning as Git tags.
```yaml
depends:
- name: git-profile
git: http://example.com/path/to/repo
branch: desired_branch
tag: desired_version
commit: pinned_commit
version: semver_via_tags
relative_path: relative/optional/path/to/profile
```
### supermarket
A `supermarket` setting specifies a profile that is located in a cookbook hosted
on Chef Supermarket. The source location is translated into a URL upon resolution.
For example:
```yaml
depends:
- name: supermarket-profile
supermarket: supermarket-username/supermarket-profile
```
Available Supermarket profiles can be listed with `inspec supermarket profiles`.
### compliance
A `compliance` setting specifies a profile that is located on the Chef Automate
or Chef Compliance server.
For example:
```yaml
depends:
- name: linux
compliance: base/linux
```
## Gem dependencies
Any profile with Ruby gem dependencies that need to be installed can be specified using the `gem_dependencies` settings in the `inspec.yml` metadata file.
For example, if you required any Ruby library in a custom resource that needs a specific gem to be installed, then you can specify those gems in the metadata file.
Chef InSpec will prompt to install the gems to `~/.inspec/gems` when you run your profile the first time.
To skip the prompt and automatically install, pass the `--auto-install-gems` option to `inspec exec`.
```yaml
gem_dependencies:
- name: "mongo"
version: ">= 2.3.12"
```
## Alternate resource names
By default, all [custom resources](/inspec/profiles/custom_resources/) from a listed dependency are available for use in a profile.
If two of your dependencies provide a resource with the same name, you can use the `require_resource` InSpec DSL function to disambiguate the two:
```ruby
require_resource(
profile: '<DEPENDENCY_NAME>',
resource: '<RESOURCE_NAME>',
as: '<ALTERNATE_RESOURCE_NAME>'
)
```
where:
- `<DEPENDENCY_NAME>` is the dependent profile
- `<RESOURCE_NAME>` is the resource name in the dependent profile
- `<ALTERNATE_RESOURCE_NAME>` is an alternate name for that resource
## Use controls from a dependent profile
After you define a dependent profile in the `inspec.yml` file, you can use controls from those profiles.
See the `inspec` repository for an [example profile](https://github.com/inspec/inspec/tree/main/examples/inheritance) that inherits controls from another profile.
The following examples show you how to include controls from a dependent profile.
### Include all controls
With the `include_controls` command in a profile, all controls from the named
profile will be executed every time the including profile is executed.
For example, if you have a profile called `baseline-profile` with the following controls:
- baseline-1
- baseline-2
And `app-profile` with the following controls:
- app-1
- app-2
- app-3
Add `baseline-profile` as dependency of `app-profile`, then include the `baseline-profile` controls using `include_controls` in the control code of `app-profile`:
```ruby
include_controls 'baseline-profile'
```
Every time you execute `app-profile`, InSpec also executes all the controls from `baseline-profile`:
- app-1
- app-2
- app-3
- baseline-1
- baseline-2
This is a great reminder that having a good naming convention for your controls
is helpful to avoid confusion when including controls from other profiles!
### Skip a control
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 Chef InSpec to not run a particular control.
For example, if you have a profile called `baseline-profile` with the following controls:
- baseline-1
- baseline-2
And `app-profile` with the following controls:
- app-1
- app-2
- app-3
Add `baseline-profile` as dependency of `app-profile`, then include the `baseline-profile` controls using `include_controls` and `skip_control` to exclude the profile you don't want execute:
```ruby
include_controls 'baseline-profile' do
skip_control 'baseline-2'
end
```
Every time you execute `app-profile`, InSpec also executes all the controls from `baseline-profile` except `baseline-2`:
- app-1
- app-2
- app-3
- baseline-1
### Modify a control
Let's say a particular control from an included profile should still be run, but
the impact isn't appropriate? Perhaps the test should still run, but if it fails,
it should be treated as low severity instead of high severity?
When a control is included, it can also be modified!
For example, if you have a profile called `baseline-profile` with the following controls:
- baseline-1
- baseline-2
And `baseline-1` has an `impact` of `1.0` defined in `baseline-profile`:
```ruby
control 'baseline-1' do
impact 1.0
...
end
```
Add `baseline-profile` as dependency of `app-profile`, then include the `baseline-profile` controls to `app-profile` using `include_controls` and redefine the impact of `baseline-1`:
```ruby
include_controls 'baseline-profile' do
control 'baseline-1' do
impact 0.5
end
end
```
In the above example, all controls from `baseline-profile` are executed along with all the controls from the including profile, `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`.
### Selectively include controls
Use the `require_controls` command selectively include certain controls from an included
profile. You don't have to skip all the unneeded controls, or worse,
copy/paste those controls bit-for-bit into your profile.
For example, if you have a profile called `baseline-profile` with the following controls:
- baseline-1
- baseline-2
- baseline-3
- baseline-4
- baseline-5
And `app-profile` with the following controls:
- app-1
- app-2
- app-3
Add `baseline-profile` as dependency of `app-profile`, then include specific `baseline-profile` controls using `require_controls` in the control code of `app-profile`:
```ruby
require_controls 'baseline-profile' do
control 'baseline-2'
control 'baseline-4'
end
```
Every time you execute `app-profile`, InSpec executes the controls `app-profile` and the controls specified in the `require_controls` block:
- app-1
- app-2
- app-3
- baseline-2
- baseline-4
Controls `baseline-1`, `baseline-3`, and `baseline-5` are not 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 `baseline-profile`, they would not be run.
And, just the way its possible to modify controls when using `include_controls`,
controls can be modified with `require_controls` as well.
```ruby
require_controls 'baseline-profile' do
control 'baseline-2' do
impact 0.5
end
control 'baseline-4'
end
```
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.
## Include controls from different profile versions
When a Chef InSpec profile has dependency on another profile to its specific version, then the controls can be included or selected by using the profile name and version separated by `-`.
Here, `profile-a` has following dependency:
```yaml
name: profile-a
depends:
- name: ssh
git: https://github.com/dev-sec/ssh-baseline.git
tag: 2.6.0
```
And `profile-b` has following dependency:
```yaml
name: profile-b
depends:
- name: ssh
git: https://github.com/dev-sec/ssh-baseline.git
tag: 2.7.0
```
You can include or require controls of these profiles in a following manner:
```ruby
include_controls "ssh-2.6.0"
include_controls "ssh-2.7.0"
```
OR
```ruby
require_controls "ssh-2.6.0"
require_controls "ssh-2.7.0"
```
## Vendor dependencies
When you execute a local profile, Inspec reads the `inspec.yml` file in order to
source any profile dependencies. It then caches the dependencies locally and
generates an `inspec.lock` file.
If you add or update dependencies in `inspec.yml`, dependencies may be re-vendored
and the lockfile updated with `inspec vendor --overwrite`

View file

@ -0,0 +1,60 @@
+++
title = "Profile Files"
draft = false
gh_repo = "inspec"
[menu]
[menu.inspec]
title = "Files"
identifier = "inspec/profiles/files"
parent = "inspec/profiles"
weight = 50
+++
A Chef InSpec profile may contain additional files that can be accessed during tests.
A profile file enables you to separate the logic of your tests from the data your tests check for.
For example, the list of ports you require to be open.
## Files location
Add files to the `files` directory at the root of a profile.
```text
examples/profile
├── controls
│ ├── example.rb
│── files
│ └── services.yml
└── inspec.yml
```
## Access file
Use `inspec.profile.file('FILENAME.yml')` to access data from the file.
## Example
With `files/services.yml` containing the following data:
```yaml
- service_name: httpd-alpha
port: 80
- service_name: httpd-beta
port: 8080
```
The tests in `example.rb` can now access this file:
```ruby
my_services = yaml(content: inspec.profile.file('services.yml')).params
my_services.each do |s|
describe service(s['service_name']) do
it { should be_running }
end
describe port(s['port']) do
it { should be_listening }
end
end
```

View file

@ -0,0 +1,485 @@
+++
title = "Chef InSpec Inputs"
draft = false
gh_repo = "inspec"
[menu]
[menu.inspec]
title = "Inputs"
identifier = "inspec/profiles/Inputs"
parent = "inspec/profiles"
weight = 60
+++
Inputs allow you to customize the behavior of Chef InSpec profiles.
In [_profiles that accept inputs_](#profile-support), you can configure them using the following methods:
- Inline in [control code](#control-code)
- In the [`inspec.yml` file](#inspecyml-file)
- In the command line using the [`--input` option](#input-cli-option)
- In an input file that's invoked with the CLI [`--input-file` option](#input-file-cli-option)
- In [input plugins](#plugins)
Profiles that include other profiles can set inputs in the included profile, enabling a multi-layered approach to configuring profiles.
## Profile support
Profiles accept inputs from any input method as long as one or both of the following conditions exists:
- inputs are listed in the [`inspec.yml` file](#inspecyml-file)
- inputs are included in the [control source code](#control-code)
## Simple example
Suppose you have a profile named `rock_critic` and its profile `inspec.yml` metadata file includes the following inputs:
```yaml
# Optionally declare inputs in the profile metadata
# This lets you set up things like type checking, etc.
inputs:
- name: amplifier_max_volume
description: How loud the amplifiers can go
type: numeric
# More options, including value: and priority: are possible here
```
In the profile's control code, define the value of the input using the `input` function:
```ruby
# Set a default value for an input. This is optional.
input('amplifier_max_volume', value: 10)
control 'Big Rock Show' do
describe input('amplifier_max_volume') do # This line reads the value of the input
it { should cmp 11 } # The UK'S LOUDEST BAND
end
end
```
When the above profile is executed by using `inspec exec rock_critic`, you would see something like:
```bash
× Big Rock Show: 10
× 10 is expected to cmp == 11
expected: 11
got: 10
(compared using `cmp` matcher)
Profile Summary: 0 successful controls, 1 control failure, 0 controls skipped
```
The control fails because the value is set to `10`, but the control expects `11`.
That result clearly won't do.
By default, inputs set using the CLI `--input` option override inputs defined in control code.
So, you can set the `amplifier_max_volume` to `11` and the control will pass.
```sh
inspec exec rock_critic --input amplifier_max_volume=11
```
which returns:
```bash
✔ Big Rock Show: 11
✔ 11 is expected to cmp == 11
Profile Summary: 1 successful control, 0 control failures, 0 controls skipped
```
## Set inputs
You can set inputs using one or more of the following methods. Each method has a different priority allowing them to override each other. Some methods allow you to modify their priority. For more information, see the [input priority documentation](#input-priority).
### `--input` CLI option
Use the `--input` option to set inputs and values directly on the command line.
Inputs set with the `--input` option have a priority of 50.
```sh
inspec exec my_profile --input input_name=input_value
```
You can set multiple inputs.
```sh
inspec exec my_profile --input input_name1=input_value1 name2=value2
```
If a CLI input value resembles a number, it will be converted to an Integer or
Float. Scientific notation is not recognized.
```sh
inspec exec my_profile --input amplifier_volume=-11
inspec exec my_profile --input water_depth=11.5
```
You can set inputs with complex values, such as arrays and hashes using either
YAML or JSON syntax. Just be sure to protect the string from the shell using single
quotes.
```sh
inspec exec my_profile --input alphabet='[a,b,c]'
inspec exec my_profile --input fruits='{a: apples, b: bananas, c: cantelopes}'
inspec exec my_profile --input json_fruit='{"a": "apples", "g": ["grape01", "grape02"] }'
```
Do not repeat the `--input` flag; that will override the previous setting.
As of Chef InSpec 4.12, this mechanism has the following limitations:
- No [input options](#input-options) may be set---only the name and value.
- Because the CLI is outside the scope of any individual profile and the inputs
don't take options, the inputs are clumsily copied into every profile,
effectively making the CLI mechanism global.
### `--input-file` CLI option
You can set inputs and values with a YAML file in the command line.
Inputs set the `--input-file` option have a priority of 40.
Create a YAML file using the following format:
```yaml
an_input: a_value
another_input: another_value
```
Invoke the input file using the `--input-file` option.
```sh
inspec exec my_profile --input-file <FILENAME>.yml
```
As of Chef InSpec 4.3.2, this mechanism has the following limitations:
- No [input options](#input-options) may be set---only the name and value.
- Because the CLI is outside the scope of any individual profile and the inputs
don't take options, the inputs are clumsily copied into every profile,
effectively making the CLI mechanism global.
### inspec.yml file
In the [`inspec.yml` file](/inspec/profiles/inspec_yml), you may add a section for inputs.
You may define inputs there, clearly setting options including values, type checking, and whether the input is
required.
```yaml
name: my_profile
inputs:
- name: webserver_user # Name is the only required field
- name: favorite_fruit
value: banana # You can set a value; priority is 30 for metadata
- name: meaning_of_life
type: Numeric
value: 42
required: true
priority: 70
sensitive: true
```
All [input options](#input-options) are supported in metadata files.
Defining inputs in profile metadata has two major advantages:
- The inputs and their configuration are listed explicitly in simple YAML in one place - a consumer of your profile does not need to read through the control code to find the inputs.
- You can set inputs in other profiles that you depend on using profile inheritance.
#### Profile inheritance
When your profile relies on another profile using the `depends` key in the metadata file, you can set---that is, override---the value of the input in the dependent profile by including the `profile` option and naming the dependent profile.
```yaml
# child inspec.yml
name: child
inputs:
- name: favorite_food
value: pizza
```
```yaml
# wrapper inspec.yml
name: wrapper
depends:
- name: child
path: ../child
inputs:
- name: favorite_food
value: broccoli
profile: child # <----- REQUIRED to override the value in InSpec 4
```
In **Chef InSpec 4+**, every input is namespaced. For example, you could have an
input named `wrapper/favorite_food` and one named `child/favorite_food`. If no
explicit profile option is set within the `wrapper` profile metadata file, then
`wrapper` is assumed to be the profile.
### Control Code
Inputs are available throughout the InSpec profile DSL. You can use them anywhere.
```ruby
# some_controls.rb
input('outer_input', value: 1) # here
control 'control-1' do
input('control_dsl_input', value: 2) # here too
describe some_resource do
input('test_dsl_input', value: 3) # even here
it { should cmp input('expectation_dsl_input') } # and yes here too
end
end
```
#### Setting Inputs
When you write `input('some_name', value: 'some_value')`, you are *setting* an input value in the DSL.
Because the `value:` option is present, a new value will be set.
You may also pass any other option listed in the
[input option reference](#input-options).
#### Reading Inputs
When you call `input('some_name')`, with or without additional options, the value of the input will be resolved and returned.
Note that this process may involve sourcing the value from another provider, using the value set in DSL, or overriding
the value provided in the same call.
```ruby
# You can use the value in a Ruby variable
some_var = input('some_input_name')
# Or more directly in a resource parameter
describe file(input('important_path')) do
it { should exist }
end
# Or as the resource itself (this could be a string, here)
describe input('some_setting') do
it { should cmp 'correct_value' }
end
# Or as the expected value
describe file('/etc/httpd/httpd.conf') do
its('owner') { should_not cmp input('webserver_user') }
end
```
The value returned can be used anywhere a Ruby value is used.
### Plugins
You can also set inputs using custom input plugins, which retrieve values from external sources like secret stores or databases. Please check [RubyGems.org](https://rubygems.org/) for available InSpec input plugins.
#### Disabling Caching
Especially with plugins, you may want to re-evaluate inputs every time and not cache them.
By default, an existing input value is reused which can lead to problems if the retrieved values are expected to change.
An example for this is using `kitchen-inspec` with input plugins to connect to a Vault server for password retrieval.
To disable input caching, you can disable the cache from your Ruby code:
```ruby
Inspec::InputRegistry.instance.cache_inputs = false
```
## Input options
`name`
: The input name.
Required
Date type: `String`.
Allowed in: all input methods.
When used in control code and `inspec.yml` file, the name is unique within the
current profile. When used in CLI input files, and kitchen-inspec,
the input is copied across all profiles using the same name.
`description`
: Human-meaningful explanation of the input.
Optional
Data type: `String`
Allowed in: control code, `inspec.yml` file
`value`
: The value that will be available when you read the input.
See the [Reading Inputs](#reading-inputs-in-control-dsl) section for more information.
Optional
Data type: any Ruby or YAML type
Allowed in: all input methods.
`type`
: If provided, Inspec will check the value of the input to see if it's of the corresponding type.
Note that `Regexp` indicates that the input value itself should be a regular expression, not that it should
match any particular regular expression.
Optional
Data type: `String`
Allowed values:
- `String`
- `Numeric`
- `Regexp`
- `Array`
- `Hash`
- `Boolean`
- `Any`
Allowed in: control code, `inspec.yml` file
`required`
: If `true`, a control using the input will be failed
if it [reads](#reading-inputs) the value when none has been set.
Optional
Data type: Boolean
Allowed values: `true` or `false`.
Allowed in: control code, `inspec.yml` file
`priority`
: Higher values have higher precedence.
For more information, see the [input priority documentation](#input-priority).
Optional
Data type: `Integer`
Allowed values: 0-100
Allowed in: control code, `inspec.yml` file
`profile`
: Optional
Data type: `String`.
Sets an input in another profile from your profile.
Allowed in: control code, `inspec.yml` file
`sensitive`
: Optional
Date type: `true` or `false`.
If `true`, the value of the input will be used normally
during the `exec` run, but the value will be obscured as "***" in the "inputs" or
"attributes" section of any [Reporter](/inspec/reporters/) that explicitly lists
inputs (the `json` reporter is one such reporter). Note that this will not obscure
input values that are used as test results.
Allowed in: `inspec.yml` file
`pattern`
: Validates the input by matching it with the provided regular expression.
Optional
Date type: `Regexp`.
Allowed in: control code, `inspec.yml` file
## Input priority
The following table lists the *default* priority for input methods in order from highest priority (50) to lowest priority (20).
| Input Provider | Priority | May change priority |
| --------------------------------------- | -------- | ------------------- |
| CLI `--input` option | 50 | No |
| inspec-kitchen `inputs:` section | 40 | No |
| CLI `--input-file` option | 40 | No |
| `inspec.yml` file in a wrapper cookbook | 35 | Yes |
| `inspec.yml` file | 30 | Yes |
| Inline control code | 20 | Yes |
### Priority override
An input can have multiple assignments with varying priority values.
When Chef InSpec evaluates an input, it determines the input value by finding the setting event with the highest priority.
You can set a priority using the [`priority` option](#input-options) in the following input methods:
- `inspec.yml` metadata file
- Control code
For example, to set a priority of 50 in an `inspec.yml` metadata file, use:
```yaml
inputs:
- name: very_important_input
value: 12
priority: 50
```
To set a priority in control code, use:
```ruby
input('also_important', value: 42, priority: 45)
```
### Priority debugging
If it's difficult to determine why InSpec is using a particular priority value, you can use the Event Log to determine what is happening.
First, use the `input_object()` DSL method.
This method is like `input()` in that it looks up an input, but instead of evaluating the current value, it returns the underlying `Inspec::Input` object.
```ruby
puts input_object('troublesome_input').diagnostic_string
```
Or
```ruby
require 'pp'
pp input_object('troublesome_input').events
```
`diagnostic_string` assembles the Event Log into a printable log message for
convenience.
The Event Log contains entries for every time that the value changed, as well as
one for when the input was first created. When possible, stack probing is used
to determine file and line numbers. Most importantly, you will see priority numbers;
remember that highest priority wins; order only matters to break a tie.
## InSpec Attributes
When originally introduced, the Input facility was named *Attributes*. This name
was problematic, because:
- The Chef Infra tool uses the same word to describe its parameterization system.
- Chef Infra attributes have a completely different and much more complex precedence system.
- This caused confusion about passing Chef Infra attributes into InSpec when using Audit Cookbook and kitchen-inspec.
Based on these concerns, InSpec attributes have been renamed to InSpec inputs in Chef InSpec v4.
Support for using the DSL keyword `attribute()`, the metadata field `attributes:`, and the corresponding kitchen-inspec and audit cookbook values are anticipated to continue through Chef InSpec v5.

View file

@ -0,0 +1,138 @@
+++
title = "inspec.yml File"
draft = false
gh_repo = "inspec"
aliases = ["/inspec/profiles/inspec_yaml"]
[menu]
[menu.inspec]
title = "inspec.yml"
identifier = "inspec/profiles/inspec.yml"
parent = "inspec/profiles"
weight = 20
+++
The `inspec.yml` metadata file describes a profile. This file is required.
## Parameters
The `inspec.yml` file defines the following information:
`name`
: A unique name for the profile.
Required
`title`
: A human-readable name for the profile.
Optional
`maintainer`
: The profile maintainer.
Optional
`copyright`
: The copyright holder.
Optional
`copyright_email`
: The support contact information for the profile, typically an email address.
Optional
`license`
: The license for the profile.
Optional
`summary`
: A one line summary for the profile.
Optional
`description`
: A multiple line description of the profile.
Optional
`version`
: The profile version.
Optional
`inspec_version`
: The SemVer version of Chef InSpec that the profile can run under.
Optional
`supports`
: A list of [supported platform](/inspec/profiles/platforms/) targets.
Optional
`depends`
: A list of [profile dependencies](/inspec/profiles/depends/).
Optional
`inputs`
: A list of [inputs](/inspec/profiles/inputs) you can use in your controls.
Optional
`gem_dependencies`
: A list of profile [gem dependencies](/inspec/profiles/depends/#gem-dependencies) that must be installed for the profile to function correctly.
Optional
### Example
```yaml
name: ssh
title: Basic SSH
maintainer: Chef Software, Inc.
copyright: Chef Software, Inc.
copyright_email: support@chef.io
license: Proprietary, All rights reserved
summary: Verify that SSH Server and SSH Client are configured securely
version: 1.0.0
supports:
- platform-family: linux
inputs:
- name: input_name
required: true
description: 'Input description.'
value: 10
priority: 50
depends:
- name: profile
path: ../path/to/profile
gem_dependencies:
- name: "gem-name"
version: ">= 2.0.0"
inspec_version: "~> 2.1"
```
### Embedded ERB
The `inspec.yml` also supports embedded ERB.
```yaml
name: dummy
title: InSpec Profile
maintainer: The Authors
copyright: The Authors
copyright_email: you@example.com
license: Apache-2.0
summary: An InSpec Compliance Profile
version: 0.1.0
depends:
- name: inherit
url: "https://artifactory.com/artifactory/example-repo-local/inspec/0.4.1.tar.gz"
username: <%= ENV['USERNAME'] %>
password: <%= ENV['API_KEY'] %>
```

View file

@ -0,0 +1,89 @@
+++
title = "InSpec Profile Platform Support"
draft = false
gh_repo = "inspec"
[menu]
[menu.inspec]
title = "Platforms"
identifier = "inspec/profiles/platforms"
parent = "inspec/profiles"
weight = 90
+++
Use the `supports` setting in the [`inspec.yml` file](/inspec/profiles/inspec_yml/) to specify one (or more) platforms for which a profile is targeting. The list of supported platforms may contain the following:
- Use `platform-family` to restrict to a specific platform family.
- Use `platform-name` to restrict on a specific platform name. `platform-name` supports asterisk (`*`) wildcard use.
- Use `release` to restrict to a specific platform version, and use together with `platform-name`. `release` supports asterisk (`*`) wildcard use.
- Use `platform` to restrict on either platform-name or platform-family.
To get a list of all valid values for `platform-name` and `platform-family`, run `inspec schema platforms`, which returns the supported list in JSON format.
For compatibility we support `os-name` and `os-family`. We recommend all users
to change `os-name` to `platform-name` and `os-family` to `platform-family`.
With Chef InSpec 2.0, we introduced new families to help distinguish the cloud
platforms. The new families can restrict the platform family to `os`, `aws`, `azure` or `gcp`.
For example, to target anything running Debian Linux, use:
```yaml
name: ssh
supports:
- platform-name: debian
```
To target only Ubuntu version 20.04, use:
```yaml
name: ssh
supports:
- platform-name: ubuntu
release: 20.04
```
To target the entire release of Ubuntu version 20.x, use:
```yaml
name: ssh
supports:
- platform-name: ubuntu
release: 20.*
```
To target the Red Hat and derivative platforms such as CentOS and Oracle Linux, use:
```yaml
name: ssh
supports:
- platform-family: redhat
```
To target the entire Windows 2019 platform family, including Datacenter and Core Servers, use:
```yaml
name: ssh
supports:
- platform-name: windows_server_2019*
```
To target anything running on Amazon AWS, use:
```yaml
name: ssh
supports:
- platform: aws
```
To target all of these examples in a single `inspec.yml` file, use:
```yaml
name: ssh
supports:
- platform-name: debian
- platform-name: ubuntu
release: 20.04
- platform-family: redhat
- platform: aws
```

View file

@ -0,0 +1,193 @@
+++
title = "Signed InSpec Profiles"
draft = false
gh_repo = "inspec"
aliases = ['/inspec/signing/']
[menu]
[menu.inspec]
title = "Signed Profiles"
identifier = "inspec/profiles/Signed profiles"
parent = "inspec/profiles"
weight = 100
+++
This page documents how to make and use signed InSpec profiles.
A signed profile, or `.iaf` file, is an InSpec profile with a digital signature that attests to its authenticity.
Progress Chef-authored profiles are available as signed profiles starting in 2022.
IAF files are not human-readable, but you can view them using `inspec export`. Support for IAF v2.0 was added to InSpec 5.
## How does profile signing work?
Profile signing uses a matched pair of keys. The _signing key_ is secret and is used to sign the profile. The _validation key_ is widely distributed and verifies the signed profile signature.
Keypairs are first searched for in the current directory and then in the user's `~/.inspec/keys` directory.
Progress Chef validation keys are also distributed in the `etc/keys` directory of the InSpec installation tree.
Finally, if a validation key is not found, the profile verification system attempts to download keys from the [InSpec Github](https://github.com/inspec/inspec/tree/main/etc/keys) repository.
## Execute a signed profile
You can execute a signed profile like any other profile.
```bash
$ inspec exec simple.iaf
Profile: InSpec Profile (simple)
Version: 0.1.0
Target: local://
Target ID: 46f308fc-7ad8-4230-8dd0-f2582227e164
✔ tmp-1.0: Create /tmp directory
✔ File /tmp is expected to be directory
File /tmp
✔ is expected to be directory
Profile Summary: 1 successful control, 0 control failures, 0 controls skipped
Test Summary: 2 successful, 0 failures, 0 skipped
```
A signed profile is checked for validity before it's executed. If the profile cannot be verified, then InSpec exits with `code 5` (bad signature).
## Identify key used to sign profile
The `inspec sign verify` command displays which key is used to sign a profile.
```bash
$ inspec sign verify simple-0.1.0-v2.iaf
Verifying simple-0.1.0-v2.iaf
Detected format version 'INSPEC-PROFILE-2'
Attempting to verify using key 'cwolfe-03'
Profile is valid.
```
## See contents of signed profile
Use the `inspec export` command to examine a signed profile's contents. You must be able to verify the profile in order to export the contents. By default, the `export` command dumps a profile summary in a human-readable YAML format, including most of the metadata and the control IDs, control source code, inputs, and other profile information.
- To view a **signed profile**, run:
```bash
$ inspec export simple-0.1.0.iaf
---
:name: simple
:title: InSpec Profile
:maintainer: The Authors
:copyright: The Authors
:copyright_email: you@example.com
:license: Apache-2.0
:summary: An InSpec Compliance Profile
:version: 0.1.0
:supports:
- :platform: os
:controls:
- :title:
:desc:
:descriptions: {}
:impact: 0.5
:refs: []
:tags: {}
:code: ''
:source_location:
:ref: "/Users/cwolfe/sandbox/inspec/inspec-5/lib/inspec/control_eval_context.rb"
:line: 92
:id: "(generated from example.rb:6 7007cd4757c4892cc89977e9847c1051)"
- :title: Create /tmp directory
:desc: An optional description...
:descriptions:
:default: An optional description...
:impact: 0.7
:refs: []
:tags: {}
:code: |
control "tmp-1.0" do # A unique ID for this control
impact 0.7 # The criticality, if this control fails.
title "Create /tmp directory" # A human-readable title
desc "An optional description..."
describe file("/tmp") do # The actual test
it { should be_directory }
end
end
:source_location:
:ref: controls/example.rb
:line: 11
:id: tmp-1.0
:groups:
- :title: sample section
:controls:
- "(generated from example.rb:6 7007cd4757c4892cc89977e9847c1051)"
- tmp-1.0
:id: controls/example.rb
:inputs: []
:sha256: c1a5298d56f028386edf4c52573264ca38d476ce6156a053a2c412991fb0b646
:status_message: ''
:status: loaded
:generator:
:name: inspec
:version: 5.14.5
```
- To view a profile's **README**, run:
```bash
$ inspec export --what readme simple-0.1.0.iaf
# Example InSpec Profile
This example shows the implementation of an InSpec profile.
```
- To view a **signed profile's metadata file (inspec.yml)**, run:
```bash
$ inspec export --what metadata simple-0.1.0.iaf
name: simple
title: InSpec Profile
maintainer: The Authors
copyright: The Authors
copyright_email: you@example.com
license: Apache-2.0
summary: An InSpec Compliance Profile
version: 0.1.0
supports:
platform: os
```
## Mandatory profile signing
**Chef InSpec 6** and above has an optional setting that requires that all profiles are signed.
If mandatory profile signing is enabled, InSpec will not execute functions with an un-signed profile and exits with exit code 6.
To enable mandatory profile signing, set the environment variable `CHEF_PREVIEW_MANDATORY_PROFILE_SIGNING` to any non-empty value.
If you need to bypass mandatory profile signing, use the `--allow-unsigned-profiles` CLI option or set the `CHEF_ALLOW_UNSIGNED_PROFILES` environment variable.
## Advanced Usage
### Create a signing and validation keys
Most users of signed profiles need not create keys of their own unless they wish to sign and distribute profiles themselves.
To generate keys of your own, use the `inspec sign generate-keys` command:
```bash
$ inspec sign generate-keys --keyname test-03
Generating keys
Generating signing key in /Users/cwolfe/.inspec/keys/test-03.pem.key
Generating validation key in /Users/cwolfe/.inspec/keys/test-03.pem.pub
```
Keep your signing key secret. You must devise a way of distributing the validation key to your profile users; they will be unable to use your signed IAF files unless they have the validation key.
### Sign profile
You will need a signing key to sign profiles. Specify the path of profile and the name of the key.
```bash
$ inspec sign profile simple --keyname test-03
Signing simple with key cwolfe-03
Dependencies for profile simple successfully vendored to /Users/cwolfe/sandbox/inspec/inspec-5/temp/simple/vendor
Successfully generated simple-0.1.0.iaf
```

View file

@ -3,16 +3,70 @@ title = "Chef InSpec Profile Style Guide"
draft = false
gh_repo = "inspec"
aliases = ['/inspec/style/']
[menu]
[menu.inspec]
title = "Profile Style Guide"
identifier = "inspec/reference/style.md Profile Style Guide"
parent = "inspec/reference"
weight = 80
identifier = "inspec/profiles/style"
parent = "inspec/profiles"
weight = 100
+++
This is a set of recommended Chef InSpec rules you should use when writing controls.
## "should" vs. "expect" syntax
Users familiar with the RSpec testing framework may know that there are two ways
to write test statements: `should` and `expect`. The RSpec community decided that
`expect` is the preferred syntax. However, Chef InSpec recommends the `should`
syntax as it tends to read more easily to those users who are not as technical.
Chef InSpec will continue to support both methods of writing tests. Consider
this `file` test:
```Ruby
describe file('/tmp/test.txt') do
it { should be_file }
end
```
This can be re-written with `expect` syntax
```Ruby
describe file('/tmp/test.txt') do
it 'should be a file' do
expect(subject).to(be_file)
end
end
```
The output of both of the above examples looks like this:
```bash
File /tmp/test.txt
✔ should be a file
```
In addition, you can make use of the `subject` keyword to further control your
output if you choose:
```Ruby
describe 'test file' do
subject { file('/tmp/test.txt') }
it 'should be a file' do
expect(subject).to(be_file)
end
end
```
... which will render the following output:
```bash
test file
✔ should be a file
```
## Control Files
### Place control files in `controls/` and end them with `.rb`

View file

@ -6,22 +6,25 @@ gh_repo = "inspec"
[menu]
[menu.inspec]
title = "Reporters"
identifier = "inspec/reference/reporters.md Reporters"
parent = "inspec/reference"
weight = 50
identifier = "inspec/Reporters"
parent = "inspec"
weight = 100
+++
A `reporter` is a facility for formatting and delivering the results of a Chef InSpec auditing run. Reporters were introduced in Chef InSpec 1.51.6.
A Chef InSpec reporter formats and delivers the results of a Chef InSpec audit run. You can output the results of your audits to more than one reporter.
Chef InSpec allows you to output your test results to one or more reporters.
## Configure
Configure the reporter(s) using the `--reporter` option or as part of the general configuration file using the `--config` (or `--json-config`, prior to v3.6) option. Both the --reporter and --config options may be used, in which case the options are merged. While you can configure multiple reporters to write to different files, only one reporter can output to the screen(stdout).
Configure the reporter(s) using the `--reporter` option or as part of the general configuration file using the `--config` option.
## Syntax
You can use both the `--reporter` and `--config` options, in which case the options are merged.
While you can configure multiple reporters to write to different files, only one reporter can output to the screen(stdout).
### reporter option
You can specify one or more reporters using the `--reporter` CLI flag. You can also specify an output by appending a path separated by a colon.
**Output json to screen**
**Output JSON to screen**
```bash
inspec exec example_profile --reporter json
@ -29,7 +32,7 @@ inspec exec example_profile --reporter json
inspec exec example_profile --reporter json:-
```
**Output yaml to screen.**
**Output YAML to screen.**
```bash
inspec exec example_profile --reporter yaml
@ -37,19 +40,19 @@ inspec exec example_profile --reporter yaml
inspec exec example_profile --reporter yaml:-
```
**Output cli to screen and write json to a file.**
**Output CLI to screen and write JSON to a file.**
```bash
inspec exec example_profile --reporter cli json:/tmp/output.json
```
**Output nothing to screen and write junit and html to a file.**
**Output nothing to screen and write JUnit and HTML to a file.**
```bash
inspec exec example_profile --reporter junit2:/tmp/junit.xml html:www/index.html
```
**Output json to screen and write to a file. Write junit to a file.**
**Output JSON to screen and write to a file. Write JUnit to a file.**
```bash
inspec exec example_profile --reporter json junit2:/tmp/junit.xml | tee out.json
@ -61,9 +64,18 @@ If you wish to pass the profiles directly after specifying the reporters, you mu
inspec exec --reporter json junit2:/tmp/junit.xml -- profile1 profile2
```
Using the CLI option `--config`, you can also set reporters.
**Output real-time progress to screen with a progress bar.**
**Output cli to screen.**
```bash
inspec exec example_profile --reporter progress-bar
```
### config file
You can also set reporters using a configuration file.
For guidance on creating and using a config file, see the [InSpec config documentation](/inspec/config/).
**Output CLI to screen.**
```json
{
@ -75,7 +87,7 @@ Using the CLI option `--config`, you can also set reporters.
}
```
**Output cli to screen and write json to a file.**
**Output CLI to screen and write JSON to a file.**
```json
{
@ -91,31 +103,52 @@ Using the CLI option `--config`, you can also set reporters.
}
```
**Output real-time progress to screen with a progress bar.**
## Options
```bash
inspec exec example_profile --reporter progress-bar
```
## Reporter Options
The following are CLI options that are used to modify reporter behavior. Many of these options allow you to limit the report size because some reporters (such as the json-automate reporter) limit on the total size of the report that can be processed.
The following are CLI options that are used to modify reporter behavior.
Many of these options allow you to limit the report size because some reporters (such as the json-automate reporter) limit on the total size of the report that can be processed.
`--diff`, `--no-diff`
: Include a `diff` comparison of textual differences in the failed test output (default: `true`).
: Include a `diff` comparison of textual differences in the failed test output.
Use `--no-diff` to limit the size of the report output when tests contain large amounts of text output.
Default: `true`
`--enhanced-outcomes`
: Includes enhanced outcome of controls in report data.
The control level status outcomes are:
- `Passed`
- `Failed`
- `Not Applicable (N/A)`
- `Not Reviewed (N/R)`
- `Error (ERR)`.
Supported with the following reporters:
- automate
- cli
- html2
- json
- json-automate
- progress-bar
- yaml
: Use `--no-diff` to limit the size of the report output when tests contain large amounts of text output.
`--filter-empty-profiles`
: Remove empty profiles (those containing zero controls, such as resource packs) from the reporter's output.
`--reporter-backtrace-inclusion`, `--no-reporter-backtrace-inclusion`
`--reporter-backtrace-inclusion`
`--no-reporter-backtrace-inclusion`
: Include a code backtrace in report data (default: `true`).
: Include a code backtrace in report data.
: The `--no-reporter-backtrace-inclusion` option may be used to limit report size when large code stack traces are present in the output.
The `--no-reporter-backtrace-inclusion` option may be used to limit report size when large code stack traces are present in the output.
Default: `true`
`--reporter-include-source`
@ -123,89 +156,75 @@ The following are CLI options that are used to modify reporter behavior. Many of
`--reporter-message-truncation=N`
: Number of characters to truncate failure messages in report data (default: no truncation).
: Number of characters to truncate failure messages in report data.
: This may be used to limit the size of reports when failure messages are exceptionally large.
This may be used to limit the size of reports when failure messages are exceptionally large.
`--enhanced-outcomes`
Default: no truncation
: Includes enhanced outcome of controls in report data.
## Reporters
: The control level status outcomes are `Passed`, `Failed`, `Not Applicable (N/A)`, `Not Reviewed (N/R)`, or `Error (ERR)`.
The following are the supported reporters.
: Only supported for cli, progress-bar, html2, json, json-automate, automate, and yaml reporters.
### automate
## Supported Reporters
The `automate` reporter type is a special reporter which sends its results over the network to [Chef Automate]({{< relref "/automate/">}}). To use this reporter, you must pass in the correct configuration via a JSON configuration `--config`.
The following are the currently supported reporters:
Example Configuration:
```json
{
"reporter": {
"automate" : {
"stdout" : false,
"url" : "https://AUTOMATE_URL/data-collector/v0/",
"token" : "AUTOMATE_ADMIN_TOKEN",
"insecure" : true,
"node_name" : "inspec_test_node",
"environment" : "prod"
}
}
}
```
#### Mandatory fields
`stdout`
: Either suppress or shows the automate report in the CLI screen on completion.
`url`
: Chef Automate. Append `data-collector/v0/` at the end.
`token`
: Chef Automate tokens. You can generate this token by navigating to the **admin** tab of Automate and then clicking **API keys**.
#### Optional fields
`insecure`
: Disables or enables the SSL check when accessing the Chef Automate instance.
`node_name`
: Node name which shows up in Chef Automate.
`node_uuid`
: Node UUID, which shows up in Chef Automate. Use a single static UUID per node for all your reports. You must specify a `node_uuid` in the Chef InSpec configuration file if running Chef InSpec outside of an audit cookbook or another environment where a `chef_guid` or `node_uuid` is already known to Chef InSpec.
`environment`
: Sets the environment metadata for Chef Automate.
### cli
This is the basic text based report. It includes details about tests that passed and failed and an overall summary at the end.
### json
This reporter includes all information about the profiles and test results in standard JSON format. You may optionally pass through arbitrary structured JSON data by setting a JSON configuration with the `--config` parameter.
For example:
```json
{
"reporter": {
"json": {
"stdout": true,
"passthrough": {
"a": 1,
"b": false
}
}
}
}
```
### json-min
This reporter is a redacted version of the json and only includes test results.
### yaml
This reporter includes all information about the profiles and test results in standard yaml format.
### documentation
This reporter is a very minimal text base report. It shows you which tests passed by name and has a small summary at the end.
### junit2
This reporter outputs the standard JUnit spec in XML format and is recommended for all new users of JUnit.
#### junit
This legacy reporter outputs nonstandard JUnit XML and is provided only for backward compatibility.
### progress
This reporter is very condensed and provides you a `.`(pass), `f`(fail), or `*`(skip) character per test and a small summary at the end.
### progress-bar
This reporter outputs the real-time progress of a running InSpec profile using a progress bar and prints the running control's ID with an indicator of the control's status (`Passed`, `failed`, or `skipped`).
For example:
![Progress Bar Reporter Outcome](/images/inspec/reporter_outcome_progress_bar.png)
And reporter outcome with `--enhanced-outcomes` option:
![Progress Bar Reporter Outcome with enhanced outcomes](/images/inspec/reporter_outcome_progress_bar_enhanced_outcomes.png)
### json-rspec
This reporter includes all information from the Rspec runner. Unlike the json reporter, this includes Rspec-specific details.
This reporter is a very minimal text-based report. It shows you which tests passed by name and has a small summary at the end.
### html
This reporter is the legacy RSpec HTML reporter retained for backward compatibility. The report generated is unaware of profiles or controls and only contains unsorted test information. Most users should migrate to the `html2` reporter for more complete data.
This reporter is the legacy RSpec HTML reporter retained for backward compatibility.
The report generated is unaware of profiles or controls and only contains unsorted test information.
Most users should migrate to the `html2` reporter for more complete data.
### html2
@ -237,53 +256,27 @@ Specifies the full path to the location of a CSS file that is read and inlined i
Specifies the full path to the location of a JavaScript file that is read and inlined into the HTML report. The default JavaScript is included. The JavaScript file should implement at least a `pageLoaded()` function, which is called by the `onload` event of the HTML `body` element.
## Automate Reporter
### json
The `automate` reporter type is a special reporter which sends its results over the network to [Chef Automate]({{< relref "/automate/">}}). To use this reporter, you must pass in the correct configuration via a json configuration `--config`.
This reporter includes all information about the profiles and test results in standard JSON format. You may optionally pass through arbitrary structured JSON data by setting a JSON configuration with the `--config` parameter.
Example Configuration:
For example:
```json
{
"reporter": {
"automate" : {
"stdout" : false,
"url" : "https://YOUR_A2_URL/data-collector/v0/",
"token" : "YOUR_A2_ADMIN_TOKEN",
"insecure" : true,
"node_name" : "inspec_test_node",
"environment" : "prod"
"json": {
"stdout": true,
"passthrough": {
"a": 1,
"b": false
}
}
}
}
```
### Mandatory fields
`stdout`
: Either suppress or shows the automate report in the CLI screen on completion.
`url`
: Automate 2 url. Append `data-collector/v0/` at the end.
`token`
: Automate 2 tokens. You can generate this token by navigating to the **admin** tab of A2 and then clicking **API keys**.
### Optional fields
`insecure`
: Disables or enables the SSL check when accessing the Automate 2 instance.
`node_name`
: Node name which shows up in Automate.
`node_uuid`
: Node UUID, which shows up in Chef Automate. Use a single static UUID per node for all your reports. You must specify a `node_uuid` in the Chef InSpec configuration file if running Chef InSpec outside of an audit cookbook or another environment where a `chef_guid` or `node_uuid` is already known to Chef InSpec.
`environment`
: Sets the environment metadata for Automate.
## json-Automate Reporter
### json-automate
The `json-automate` reporter is a special reporter that prepares the data format used by the Automate reporter. `json-automate` does not communicate on the network; instead, it simply produces the JSON report format that Automate would be consuming. Notably, the report is based on the `json` reporter, with the following modifications:
@ -291,3 +284,39 @@ The `json-automate` reporter is a special reporter that prepares the data format
- Child profiles are deleted, flattening the report.
The `json-automate` reporter is primarily used for internal needs, but some users may find it helpful if they want a JSON-based reporter that merges controls.
### json-min
This reporter is a redacted version of the JSON and only includes test results.
### json-rspec
This reporter includes all information from the Rspec runner. Unlike the JSON reporter, this includes Rspec-specific details.
### junit
This legacy reporter outputs nonstandard JUnit XML and is provided only for backward compatibility. New JUnit users should use the junit2 reporter.
### junit2
This reporter outputs the standard JUnit spec in XML format. New JUnit users should use this reporter instead of the legacy junit reporter.
### progress
This reporter is very condensed and provides you a `.`(pass), `f`(fail), or `*`(skip) character per test and a small summary at the end.
### progress-bar
This reporter outputs the real-time progress of a running InSpec profile using a progress bar and prints the running control's ID with an indicator of the control's status (`Passed`, `failed`, or `skipped`).
For example:
![Progress Bar Reporter showing outcome of tests in CLI output.](/images/inspec/reporter_outcome_progress_bar.png)
And reporter outcome with `--enhanced-outcomes` option:
![Progress Bar Reporter showing outcome of tests in CLI output with enhance output.](/images/inspec/reporter_outcome_progress_bar_enhanced_outcomes.png)
### yaml
This reporter includes all information about the profiles and test results in standard yaml format.

View file

@ -6,12 +6,12 @@ gh_repo = "inspec"
[menu]
[menu.inspec]
title = "InSpec Shell"
identifier = "inspec/reference/shell.md Chef InSpec Shell"
parent = "inspec/reference"
weight = 110
identifier = "inspec/Chef InSpec Shell"
parent = "inspec"
weight = 70
+++
The Chef InSpec interactive shell is a pry based REPL that can be used to
The Chef InSpec interactive shell is a pry-based REPL that can be used to
quickly run Chef InSpec controls and tests without having to write it to a
file. Its functionality is similar to [chef-shell](/chef_shell/) as it provides a way
to exercise the Chef InSpec Language, its resources, tests, and plugins without
@ -20,14 +20,13 @@ having to create a profile or write a test file. See
do.
See [Explore Chef InSpec resources](https://learn.chef.io/modules/explore-inspec-resources#/)
on Learn Chef Rally for a hands-on example that uses Chef InSpec shell.
on Learn Chef for a hands-on example that uses Chef InSpec shell.
## Launching the shell
## Launch the shell
If you are using Chef InSpec from a platform-specific package (rpm, msi,
etc.) or from a Chef prepared shell in Chef Workstation, you can directly launch
Chef InSpec shell against your local machine using the following. See
<https://docs.chef.io/install_dk.html#set-system-ruby> for details.
Chef InSpec shell against your local machine using the `inspec shell` command.
```bash
inspec shell
@ -77,10 +76,10 @@ Once inside the shell your resource will be available:
inspec> example_config
```
## Using Ruby in Chef InSpec shell
## Use Ruby
Since Chef InSpec shell is pry based, you may treat the shell as an
interactive Ruby session. You may write Ruby expressions and evaluate
Since Chef InSpec shell is pry based, you can treat the shell as an
interactive Ruby session. You can 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`.
@ -95,12 +94,12 @@ inspec> 1 + 2
inspec> exit
```
## Using Chef InSpec Language in Chef InSpec shell
## Use InSpec DSL
Chef InSpec shell will automatically evaluate the result of every command as
The Chef InSpec shell automatically evaluates the result of every command as
if it were a test file. If you type in a Ruby command that is not an
Chef InSpec control or test, the shell will evaluate it as if it were a
regular ruby command.
regular Ruby command.
Bare Chef InSpec resources are instantiated and their help text is presented.
You may also access the resource contents or other matchers that they
@ -167,10 +166,10 @@ inspec> end
Summary: 0 successful, 1 failures, 0 skipped
```
## Running a single Chef InSpec command
## Run InSpec commands
If you wish to run a single Chef InSpec command and fetch its results, you
may use the `-c` flag. This is similar to using `bash -c`.
You can run a single Chef InSpec command and fetch its results using the `-c` flag.
This is similar to using `bash -c`.
```bash
$ inspec shell -c 'describe file("/Users/username") do it { should exist } end'
@ -232,15 +231,15 @@ $ inspec shell --format json -c 'describe file("/Users/test") do it { should exi
}
```
## Running Chef InSpec Shell With Inputs
## Set inputs
With InSpec [profiles that support inputs]({{< relref "inputs/#which-profiles-support-inputs" >}}),
you can set inputs using the InSpec `shell` command. This allows you to work more consistently with
InSpec profiles when switching between the `shell` and `exec` commands.
With InSpec [profiles that support inputs]({{< relref "/inspec/profiles/inputs#profile-support" >}}),
you can set inputs using the InSpec `shell` command.
This allows you to work more consistently with InSpec profiles when switching between the `shell` and `exec` commands.
For more details on inputs, see the [inputs reference](/inspec/inputs/).
For more details on inputs, see the [inputs reference](/inspec/profiles/inputs/).
### Set Inputs with Command-line Options
### Set inputs with command-line options
The `shell` command accepts one or more inputs in the command line as single-quoted YAML or JSON structures.
@ -264,7 +263,7 @@ Test Summary: 1 successful, 0 failures, 0 skipped
inspec> exit
```
### Set Inputs with YAML File
### Set inputs with YAML file
You can also save inputs and values to one or more YAML files and pass them to `shell` in the command line.
For example:

View file

@ -1,193 +0,0 @@
+++
title = "Signed InSpec Profiles"
draft = false
gh_repo = "inspec"
[menu]
[menu.inspec]
title = "Signed InSpec Profiles"
identifier = "inspec/reference/signing.md Signed InSpec Profiles"
parent = "inspec/reference"
weight = 60
+++
This page documents the `inspec sign` command introduced in InSpec 5, the mandatory profile signing feature introduced in InSpec 6, and details some methods to work with signed profiles.
## Usage
### What is a Signed Profile?
A signed profile, or `.iaf` file, is an InSpec profile with a digital signature that attests to its authenticity. Progress Chef authored profiles are available as signed profiles starting from 2022.
IAF files are not human-readable, but may be viewed using `inspec export`. Support for IAF v2.0 was added to InSpec 5.
### Mandatory profile signing
**Chef InSpec 6** and above has an optional setting that requires that all profiles are signed.
If mandatory profile signing is enabled, InSpec will not execute functions with an un-signed profile and exits with exit code 6.
To enable mandatory profile signing, set the environment variable `CHEF_PREVIEW_MANDATORY_PROFILE_SIGNING` to any non-empty value.
If you need to bypass mandatory profile signing, use the `--allow-unsigned-profiles` CLI option or set the `CHEF_ALLOW_UNSIGNED_PROFILES` environment variable.
### How does Profile Signing Work?
Profile signing uses a matched pair of keys. The _signing key_ is secret and is used to sign the profile. The _validation key_ is widely distributed and verifies the signed profile signature.
Keypairs are first searched for in the current directory and then in the user's `~/.inspec/keys` directory. Progress Chef validation keys are also distributed in the `etc/keys` directory of the InSpec installation tree. Finally, if a validation key is not found, the profile verification system attempts to download keys from the [InSpec Github](https://github.com/inspec/inspec/tree/main/etc/keys) repository.
### How do I execute a signed profile?
You can execute a signed profile like any other profile.
```bash
[cwolfe@lodi temp]$ inspec exec simple.iaf
Profile: InSpec Profile (simple)
Version: 0.1.0
Target: local://
Target ID: 46f308fc-7ad8-4230-8dd0-f2582227e164
✔ tmp-1.0: Create /tmp directory
✔ File /tmp is expected to be directory
File /tmp
✔ is expected to be directory
Profile Summary: 1 successful control, 0 control failures, 0 controls skipped
Test Summary: 2 successful, 0 failures, 0 skipped
```
A signed profile is checked for validity before being executed, and if it cannot be verified, then InSpec exits with `code 5` (bad signature).
### How do I know which key is used to sign a profile?
The `inspec sign verify` command displays which key is used to sign a profile.
```bash
[cwolfe@lodi temp]$ inspec sign verify simple-0.1.0-v2.iaf
Verifying simple-0.1.0-v2.iaf
Detected format version 'INSPEC-PROFILE-2'
Attempting to verify using key 'cwolfe-03'
Profile is valid.
```
### How do I look inside a signed profile?
Use the `inspec export` command to examine a signed profile's contents. You must be able to verify the profile in order to export the contents. By default, the `export` command dumps a profile summary in a human-readable YAML format, including most of the metadata and the control IDs, control source code, inputs, and other profile information.
- To view a **signed profile**, run:
```bash
[cwolfe@lodi temp]$ inspec export simple-0.1.0.iaf
---
:name: simple
:title: InSpec Profile
:maintainer: The Authors
:copyright: The Authors
:copyright_email: you@example.com
:license: Apache-2.0
:summary: An InSpec Compliance Profile
:version: 0.1.0
:supports:
- :platform: os
:controls:
- :title:
:desc:
:descriptions: {}
:impact: 0.5
:refs: []
:tags: {}
:code: ''
:source_location:
:ref: "/Users/cwolfe/sandbox/inspec/inspec-5/lib/inspec/control_eval_context.rb"
:line: 92
:id: "(generated from example.rb:6 7007cd4757c4892cc89977e9847c1051)"
- :title: Create /tmp directory
:desc: An optional description...
:descriptions:
:default: An optional description...
:impact: 0.7
:refs: []
:tags: {}
:code: |
control "tmp-1.0" do # A unique ID for this control
impact 0.7 # The criticality, if this control fails.
title "Create /tmp directory" # A human-readable title
desc "An optional description..."
describe file("/tmp") do # The actual test
it { should be_directory }
end
end
:source_location:
:ref: controls/example.rb
:line: 11
:id: tmp-1.0
:groups:
- :title: sample section
:controls:
- "(generated from example.rb:6 7007cd4757c4892cc89977e9847c1051)"
- tmp-1.0
:id: controls/example.rb
:inputs: []
:sha256: c1a5298d56f028386edf4c52573264ca38d476ce6156a053a2c412991fb0b646
:status_message: ''
:status: loaded
:generator:
:name: inspec
:version: 5.14.5
```
- To view a profile's **README**, run:
```bash
[cwolfe@lodi temp]$ inspec export --what readme simple-0.1.0.iaf
# Example InSpec Profile
This example shows the implementation of an InSpec profile.
```
- To view a **signed profile's metadata file (inspec.yml)**, run:
```bash
[cwolfe@lodi temp]$ inspec export --what metadata simple-0.1.0.iaf
name: simple
title: InSpec Profile
maintainer: The Authors
copyright: The Authors
copyright_email: you@example.com
license: Apache-2.0
summary: An InSpec Compliance Profile
version: 0.1.0
supports:
platform: os
```
## Advanced Usage
### How do I create keys?
Most users of signed profiles need not create keys of their own unless they wish to sign and distribute profiles themselves. To generate keys of your own, use the `inspec sign generate-keys` command:
```bash
[cwolfe@lodi temp]$ inspec sign generate-keys --keyname test-03
Generating keys
Generating signing key in /Users/cwolfe/.inspec/keys/test-03.pem.key
Generating validation key in /Users/cwolfe/.inspec/keys/test-03.pem.pub
[cwolfe@lodi temp]$
```
Keep your signing key secret. You must devise a way of distributing the validation key to your profile users; they will be unable to use your signed IAF files unless they have the validation key.
### How do I sign profiles?
You will need a signing key to sign profiles. Specify the path of profile and the name of the key.
```bash
[cwolfe@lodi temp]$ inspec sign profile simple --keyname test-03
Signing simple with key cwolfe-03
Dependencies for profile simple successfully vendored to /Users/cwolfe/sandbox/inspec/inspec-5/temp/simple/vendor
Successfully generated simple-0.1.0.iaf
[cwolfe@lodi temp]$
```

View file

@ -8,7 +8,7 @@ gh_repo = "inspec"
title = "Troubleshooting"
identifier = "inspec/Troubleshooting"
parent = "inspec"
weight = 55
weight = 120
+++
## Exit code 5

View file

@ -6,17 +6,17 @@ gh_repo = "inspec"
[menu]
[menu.inspec]
title = "Waivers"
identifier = "inspec/reference/waivers.md Waivers"
parent = "inspec/reference"
weight = 140
identifier = "inspec/Waivers"
parent = "inspec"
weight = 110
+++
Waivers allow you to waive controls and to dictate the running and/or reporting of those controls. A waiver file identifies:
1. which controls are waived
1. a description of why it is waived
1. (optionally) whether they should be skipped from running
1. (optionally) an expiration date for the waiver
- which controls are waived
- a description of why it is waived
- (optionally) whether they should be skipped from running
- (optionally) an expiration date for the waiver
## Usage
@ -45,7 +45,7 @@ Specify the following parameters in the waiver file:
`justification` **required**
: A description of the waiver. This might include a reason for the waiver or the person who signed off on the waiver.
### Examples
## Examples
Example in YAML:
@ -78,6 +78,14 @@ Example in JSON:
Example in CSV:
```plain
control_id,justification,run,expiration_date
waiver_control_1_2_3,Not needed until Q3,TRUE,2019-10-15T00:00:00.000Z
xccdf_org.cisecurity.benchmarks_rule_1.1.1.4_Ensure_mounting_of_hfs_filesystems_is_disabled,This might be a bug in the test. @qateam,FALSE,2020-03-01T00:00:00.000Z
```
which looks like this:
| control_id | justification | run | expiration_date |
|---------------------------------------------------------------------------------------------|------------------------------------------|-------|--------------------------|
| waiver_control_1_2_3 | Not needed until Q3 | TRUE | 2019-10-15T00:00:00.000Z |