Skip to content

Commit

Permalink
User Class Updates (#259)
Browse files Browse the repository at this point in the history
* Added bullet numbering and made semantic changes

Signed-off-by: Shivani Karikar <[email protected]>

* Fixed typos

Signed-off-by: Shivani Karikar <[email protected]>

* Corrected link and fixed typos

Signed-off-by: Shivani Karikar <[email protected]>

* Added bullet number

Signed-off-by: Shivani Karikar <[email protected]>

* Fixed links and typos

Signed-off-by: Shivani Karikar <[email protected]>

* Testing tip

Signed-off-by: Shivani Karikar <[email protected]>

* Testing tip again

Signed-off-by: Shivani Karikar <[email protected]>

* Addressed comments and fixed link

Signed-off-by: Shivani Karikar <[email protected]>

* copilot suggestions - stage 1

Signed-off-by: Aaron Lippold <[email protected]>

* Enhancements

Signed-off-by: Shivani Karikar <[email protected]>

* copilot suggestions - 8

Signed-off-by: Aaron Lippold <[email protected]>

* copilot suggestions - 9

Signed-off-by: Aaron Lippold <[email protected]>

* Corrected flag and acronyms

Signed-off-by: Shivani Karikar <[email protected]>

* Standardized code blocks

Signed-off-by: Shivani Karikar <[email protected]>

* Enhancements

Signed-off-by: Shivani Karikar <[email protected]>

* fixed section numbering and section 6.3

Signed-off-by: Aaron Lippold <[email protected]>

* Added link + Grammar fixes

Signed-off-by: Shivani Karikar <[email protected]>

* fixed more numbering issues 8 - 16

Signed-off-by: Aaron Lippold <[email protected]>

* Grammar fixes

Signed-off-by: Shivani Karikar <[email protected]>

* typo in section title

Signed-off-by: Will <[email protected]>

* small fix to 15

Signed-off-by: Aaron Lippold <[email protected]>

* wordsmithing in section 6

Signed-off-by: Will <[email protected]>

* Bump the vuepress group with 2 updates

Bumps the vuepress group with 2 updates: [@vuepress/plugin-markdown-image](https://github.com/vuepress/ecosystem/tree/HEAD/plugins/plugin-markdown-image) and [@vuepress/plugin-markdown-tab](https://github.com/vuepress/ecosystem/tree/HEAD/plugins/markdown/plugin-markdown-tab).


Updates `@vuepress/plugin-markdown-image` from 2.0.0-rc.60 to 2.0.0-rc.61
- [Release notes](https://github.com/vuepress/ecosystem/releases)
- [Commits](https://github.com/vuepress/ecosystem/commits/v2.0.0-rc.61/plugins/plugin-markdown-image)

Updates `@vuepress/plugin-markdown-tab` from 2.0.0-rc.60 to 2.0.0-rc.61
- [Release notes](https://github.com/vuepress/ecosystem/releases)
- [Changelog](https://github.com/vuepress/ecosystem/blob/main/plugins/markdown/plugin-markdown-tab/CHANGELOG.md)
- [Commits](https://github.com/vuepress/ecosystem/commits/v2.0.0-rc.61/plugins/markdown/plugin-markdown-tab)

---
updated-dependencies:
- dependency-name: "@vuepress/plugin-markdown-image"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: vuepress
- dependency-name: "@vuepress/plugin-markdown-tab"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: vuepress
...

Signed-off-by: dependabot[bot] <[email protected]>

* Bump mermaid from 11.4.0 to 11.4.1

Bumps [mermaid](https://github.com/mermaid-js/mermaid) from 11.4.0 to 11.4.1.
- [Release notes](https://github.com/mermaid-js/mermaid/releases)
- [Changelog](https://github.com/mermaid-js/mermaid/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/mermaid-js/mermaid/compare/[email protected]@11.4.1)

---
updated-dependencies:
- dependency-name: mermaid
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>

* DEC Training - Guidance Course (#263)

* typos, adding details, updating control in section 7 to use a more intuitive example

Signed-off-by: Will <[email protected]>

* fixing navbar to show all resource pages, combining and updating resource pages, adding the STIG vendor process guide as a downloadable PDF

Signed-off-by: Will <[email protected]>

* updating the screenshots to use the right component (updating examples to be based off of most recent GPOS SRG

Signed-off-by: Will <[email protected]>

* updating more screenshots, removing the step numbers in 5-7 since they dont make much sense for a doc with headers like this

Signed-off-by: Will <[email protected]>

* updating images to use correct SRG version, fleshing out some sections, typos/copyediting

Signed-off-by: Will <[email protected]>

* section 7 too long, decided it needed to be its own section -- TODO: decide if we want more content re: adding requirements

Signed-off-by: Will <[email protected]>

* updating diff viewer section

Signed-off-by: Will <[email protected]>

* flow editing for STIGs

Signed-off-by: Will <[email protected]>

* typos

Signed-off-by: Will <[email protected]>

---------

Signed-off-by: Will <[email protected]>

* typo

Signed-off-by: Will <[email protected]>

* moving section 15 to an appendix

Signed-off-by: Will <[email protected]>

* forgot to save last change

Signed-off-by: Will <[email protected]>

* taking the wrong numbers out of the appendices

Signed-off-by: Will <[email protected]>

---------

Signed-off-by: Shivani Karikar <[email protected]>
Signed-off-by: Aaron Lippold <[email protected]>
Signed-off-by: Will <[email protected]>
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: Aaron Lippold <[email protected]>
Co-authored-by: Will <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: wdower <[email protected]>
  • Loading branch information
5 people authored Dec 2, 2024
1 parent 7d7ffb3 commit 0245cf0
Show file tree
Hide file tree
Showing 20 changed files with 403 additions and 473 deletions.
36 changes: 18 additions & 18 deletions src/courses/advanced/Appendix A - Writing Plural Resources.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ author: Aaron Lippold
headerDepth: 3
---

## 10. Plural Resources
## Plural Resources

You might have noticed that many InSpec resources have a "plural" version. For example, `user` has a `users` counterpart, and `package` has `packages`.

Expand All @@ -30,7 +30,7 @@ This test queries **all** users to confirm that the only one with a uid of zero

Plural InSpec resources are created by leveraging Ruby's FilterTable module to capture system data. Let's dig into how FilterTable works so that you can write your own plural resources.

### 10.1. Using FilterTable to write a Plural Resource
### Using FilterTable to write a Plural Resource

FilterTable is intended to help you author plural resources with **stucture data**. You declare a number of columns of data, attach them to a FilterTable object, and then write methods that the FilterTable can call to populate those columns. You can also define custom matchers that make sense for whatever data you are modeling (to go alongside the standard InSpec matchers like `be_in`,`include`, and `cmp`). You wind up with a queryable structure:

Expand All @@ -47,11 +47,11 @@ inspec> etc_hosts.entries

```

#### 10.1.1. May I have multiple FilterTable installations on a class?
#### May I have multiple FilterTable installations on a class?

In theory, yes - that would be used to implement different data fetching / caching strategies. It is a very advanced usage, and no core resources currently do this, as far as we know.

### 10.2. FilterTable Hands-On
### FilterTable Hands-On

Let's take a look at the structure of a resource that leverages FilterTable. We will write a dummy resource that models a small group of students. Our resource will describe each student's name, grade, and the toys they have. Usually, a resource will include some methods that reach out the system under test to populate the FilterTable with real system data, but for now we're just going to hard-code in some dummy data.

Expand Down Expand Up @@ -99,23 +99,23 @@ end
```
Now we've got a nice blob of code in a resource file. Let's load this resource in the InSpec shell and see what we can do with it.

#### 10.2.1. Run the InSpec shell with a custom resource
#### Run the InSpec shell with a custom resource

Invoking the InSpec shell with `inspec shell` will give you access to all the core InSpec resources by default, but InSpec does not automatically know about your locally defined resources unless you point them out. If you're testing a local resource, use the `--depends` flag and pass in the profile directory that your resource lives in.

```
inspec shell --depends /path/to/profile/root/
```

#### 10.2.2. Fetching Data
#### Fetching Data

FilterTables organize their data into columns. Your resource will declare a number of columns using the `register_column` method.

Once you declare the columns that you want in your FilterTable (`name`, `grade`, and `toys` in our example), you need to insert some data into them using the `install_filter_methods_on_resource` method. That method takes two args -- `self` and a data structure that is an array of hashes. The array of hashes will be matched up to the columns you defined using the hashes' keys. For our example we hard-coded this data structure, which is returned by the `fetch_data` method.

As we mentioned earlier, a real InSpec resource will include methods that will populate the resource with real system data. Take a look at the [Firewalld resource](https://github.com/inspec/inspec/blob/63a5fd26a6925b1570ee80e2953d259b58c3012e/lib/inspec/resources/firewalld.rb) for an example of a resource that does this -- note the resource is ultimately invoking a shell command (`firewall-ctl`) to populate its FilterTable. There are plenty of other InSpec resources using FilterTable that you can find in the source code if you are interested in more examples.

#### 10.2.3. Custom Matcher Examples
#### Custom Matcher Examples

After we define our FilterTable's columns, we can also define custom matchers just like we do in singluar resources using `register_custom_matcher`. That function takes a block as an argument that defines a boolean expression that tells InSpec when that matcher should return `true`. Note that the matcher's logic can get pretty complicated -- that's why we're shoving all of it into a resource so we can avoid having to write complicated tests.

Expand Down Expand Up @@ -167,7 +167,7 @@ Test Summary: 1 successful, 0 failures, 0 skipped

```

#### 10.2.4. Custom Property
#### Custom Property

We can also declare custom properties for our resource, using whatever logic we like, just like we did for our custom matchers. Properties can be referred to with `its` syntax in an InSpec test.

Expand Down Expand Up @@ -209,7 +209,7 @@ Test Summary: 0 successful, 1 failure, 0 skipped

```

#### 10.2.5. Suggested activity
#### Suggested activity

To get a better feel for how FilterTable works, we suggest you add a few extra features to the sample given above.

Expand All @@ -219,11 +219,11 @@ To get a better feel for how FilterTable works, we suggest you add a few extra f

Then write some tests to see how your new matchers and properties work.

### 10.3. Predefined Methods for FilterTable
### Predefined Methods for FilterTable

When you create a new FilterTable, these methods are installed automatically: `where`, `entries`, `raw_data`, `count`, and `exist?`. Each is very useful both for writing tests in and of themselves and for creating custom matchers and properties inside the resource code.

#### 10.3.1 The `where` method
#### The `where` method

You may have already noticed that a bunch of our example tests are using the `where` method on the FilterTable object. This method returns a new FilterTable object created from the rows of the original table that match the query provided to `where`. If you have experience with relational databases, think of it like the `WHERE` clause in a SQL query. This method is extremely flexible; we give some examples below.

Expand Down Expand Up @@ -255,7 +255,7 @@ You may have already noticed that a bunch of our example tests are using the `wh

```

##### 10.3.1.1. `where` method with blocks
##### `where` method with blocks

You can also call the `where` method with a block. The block is executed row-wise. If it returns truthy, the row is included in the results. Each field declared with the `register_custom_property` configuration method is available as a data accessor.

Expand All @@ -272,7 +272,7 @@ You can also call the `where` method with a block. The block is executed row-wis
end
```

##### 10.3.1.2. Chaining `where` calls and Tables without re-fetching raw data
##### Chaining `where` calls and Tables without re-fetching raw data

The first time `where` is called, the data fetcher method is called. `where` performs filtration on the raw data table. It then constructs a new `FilterTable::Table`, directly passing in the filtered raw data; this is then the return value from `where`.

Expand All @@ -285,7 +285,7 @@ The first time `where` is called, the data fetcher method is called. `where` pe

Some other methods return a Table object, and they may be chained without a re-fetch as well.

#### 10.3.2. The `entries` method
#### The `entries` method

The other `register_filter_method` call enables a pre-defined method, `entries`. `entries` is much simpler than `where` - in fact, its behavior is unrelated. It returns an encapsulated version of the raw data - a plain array, containing Structs as row-entries. Each struct has an attribute for each time you called `register_column`.

Expand Down Expand Up @@ -319,7 +319,7 @@ If you call `entries` without chaining it after `where`, calling entries will tr
end
```

#### 10.3.3. The `exist?` matcher
#### The `exist?` matcher

This `register_custom_matcher` call:
```ruby
Expand All @@ -342,7 +342,7 @@ As when you are implementing matchers on a singular resource, the only thing tha
end
```

#### 10.3.4. The `count` property
#### The `count` property

This `register_custom_property` call:
```ruby
Expand All @@ -363,7 +363,7 @@ causes a new method to be defined on both the resource class and the Table class
end
```

#### 10.3.5. The `raw_data` method
#### The `raw_data` method

Unlike `entries`, which wraps each row in a Struct and omits undeclared fields, `raw_data` simply returns the actual raw data array-of-hashes. It is not `dup`'d. People _definitely_ use this out in the wild, even though it returns a rougher data structure.

Expand All @@ -377,7 +377,7 @@ Unlike `entries`, which wraps each row in a Struct and omits undeclared fields,
end
```

### 10.4 FilterTable Examples
### FilterTable Examples

FilterTable is a very flexible and powerful class that works well when designing plural resources. As always, if you need to write a plural resource, we encourage you to examine existing resources in the InSpec source code to see how other developers have implemented it. Some good examples include:
- [FirewallD](https://github.com/inspec/inspec/blob/63a5fd26a6925b1570ee80e2953d259b58c3012e/lib/inspec/resources/firewalld.rb)
Expand Down
30 changes: 16 additions & 14 deletions src/courses/advanced/Appendix B - Resource Examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ headerDepth: 3

As an example we will go through a few custom resources that were built and approved.

### 14.1. IPv6 resource
#### 14.1.1. docs/resources/ip6tables.md.erb
### The IPv6 resource

#### docs/resources/ip6tables.md.erb
```ruby
---
title: About the ip6tables Resource
Expand Down Expand Up @@ -86,7 +87,7 @@ The `have_rule` matcher tests the named rule against the information in the `ip6
it { should have_rule('RULE') }
```

#### 14.1.2. lib/inspec/resources.rb
#### lib/inspec/resources.rb
```ruby
require "inspec/resources/iis_site"
require "inspec/resources/inetd_conf"
Expand All @@ -97,7 +98,7 @@ require "inspec/resources/kernel_module"
require "inspec/resources/kernel_parameter"
```

#### 14.1.3. lib/inspec/resources/ip6tables.rb
#### lib/inspec/resources/ip6tables.rb
```ruby
require "inspec/resources/command"

Expand Down Expand Up @@ -184,7 +185,7 @@ end
While submitting PR it may be possible to extend existing test elements from current resources to perform integration and unit testing such is seen in this example, the ipv6 resource extends the testing for [iptables](https://www.inspec.io/docs/reference/resources/iptables/) resource
:::

#### 14.1.4. test/integration/default/controls/ip6tables_spec.rb
#### test/integration/default/controls/ip6tables_spec.rb
```ruby
case os[:family]
when 'ubuntu', 'fedora', 'debian', 'suse'
Expand All @@ -211,7 +212,7 @@ when 'redhat', 'centos'
end
```

#### 14.1.5. test/unit/resources/ip6tables_test.rb
#### test/unit/resources/ip6tables_test.rb
```ruby
require "helper"
require "inspec/resource"
Expand Down Expand Up @@ -247,8 +248,8 @@ describe "Inspec::Resources::Ip6tables" do
end
```

### 14.2. NGINX resource
#### 14.2.1. docs/resources/nginx.md.erb
### The NGINX resource
#### docs/resources/nginx.md.erb
```ruby
---
title: The Nginx Resource
Expand Down Expand Up @@ -324,7 +325,7 @@ where
end
```
#### 14.2.2. lib/inspec/resource.rb
#### lib/inspec/resource.rb
```ruby
require 'resources/mysql'
require 'resources/mysql_conf'
Expand All @@ -335,7 +336,7 @@ require 'resources/npm'
require 'resources/ntp_conf'
```
#### 14.2.3. lib/resources/nginx.rb
#### lib/resources/nginx.rb
```ruby
# encoding: utf-8
# author: Aaron Lippold, [email protected]
Expand Down Expand Up @@ -436,7 +437,7 @@ module Inspec::Resources
end
```
#### 14.2.4. test/unit/resources/nginx_test.rb
#### test/unit/resources/nginx_test.rb
```ruby
# encoding: utf-8
# author: Aaron Lippold, [email protected]
Expand Down Expand Up @@ -534,10 +535,11 @@ describe 'Inspec::Resources::Nginx' do
end
```
### 14.3. Additional examples
#### 14.3.1. PAM resource currently open PR
### Additional examples
#### PAM resource currently open PR
- [PAM Resource](https://github.com/simp/inspec-profile-disa_stig-el7/blob/master/libraries/pam.rb)
- [PAM PR](https://github.com/inspec/inspec/pull/3993)
#### 14.3.2. Customizing an already existing resource (windows registry)
#### Customizing an already existing resource (windows registry)
- [https://github.com/mitre/microsoft-windows-2012r2-memberserver-stig-baseline/blob/master/libraries/windows_registry.rb](https://github.com/mitre/microsoft-windows-2012r2-memberserver-stig-baseline/blob/master/libraries/windows_registry.rb)
4 changes: 2 additions & 2 deletions src/courses/advanced/Appendix E - More Resource Examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ author: Aaron Lippold
headerDepth: 3
---

### 11.1. File
### The File Resource
```ruby
# copyright: 2015, Vulcano Security GmbH

Expand Down Expand Up @@ -371,7 +371,7 @@ module Inspec::Resources
end
```

### 11.3. etc_hosts
### The etc_hosts Resource
```ruby
require "inspec/utils/parser"
require "inspec/utils/file_reader"
Expand Down
28 changes: 18 additions & 10 deletions src/courses/user/02.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,33 @@ headerDepth: 3
---

## 2.1 The Goal of the SAF

### 1. Accelerate ATO
- Automate tailored security configuration testing in every build
- Aggregate all security assessment results in a single dashboard to show security status

- Automate tailored security configuration testing in every build.
- Aggregate all security assessment results in a single dashboard to show security status.

### 2. Establish Security Requirements
- Align security tests to requirements
- Write STIG-ready content for software components

- Align security tests to requirements.
- Write STIG-ready content for software components.

### 3. Build Security In
- Automate security control assessment aligned to common standards
- Implement security requirements within existing DevSecOps pipelines

- Automate security control assessment aligned to common standards.
- Implement security requirements within existing DevSecOps pipelines.

### 4. Assess/Monitor Vulnerabilities
- Visualize results of all ongoing assessments to understand risk over time
- Enable ongoing or continuous authorization to operate (cATO)

- Visualize results of all ongoing assessments to understand risk over time.
- Enable ongoing or continuous authorization to operate (cATO).

![The Goals of the SAF](../../assets/img/SAF_Goals.png)

## 2.2 The Road to Security Automation

As you can see from the picture below, the process for developing automated security tests starts with requirements documents like SRGs, STIGs or CIS Benchmark that are written in regular, human language and then implemented as code. We need that code to record test results in a standardized format so that we can easily export our security data somewhere people can use it to make decisions (like the Heimdall visualization app).
As illustrated in the picture below, the process for developing automated security tests starts with requirements documents like SRGs, STIGs, or CIS Benchmarks, which are written in human-readable language. These documents are then implemented as code. We need that code to record test results in a standardized format so that we can easily export our security data to a platform where it can be used to make informed decisions (such as the Heimdall visualization app).

This challenge is what the [MITRE Security Automation Framework](https://saf.mitre.org) or MITRE SAF was developed to simplify -- to make the journey from a Requirement Document to an automated test profile and back again a little easier to navigate.
This challenge is what the [MITRE Security Automation Framework](https://saf.mitre.org) (MITRE SAF) was developed to address. It simplifies the journey from a Requirement Document to an automated test profile and back again, making it easier to navigate.

![The SAF Lifecycle](../../assets/img/saf-lifecycle.png)
45 changes: 13 additions & 32 deletions src/courses/user/03.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,56 +6,37 @@ author: Aaron Lippold
headerDepth: 3
---

## 3. SAF Scavenger Hunt
## 3.1 SAF Scavenger Hunt

Explore the [SAF homepage](https://saf.mitre.org/) to find the answers to this scavenger hunt and familiarize yourself with the topics of this course. When you are done, check your answers!

::: details 1. What are the main pillars of the SAF?
The main pillars are
The main pillars are:

- Plan
- Harden
- Validate
- Normailze
- Normalize
- Visualize

The SAF helps teams plan what guidance will help them keep their software secure. It also provide libraries and tools for automatically hardening and validating software based on that guidance, normalize other security data, and visualize all the information to properly inform teams of risk and vulnerabilities.
The SAF helps teams plan what guidance will help them keep their software secure. It also provides libraries and tools for automatically hardening and validating software based on that guidance, normalizing other security data, and visualizing all the information to properly inform teams of risk and vulnerabilities.
:::

::: details 2. Is SAF a tool? Why or why not?
Nope!

SAF, the Security Automation Framework, is a Framework and uses a COLLECTION of tools, techniques, applications, and libraries to streamline security automation. Since teams operate in different environments with different components, not everyone's security journey will look the same.
No.

SAF, the Security Automation Framework, is a framework that uses a collection of tools, techniques, applications, and libraries to streamline security automation. Since teams operate in different environments with different components, not everyone's security journey will look the same.

Some notable tools within the Security Automation Framework are Vulcan, the SAF CLI, and Heimdall.
![Alt text](../../assets/img/SAF_Capabilities_SAF_Tools.png)
![SAF Tools](../../assets/img/SAF_Capabilities_SAF_Tools.png)
:::

::: details 3. What is HDF?
[HDF](https://saf.mitre.org/#/normalize), or Heimdall Data Format, is a common format to represent normalized security data. HDF files record vital security data about a completed validation test, such as the test code, description, attributes, and outcome. This allows for the aggregation and analysis of test results from a wide range of validation tools at once.
::: details 3. What is OHDF?
[OHDF](https://saf.mitre.org/#/normalize), or the OASIS Heimdall Data Format, is a common format to represent normalized security data. OHDF files record vital security data about a completed validation test, such as the test code, description, attributes, and outcome. This allows for the aggregation and analysis of test results from a wide range of validation tools at once.

HDF data can be easily visualized in [Heimdall](https://heimdall-lite.mitre.org/), the SAF's visualization application.
OHDF data can be easily visualized in [Heimdall](https://heimdall-lite.mitre.org/), the SAF's visualization application.
:::

::: details 4. Which of the following is NOT a tool that SAF provides to help in the security automation process? (eMASS Client, InSpec, SAF CLI, Heimdall, Vulcan)
InSpec is more than a tool - it is a language developed by Chef that MITRE and other security community members use to write InSpec profiles which are sets of controls for automating security validation. You can view InSpec profiles on the [validation section of the SAF site](https://saf.mitre.org/#/validate). You can see more information on how to run InSpec profiles on the [getting started section](https://saf.mitre.org/#/getstarted). The available tools are found under the "The MITRE SAF© Open Source Toolset" section of the [site](https://saf.mitre.org/).
InSpec is more than a tool - it is a language developed by Chef that MITRE and other security community members use to write InSpec profiles, which are sets of controls for automating security validation. You can view InSpec profiles on the [validation section of the SAF site](https://saf.mitre.org/#/validate). You can see more information on how to run InSpec profiles on the [getting started section](https://saf.mitre.org/#/getstarted). The available tools are found under the "The MITRE SAF© Open Source Toolset" section of the [site](https://saf.mitre.org/).
:::

<!-- ### 2.1. Identifying your stack and checking for a profile using the saf site
![Alt text](../../assets/img/SAF_Validate.png)
### 2.2. Reviewing README for a profile and understanding how to use them
![Alt text](../../assets/img/Github_nginx.png)
### 2.3. Understand the most appropriate way of running InSpec
![Alt text](../../assets/img/runner.png)
### 2.4. Learning how to run InSpec
![Alt text](../../assets/img/InSpec_Multiple_Controls.png)
### 2.5. Tooling and Reporting
![Alt text](../../assets/img/Heimdall_Results.png) -->
Loading

0 comments on commit 0245cf0

Please sign in to comment.