Skip to content

Commit

Permalink
Merge branch 'main' into post-dec24-updates
Browse files Browse the repository at this point in the history
  • Loading branch information
wdower authored Dec 4, 2024
2 parents 46fbad8 + ae5e727 commit 7a7a378
Show file tree
Hide file tree
Showing 17 changed files with 351 additions and 257 deletions.
6 changes: 3 additions & 3 deletions src/courses/advanced/03.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ InSpec profiles are a set of automated tests that relate back to a security requ

::: details Review

1. NGINX version 1.10.3 or later.
1. NGINX should be installed as version 1.27.0 or later.
2. The following NGINX modules should be installed:
* `http_ssl`
* `stream_ssl`
Expand Down Expand Up @@ -74,7 +74,7 @@ supports:
inputs:
- name: nginx_version
type: String
value: 1.10.3
value: 1.27.0

- name: nginx_modules
type: Array
Expand Down Expand Up @@ -178,7 +178,7 @@ inspec exec my_nginx -t docker://nginx --input-file inputs-linux.yml
Target ID: TARGET_ID
✔ nginx-version: NGINX version
✔ Nginx Environment version is expected to cmp >= "1.10.3"
✔ Nginx Environment version is expected to cmp >= "1.27.0"
✔ nginx-modules: NGINX modules
✔ Nginx Environment modules is expected to include "http_ssl"
✔ Nginx Environment modules is expected to include "stream_ssl"
Expand Down
133 changes: 76 additions & 57 deletions src/courses/beginner/02.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,34 @@ title: 2. What is an InSpec Profile?
author: Aaron Lippold
---

### Check-In
## Check-In

::: details Have you used InSpec before?
There is no right or wrong answer. If this is your first time using InSpec, welcome! If you have used it before, welcome back. If you want more information on the basics of Ruby (InSpec is built on Ruby), take a look at the Ruby materials linked on the [home page](../../).
:::

::: details Which goal of the MITRE Security Automation Framework (SAF) is supported by InSpec?
InSpec is used in the [Validate pillar](https://saf.mitre.org/#/validate). InSpec is used to do security validation.

_Note that InSpec is not the only validation solution, but the one preferred at the SAF. You are not required to use InSpec to use the rest of the SAF nor are you required to use the rest of the SAF to use InSpec._
_Note that InSpec is not the only validation solution, but the one preferred by the MITRE SAF team. You are not required to use InSpec to use the rest of MITRE SAF's approach to security._
:::

::: details Is your Codespace environment set up successfully?
This class will have hands-on activities. We recommend that you use the provided class [development lab environment](https://github.com/mitre/saf-training-lab-environment) to participate in the hands-on activities. All you need is to login with a [GitHub](https://github.com/signup) account (which you can make for free), and follow the directions in the [README.md](https://github.com/mitre/saf-training-lab-environment#readme). To verify that your environment is setup, run `./test-lab.sh`.
This class will have hands-on activities. The class contents are written assuming that you are following along using the recommended [development lab environment](https://github.com/mitre/saf-training-lab-environment), which leverages GitHub Codespaces to give you a stable development VM. All you need is to login with a [GitHub](https://github.com/signup) account (which you can make for free), and follow the directions in the [README.md](https://github.com/mitre/saf-training-lab-environment#readme).

To setup your environment, run `source ./build-lab.sh`. This script will install all of the dependencies we will be using in this class, not the least of which is the executable InSpec binary itself. You can validate that everything is up and running properly by running `./test-lab.sh`. If anything goes wrong or gets misconfigured, you can just run `source ./build-lab.sh` again.
:::

## What is an InSpec Profile?

### InSpec Profiles

InSpec organizes its code into `profiles`. A `profile` is a set of automated tests that usually relates directly back to a Security Requirements Benchmark -- such as a CIS Benchmark or a Defense Information Security Agency (DISA) Security Technical Implementation Guide (STIGs) - and provides an organized structure to articulate that set of requirements using tests in code.
An InSpec profile is a collection of automated tests. In real-world contexts, if we are testing a system for security, we are running tests based off of some security guidance documentation such as a [Center for Internet Security (CIS) Benchmark](https://www.cisecurity.org/cis-benchmarks) or one of the [Defense Information Security Agency (DISA) Security Technical Implementation Guide (STIGs)](https://public.cyber.mil/stigs/). An InSpec profile provides an organized structure to articulate that set of requirements as code.

If you have gone through the [MITRE SAF Guidance Class](../../courses/guidance/README.md), you may recall that a security guidance document can often be expressed as a structured, machine-readable dataset. We like to think of the human-friendly security guidance documentation and the programmatic validation of that guidance via a testing tool such as InSpec as ultimately two different ways of formatting the same data about security requirements.

### The Structure of an InSpec Profile

**Profiles have two (2) required elements:**
An InSpec profile has two required elements:
- An `inspec.yml` file
- A `controls` directory

Expand All @@ -38,71 +44,84 @@ InSpec organizes its code into `profiles`. A `profile` is a set of automated tes

You can learn all the details here: <https://docs.chef.io/inspec/profiles/>

We will be going over each of these during our class.
### InSpec Profile Structure
We will be discussing the purpose and function of each of these elements during this class.


```sh
$ tree nginx
nginx
└── profile
├── README.md
├── inputs.yml
├── controls
│ ├── V-2230.rb
│ └── V-2232.rb
├── files
│ └── services-and-ports.yml
├── inspec.yml
└── libraries
└── nginx_helper.rb
# Example profile structure
nginx
└── profile
├── README.md
├── inputs.yml
├── controls
│ ├── V-2230.rb
│ └── V-2232.rb
├── files
│ └── services-and-ports.yml
├── inspec.yml
└── libraries
└── nginx_helper.rb
```

---

### InSpec Controls Structure
### The Structure of an InSpec Control

Let's start off by taking a glance at what a quality InSpec control looks like when complete. This example is taken from the [InSpec profile](https://github.com/mitre/redhat-enterprise-linux-9-stig-baseline) that the MITRE SAF team developed to assess a Red Hat Enterprise Linux 9 operating system against security guidance documentation coming from a STIG - it could just as well have come from an alternative authority such as a CIS Benchmark.

[redhat-enterprise-linux-9-stig-baseline/controls/SV-257791.rb](https://github.com/mitre/redhat-enterprise-linux-9-stig-baseline/blob/46fd72d144fcda10b07604df037db7f683b74225/controls/SV-257791.rb)

```ruby
control "V-13727" do
title "The worker_processes StartServers directive must be set properly."
```ruby
control 'SV-257791' do
title 'RHEL 9 /boot/grub2/grub.cfg file must be owned by root.'
desc 'The " /boot/grub2/grub.cfg" file stores sensitive system configuration. Protection of this file is critical for system security.'
desc 'check', 'Verify the ownership of the "/boot/grub2/grub.cfg" file with the following command:
desc "These requirements are set to mitigate the effects of several types of
denial of service attacks. Although there is some latitude concerning the
settings themselves, the requirements attempt to provide reasonable limits
for the protection of the web server. If necessary, these limits can be
adjusted to accommodate the operational requirement of a given system."
$ sudo stat -c "%U %n" /boot/grub2/grub.cfg
root /boot/grub2/grub.cfg
If "/boot/grub2/grub.cfg" file does not have an owner of "root", this is a finding.'
desc 'fix', 'Change the owner of the file /boot/grub2/grub.cfg to root by running the following command:
$ sudo chown root /boot/grub2/grub.cfg'
impact 0.5
tag "severity": "medium"
tag "gtitle": "WA000-WWA026"
tag "gid": "V-13727"
tag "rid": "SV-36645r2_rule"
tag "stig_id": "WA000-WWA026 A22"
tag "nist": ["CM-6", "Rev_4"]

tag "check": "To view the worker_processes directive value enter the
following command:
grep ""worker_processes"" on the nginx.conf file and any separate included
configuration files
If the value of ""worker_processes"" is not set to auto or explicitly set,
this is a finding:
worker_processes auto;
worker_processes defines the number of worker processes. The optimal value
depends on many factors including (but not limited to) the number of CPU
cores, the number of hard disk drives that store data, and load pattern. When
one is in doubt, setting it to the number of available CPU cores would be a
good start (the value “auto” will try to autodetect it)."

tag "fix": "Edit the configuration file and set the value of
""worker_processes"" to the value of auto or a value of 1 or higher:
worker_processes auto;"

describe nginx_conf(NGINX_CONF_FILE).params['worker_processes'] do
it { should cmp [['auto']] }
ref 'DPMS Target Red Hat Enterprise Linux 9'
tag check_id: 'C-61532r925358_chk'
tag severity: 'medium'
tag gid: 'V-257791'
tag rid: 'SV-257791r925360_rule'
tag stig_id: 'RHEL-09-212030'
tag gtitle: 'SRG-OS-000480-GPOS-00227'
tag fix_id: 'F-61456r925359_fix'
tag 'documentable'
tag cci: ['CCI-000366']
tag nist: ['CM-6 b']
tag 'host'

only_if('Control not applicable within a container', impact: 0.0) {
!virtualization.system.eql?('docker')
}

grubfile = input('grub_conf_path')

describe file(grubfile) do
it { should exist }
it { should be_owned_by 'root' }
end
end
```

### InSpec Results
An InSpec control includes specific keywords like `control` and `describe` that define and logically organize tests. It will likely also reference some InSpec [Resources](https://docs.chef.io/inspec/resources/): pre-defined classes that model sometimes rather complex parts of software systems that we want to test. These resources expose easy to use APIs for a variety of different constructs. This control invokes the `file` resource, which allows test authors to ask questions about the attributes of a given file on the filesystem.

### What happens when I run a profile?

InSpec controls can be run singularly, but are more commonly run in a group as an entire profile is executed against the system we want to evaluate. The tool can pass output to a variety of destinations - in simple cases, we will direct the output to the terminal's STDOUT, while if we want to save our results to a report, we can pass the report to a visualization tool such as [Heimdall](https://heimdall-lite.mitre.org). We will discuss reporting and visualizing InSpec's output in more detail later.

::: warning READONLY
InSpec controls when written correctly should not make changes to your software system as you ought to only be validating that a security requirement is met. You should be utilizing a different technology to correct anything found to be non-compliant - these technologies are frequently labelled as "infrastructure as code".
:::


#### Failure

Expand Down
81 changes: 57 additions & 24 deletions src/courses/beginner/03.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,48 @@
---
order: 3
next: 04.md
title: 3. Study an InSpec Profile - NGINX Example
title: 3. Studying an InSpec Profile - NGINX Example
author: Aaron Lippold
---

## Studying an InSpec profile

Let's start by creating a profile that will contain NGINX tests.
The best way to learn how an InSpec profile works is to write our own example. Let's start out with a simple profile and start adding more tests to make it useful!

At your terminal, type:
## Our Use Case

For the purposes of this class, we will assume the role of an infrastructure engineer who is responsible for the security of a NGINX webserver, which is running in a Docker container named `nginx`. We want a way to automate the process of validating the security of our webserver, and we have settled on InSpec as our assessment tool of choice. We have installed InSpec on the host machine for our NGINX container (your GitHub Codespace virtual machine).

::: note What if I don't know anything about NGINX or webservers?
Don't worry. This class does not expect you to be an expert in webserver administration. The concepts we introduce here are relevant to any category of software, from end user applications all the way down to the operating system running your apps.
:::

### Our Requirements

Let's say that we are attempting to validate that our NGINX webserver complies with the following simple list of requirements.

```sh
1. NGINX should be installed as version 1.27.0 or later.
2. The following NGINX modules should be installed:
* `http_ssl`
* `stream_ssl`
* `mail_ssl`
3. The NGINX configuration file - `/etc/nginx/nginx.conf`- should exist as a file.
4. The NGINX configuration file should:
* be owned by the `root` user and group.
* not be readable, writeable, or executable by others.
5. The NGINX shell access should be restricted to admin users.
```

### Creating the profile

We'll start by creating a profile that will contain the tests we want to run against NGINX.

At your terminal, from your preferred directory, type:

::: code-tabs#shell

@tab InSpec Init Command
@tab Command

```bash
inspec init profile my_nginx
Expand All @@ -32,20 +61,26 @@ Creating new profile at /workspaces/saf-training-lab-environment/my_nginx
```
:::

::: note `my_nginx_answer_key`
You may notice that you already have a folder named `my_nginx_answer_key` in your lab system environment that looks suspiciously like a complete InSpec profile for testing NGINX.

That profile is what we will be constructing in the next few sections. Feel free to reference it if you want to see what your code is supposed to look like when we are done.
:::

### Understanding the profile structure

Let's take a look at how the profile is structured. We'll start with how a profile's files are structured and then move to what makes up an InSpec control.

First, run `tree` to see what's in the `my_nginx` profile.
First, run `tree` from the directory that contains your `my_nginx` profile to take a look inside.

::: code-tabs#shell

@tab Tree Command
@tab Command

```sh
tree my_nginx
```
@tab Expected Output - my_nginx folder structure
@tab Expected Output
```
my_nginx
├── README.md
Expand All @@ -58,15 +93,17 @@ my_nginx
Here's the role of each component.

- `README.md` provides documentation about the profile, including what it covers and how to run it.
- The `controls` directory contains files which implement the InSpec tests.
- `inspec.yml` provides metadata, or information, about the profile. Metadata includes the profile's description, author, copyright, and version.
- You may optionally have a `libraries` directory. The `libraries` directory contains resource extensions. A resource extension enables you to [define your own resource types](https://www.inspec.io/docs/reference/dsl_resource/). The [Advanced Security Automation Developer Class](../advanced/README.md) teaches about defining your own resources.
- The `controls` directory contains files that define the actual tests.
- `inspec.yml` provides metadata about the profile. Metadata includes the profile's human-friendly description, author, version, and what parameters we can pass to the profile at runtime.
- You may optionally have a `libraries` directory. The `libraries` directory contains resource extensions. A resource extension enables you to [define your own resource types](https://docs.chef.io/inspec/profiles/custom_resources/). The [Advanced Security Automation Developer Class](../advanced/README.md) will discuss in-depth how to define your own custom resources.

### Understand a control's structure

Let's take a look at the default control file, `controls/example.rb`.

```ruby
# copyright: 2018, The Authors

title 'sample section'

# you can also use plain tests
Expand All @@ -85,21 +122,17 @@ control 'tmp-1.0' do # A unique ID for this control
end
```

::: tip Tip for developing profiles
When creating new profiles use the existing example file as a template
:::

This example shows two tests. Both tests check for the existence of the `/tmp` directory. The second test provides additional information about the test. Let's break down each component.

- `control` (line 9) is followed by the control's name. Each control in a profile has a unique name.
- `impact` (line 10) measures the relative importance of the test and must be a value between 0.0 and 1.0.
- `title` (line 11) defines the control's purpose.
- `desc` (line 12) provides a more complete description of what the control checks for.
- `describe` (lines 1315) defines the test. Here, the test checks for the existence of the `/tmp` directory.
- `control` (line 11) is followed by the control's name. Each control in a profile must have a unique control identifier which is usually derived from the unique identifier of the security requirement being assessed.
- `impact` (line 12) measures the severity, or relative importance, of the test and must be a value between 0.0 and 1.0 where 0.0 is not applicable and 1.0 is of critical importance.
- `title` (line 13) concisely defines the control's purpose.
- `desc` (line 14) provides a more complete description of what the control is assessing.
- `describe` (lines 1517) defines the test. Here, the test checks for the existence of the `/tmp` directory.

In Ruby, the `do` and `end` keywords define a `block`. An InSpec control always contains at least one `describe` block. However, a control can contain many `describe` blocks.
In Ruby, the `do` and `end` keywords define a `block`. An InSpec control always contains at least one `describe` block. However, a control can contain many `describe` blocks as many items might need to be tested to fully assess the requirement.
::: tip More information on a block in Ruby
[Ruby's block syntax](http://ruby-for-beginners.rubymonstas.org/blocks.html)
[Ruby's block syntax](https://ruby-for-beginners.rubymonstas.org/blocks.html)
:::

### Understand a describe block's structure
Expand Down Expand Up @@ -144,10 +177,10 @@ The `it` statement validates one of your resource's features. A `describe` block
Important! Just like in English grammar, pay attention to the difference between the thing (it) and the possessive word (its).

`it` is used to describe an action or the expected behavior of the **subject/resource** in question.
e.g. `it { should be_owned_by 'root' }`
e.g. `it { should exist }`

`its` is used to specify the expectation(s) of **an attribute of the subject/resource**.
e.g. `its("signal") { should eq "on" }`
e.g. `its('size') { should eq 64 }`
:::

---
Expand All @@ -165,7 +198,7 @@ e.g. `its("signal") { should eq "on" }`

### Comprehension Check!

Look at the 4 file structures below. Determine which are valid InSpec Profiles!
Look at the 4 file structures below. Determine which are valid InSpec Profiles that will run the tests!

::: code-tabs#shell

Expand Down
Loading

0 comments on commit 7a7a378

Please sign in to comment.