This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Documentation

This documentation is a work in progress. If you have suggestions or would like to offer fixes, please feel free to submit your fixes/suggestions using the links to the right.

1 - Overview

Overview of the VMware DoD Compliance and Automation project.

What is the VMware DoD Compliance and Automation Project for?

STIG documents are written to be portable, offline hardening documentation where a sysadmin can go through, step by step, and STIG a system with no external dependencies. That said, many STIGs are either too complex or need to be applied to so many instances that manual steps are just not feasible. To augment the plain language STIG content, we are providing a number of ways to script or automate your VMware compliance activities.

Why do I want it?

The example automation provided will help with the following tasks:

  • Scanning VMware products for STIG compliance.
  • Generating artifacts such as compliance reports to visualize compliance status and CKL files for accredidation.
  • Remediating VMware products for STIG compliance.

Where should I go next?

  • Best Practices: Learn about general best practices for implementing STIGs.
  • Automation Tools: Learn about the tools we use for STIG automation.
  • Tutorials: Product specific tutorials on implementing STIGs.

2 - Best Practices

The best practices discussed in this section are intended to reduce an organizations risk when hardening systems with the methodology intended to be applied to any product.

2.1 - Types of Guidance

VMware works with DISA to publish official STIGs but also creates self-published STIG Readiness Guides.

For more information on the different types of STIG guidance VMware offers see the VMware STIG Program Overview.

2.2 - Control Types

VMware STIG Control Types

VMware STIG controls can be broken up into two categories, Product or Appliance. This helps differentiate where and how these controls are handled.

Product Control: Configurations that interact with the Product via the User Interface or API that are exposed to administrators. Whether these are Default or Non-Default, the risk of mis-configuration effecting availability of the product is low but could impact how the environment is operated if not assessed.

Appliance Control: Appliance controls deal with the underlying components (databases, web servers, Photon OS, etc) that make up the product that is shipped as an appliance. Altering these add risk to product availability if precautionary steps and care in implementation are not taken. Identifying and relying on Default settings in this category makes this category less risky (Default Appliance Controls should be seen as a positive).

2.3 - Implementation Methodology

VMware STIG Implementation Methodology

The last thing any system administrator wants to do is break the systems they are responsible for by hardening them. Implementing STIG controls in a methodical and consistent manner will reduce the risk of operational impacts to an organizations environment.

Workflow

The workflow below can be applied to any product whether it is delivered as an applicance or not. If a product is not an appliance you can skip that part of the workflow.

alt text

Tips

  • Whenever possible, it is highly recommended to test any hardening guidance in a test environment first. This will help you get familiar with the procedures and tools involved in the process.
  • Make sure you have a backout plan! Snapshots, backups, copies of files before modification are all good ideas.
  • Perform service restarts and/or appliance restarts after each appliance component is remediated. Many problems will not manifest until this is done.
  • If you are not 100% sure what a control is asking you to do, ask a co-worker to review it or reach out for clarification as detailed in the support section.
  • If the results from checking a control don’t make sense, ask a co-worker to review it or reach out for clarification as detailed in the support section.
  • Get familiar with the available automation tools and how they work before going all in on the automation content that is available.
  • Run any existing daily health checks or common tasks in your environment to confirm functionality along the way.
  • Check for updated guidance before starting.
  • Always match the product version the guidance is intended for with the product version in use.
  • Read finding statements carefully. Some controls may not be applicable in your scenario.
  • Consider how your environment is operated for impacts. If some of your tools or integrations utilize SSH to function then disabling SSH will impact daily operations and alternatives should be explored or risk accepted to waive a control by the appropriate authority.
  • Document changes so you and your co-workers can remember what changes were made.

vSphere Example

If we apply this workflow to vSphere 7 or 8 it would look like this at a high level.

  1. Apply Product STIGs with functional testing in between each STIG
    • ESXi
    • vCenter
    • Virtual Machines
  2. Apply vCenter Appliance STIGs with functional testing in between each STIG
    • EAM
    • Lookupsvc
    • Perfcharts
    • Photon
    • PostgreSQL
    • Rhttpproxy/Envoy
    • STS
    • UI
    • VAMI

It is important to focus on one STIG at a time so that any issues identified during functional testing can be quickly narrowed down.

Incremental Implementations

It is also a valid strategy, especially in larger environments with multiple vCenters and clusters, to incrementally implement STIGs to one site, vCenter, or vSphere cluster at a time to identify any issues without impacting the entire environment.

When pursuing this approach here are some items to consider:

  • Do not mix hardened with non-hardened ESXi hosts in the same cluster.
  • If multiple vCenter servers exist consider how they are linked to each other or share an SSO domain.

3 - Automation Tools

Automation tools used in this project.

3.1 - Powershell/PowerCLI

How to use and install VMware’s PowerCLI module for Powershell

PowerCLI is a command-line interface for managing and automating all aspects of vSphere management, including networking, storage, VMs, guest OS, and more. PowerCLI functions as a collection of PowerShell modules that contain more than 700 cmdlets (commands) to manage VMware infrastructure.

PowerCLI runs on top of PowerShell, which is a cross-platform task automation and configuration management framework. It consists of a command-line shell and a scripting language. PowerCLI uses PowerShell’s basic syntax and concepts.

Prerequisites

  • PowerShell version 5.1 or later is required to run PowerCLI cmdlets.
  • Powershell comes installed on Windows and Windows Server by default.
  • For Linux and MAC Powershell must be installed.

For more information, see the PowerCLI Compatability matrixes.

Installation

Online

You can install PowerCLI directly from the PowerShell Gallery.

# Run the following command from a Powershell prompt
Install-Module -Name VMware.PowerCLI

Offline

Download the .zip file with the latest released PowerCLI version from here.

# To retrieve the folder(s) on your machine that contain PowerShell modules, run the following command.
$env:PSModulePath

# Extract the downloaded .zip file to one of the listed folders.

# Unblock the copied files
cd path_to_powershell_modules_folder Get-ChildItem * -Recurse | Unblock-File

# Verify if the PowerCLI module is available on your system.
Get-Module -Name VMware.PowerCLI -ListAvailable

Basic Usage

PowerCLI includes cmdlets to connect to supported VMware products. This must be done before any other PowerCLI cmdlets can be run successfully.

Connect to vCenter or ESXi directly

# Connects to a vSphere server by using the User and Password parameters.
Connect-VIServer -Server 10.23.112.235 -Protocol https -User admin -Password pass

# Connects to a vSphere server by using a credential object.
$cred = Get-Credential
Connect-VIServer -Server 10.23.112.235 -Protocol https -Credential $cred

References

For the full PowerCLI documentation, see the PowerCLI Installation Guide

3.2 - Chef InSpec/CINC

How to use and install Chef InSpec or CINC

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.

Cinc is a recursive acronym for CINC Is Not Chef. Chef InSpec is free for non-commercial use so the Cinc project was able to remove any trademarks while still complying with Chef’s policies and offer a free for any use alternative. Cinc Auditor is built off the same code base as Chef InSpec.

Why InSpec?

Chef InSpec/CINC Auditor is currently being utilized to assess products as it is geared specifically towards compliance auditing and reporting. It is also something our DoD customers can use, along with the supporting tools from the MITRE Security Automation Framework, to create artifacts needed to accredit their environments.

Additionally, using a separate tool than what is used to fix or remediate controls is good practice and provides additional assurances that the configuration is in an agreed upon state from multiple points of view. One can think of this similar to a home builder and inspector where we don’t rely on a builder to inspect things and tell us they are up to code.

Prerequisites

  • Windows, Linux, and MAC are supported.

Installation

Online

Windows

# Run the following command from a Powershell prompt
. { iwr -useb https://omnitruck.chef.io/install.ps1 } | iex; install -project inspec

Linux

curl https://omnitruck.chef.io/install.sh | sudo bash -s -- -P inspec

Offline

Download the package for your OS here.

Concepts

Profiles

In InSpec terms we offer “profiles” to audit products. Simple profiles have the following structure:

examples/profile
├── README.md
├── controls
│   ├── example.rb
│   └── control_etc.rb
├── libraries
│   └── extension.rb
|── files
│   └── extras.conf
└── inspec.yml

The inspec.yml file includes some metadata about the profile and any inputs(variables) and dependencies.

Inputs provide a way for us to provide values to tests without having to update the test to do so. For example, we may have an input for a syslog server to check that the correct syslog server for your environment is configured. Inputs can be given as an argument at the cli or in an inputs file that is then provided at the cli as well. We recommend using an inputs file because it is easier to manage and provide at the cli.

Dependent Profiles

In many cases our profiles are really made up of multiple profiles that are included in the same folder structure but can also be pulled in from another location.

We do this when a product may have multiple STIGs that we would like to audit together but also separate into its own profile for organizational purposes. Another reason to do this is it makes profile reuse easier like with Photon OS which many of our product appliances are based on. Instead of maintaining a profile for Photon with each product we can maintain Photon separately and it can be called as a dependency in a product’s profile and then provided inputs and tweaked as needed for that specific product.

If we look at the vSphere 7 VCSA profile we will see an example of this.

An abbreviated structure for this profile.

vmware-vcsa-7.0-stig-baseline
├── README.md
├── controls
│   ├── eam.rb
│   └── photon.rb
├── eam
  ├── README.md
  ├── controls
  │   ├── VCEM-70-000001.rb
  │   └── VCEM-70-000002.rb
  ├── libraries    
  │   └── extension.rb
  |── files
  │   └── extras.conf
  └── inspec.yml
├── photon
  ├── README.md
  ├── controls
  │   ├── PHTN-30-000001.rb
  │   └── PHTN-30-000002.rb
  ├── libraries    
  │   └── extension.rb
  |── files
  │   └── extras.conf
  └── inspec.yml
└── inspec.yml

For more information on dependent profiles, see Profile Dependencies.

InSpec Vendoring

Dependent profiles are “vendored” or cached into the /vendor folder in the profile. This is important to pay attention to because if changes are made to dependent profiles and this cache is not updated you will not see the changes when you run the profile though the parent.

Update the vendor/cache.

inspec vendor --overwrite
Dependencies for profile /vmware-vcsa-7.0-stig-baseline successfully vendored to /vmware-vcsa-7.0-stig-baseline/vendor

Controls

For the profiles we develop, the controls folder contains a file for each STIG control that includes that controls metadata and a test for auditing.

Example control file

control 'ESXI-70-000001' do
  title 'Access to the ESXi host must be limited by enabling lockdown mode.'
  desc  "
    Enabling lockdown mode disables direct access to an ESXi host, requiring the host to be managed remotely from vCenter Server. This is done to ensure the roles and access controls implemented in vCenter are always enforced and users cannot bypass them by logging on to a host directly.

    By forcing all interaction to occur through vCenter Server, the risk of someone inadvertently attaining elevated privileges or performing tasks that are not properly audited is greatly reduced.
  "
  desc  'rationale', ''
  desc  'check', "
    For environments that do not use vCenter server to manage ESXi, this is not applicable.

    From the vSphere Client, go to Hosts and Clusters.

    Select the ESXi Host >> Configure >> System >> Security Profile.

    Scroll down to \"Lockdown Mode\" and verify it is set to \"Enabled\" (Normal or Strict).

    or

    From a PowerCLI command prompt while connected to the ESXi host, run the following command:

    Get-VMHost | Select Name,@{N=\"Lockdown\";E={$_.Extensiondata.Config.LockdownMode}}

    If \"Lockdown Mode\" is disabled, this is a finding.
  "
  desc 'fix', "
    From the vSphere Client, go to Hosts and Clusters.

    Select the ESXi Host >> Configure >> System >> Security Profile >> Lockdown Mode.

    Click \"Edit...\". Select the \"Normal\" or \"Strict\" radio buttons.

    or

    From a PowerCLI command prompt while connected to the ESXi host, run the following commands:

    $level = \"lockdownNormal\" OR \"lockdownStrict\"
    $vmhost = Get-VMHost -Name <hostname> | Get-View
    $lockdown = Get-View $vmhost.ConfigManager.HostAccessManager
    $lockdown.ChangeLockdownMode($level)

    Note: In strict lockdown mode, the Direct Console User Interface (DCUI) service is stopped. If the connection to vCenter Server is lost and the vSphere Client is no longer available, the ESXi host becomes inaccessible.
  "
  impact 0.5
  tag severity: 'medium'
  tag gtitle: 'SRG-OS-000027-VMM-000080'
  tag satisfies: ['SRG-OS-000123-VMM-000620']
  tag gid: 'V-256375'
  tag rid: 'SV-256375r885906_rule'
  tag stig_id: 'ESXI-70-000001'
  tag cci: ['CCI-000054', 'CCI-001682']
  tag nist: ['AC-10', 'AC-2 (2)']

  vmhostName = input('vmhostName')
  cluster = input('cluster')
  allhosts = input('allesxi')
  vmhosts = []

  unless vmhostName.empty?
    vmhosts = powercli_command("Get-VMHost -Name #{vmhostName} | Sort-Object Name | Select -ExpandProperty Name").stdout.split
  end
  unless cluster.empty?
    vmhosts = powercli_command("Get-Cluster -Name '#{cluster}' | Get-VMHost | Sort-Object Name | Select -ExpandProperty Name").stdout.split
  end
  unless allhosts == false
    vmhosts = powercli_command('Get-VMHost | Sort-Object Name | Select -ExpandProperty Name').stdout.split
  end

  if !vmhosts.empty?
    list = ['lockdownNormal', 'lockdownStrict']
    vmhosts.each do |vmhost|
      command = "(Get-VMHost -Name #{vmhost}).Extensiondata.Config.LockdownMode"
      describe powercli_command(command) do
        its('stdout.strip') { should be_in list }
      end
    end
  else
    describe 'No hosts found!' do
      skip 'No hosts found...skipping tests'
    end
  end
end

Train (Transport Interfaces)

Train Plugins allow InSpec to connect to various types of endpoints for auditing. Some common plugins are:

  • Local execution
  • SSH
  • WinRM
  • Docker and Podman
  • Mock (for testing and debugging)
  • AWS as an API
  • Azure as an API
  • VMware via PowerCLI

For example, we audit a vCenter Appliance using the SSH plugin so it connects to vCenter over SSH to perform the audit.

Reporters

InSpec can provide results in a variety of formats such as:

  • cli
  • json
  • yaml
  • html,html2
  • junit

These are useful for system admins to collect and monitor configuration drift and for accreditation tasks where with the SAF CLI tool you can convert results into a CKL file to import into STIG Viewer.

For more information on reports, see Reporters

Waivers

Waivers allow you do document as code the controls that have a waiver/poam in place for your environment. This is done through a waivers file and provided as an argument at the command line.

Example waivers.yml file

PHTN-30-000053:
  expiration_date: 2024-12-31
  run: false
  justification: "vRA gets it's IP after sshd starts and causes sshd to fail if this is configured to something other than 0.0.0.0:22"
PHTN-30-000106:
  expiration_date: 2024-12-31
  run: false
  justification: "vRA runs Kubernetes which needs this kernel option to forward traffic"

For more information on reports, see Waivers

Running InSpec Examples and Common Arguments

The examples below are for running InSpec from a Windows based machine with the vSphere 7 VCSA profile.

# Run against a target vCenter appliance and output results to CLI
inspec exec C:\Inspec\Profiles\vmware-vcsa-7.0-stig-baseline -t ssh://root@10.1.1.1 --password 'password'

# Run against a target vCenter appliance, show progress, and output results to CLI and JSON
inspec exec C:\Inspec\Profiles\vmware-vcsa-7.0-stig-baseline -t ssh://root@10.1.1.1 --password 'password' --show-progress --reporter=cli json:C:\Inspec\Reports\vcsa.json

# Run against a target vCenter appliance and provide an inputs file
inspec exec C:\Inspec\Profiles\vmware-vcsa-7.0-stig-baseline -t ssh://root@10.1.1.1 --password 'password' --input-file .\inputs-example.yml

# Run against a target vCenter appliance and provide a waivers file
inspec exec C:\Inspec\Profiles\vmware-vcsa-7.0-stig-baseline -t ssh://root@10.1.1.1 --password 'password' --waiver-file .\waiver-example.yml

# Run against a target vCenter appliance and limit the controls run to a single control
inspec exec C:\Inspec\Profiles\vmware-vcsa-7.0-stig-baseline -t ssh://root@10.1.1.1 --password 'password' --controls=VCEM-70-000001

# Run against a target vCenter appliance and limit the controls run that match a regex string
inspec exec C:\Inspec\Profiles\vmware-vcsa-7.0-stig-baseline -t ssh://root@10.1.1.1 --password 'password' --controls=/VCEM-70/

The arguments provided in the example can be combined as needed.

For more options, see InSpec Executable.

References

For the full InSpec documentation, see the InSpec Installation Instructions. For Cinc Auditor, see the Cinc Project Download Page.

3.3 - Ansible

How to use and install Ansible

Ansible is an IT automation tool. It can configure systems, deploy software, and orchestrate more advanced IT tasks such as continuous deployments or zero downtime rolling updates.

Ansible’s main goals are simplicity and ease-of-use. It also has a strong focus on security and reliability, featuring a minimum of moving parts, usage of OpenSSH for transport (with other transports and pull modes as alternatives), and a language that is designed around auditability by humans–even those not familiar with the program.

Ansible concepts talk about “Control nodes” and “Managed nodes”. Controls nodes are the machine that runs Ansible and where it is installed. The managed nodes are systems Ansible is managing and do not require Ansible to be installed.

Prerequisites

  • Linux/UNIX only for control nodes.
  • Windows is supported for managed nodes only. You can install Ansible on a WSL instance on Windows.
  • Python 3.9 or newer for the latest version. More details here.

Installation

Installation of Ansible varies by platform with detailed instructions available here.

Concepts

Playbooks

Ansible Playbooks offer a repeatable, re-usable, simple configuration management and multi-machine deployment system, one that is well suited to deploying complex applications. If you need to execute a task with Ansible more than once, write a playbook and put it under source control. Then you can use the playbook to push out new configurations or confirm the configurations of remote systems.

Playbook structure example:

vmware-photon-4.0-stig-ansible-hardening
├── defaults
   └── main.yml
├── handlers
   └── main.yml
|── meta
   └── main.yml
├── tasks
   ├── main.yml
   └── photon.yml
├── templates
   ├── audit.STIG.rules
   └── issue
├── vars
   └── main.yml
└── playbook.yml
└── requirements.yml
└── vars-example.yml

By default Ansible will look in each directory for a main.yml file.

The purpose of each folder is as follows:
defaults/main.yml - Default variables for the role/playbook. These variables have the lowest priority of any variables available, and can be easily overridden by any other variable. We use these variables to enable/disable STIG controls individually.
handlers/main.yml - Sometimes you want a task to run only when a change is made on a machine. For example, you may want to restart a service if a task updates the configuration of that service, but not if the configuration is unchanged. Ansible uses handlers to address this use case. Handlers are tasks that only run when notified.
meta/main.yml - metadata for the role, including role dependencies and optional Galaxy metadata such as platforms supported.
tasks/main.yml - The main list of tasks that the playbook executes.
templates - Templates that the playbook uses. For example, any complete files we may be replacing instead of editing.
vars/main.yml - Other variables for the role. We place variables for setting values in here. For example, variables for syslog or ntp servers.
playbook.yml - A list of plays that define the order in which Ansible performs operations, from top to bottom, to achieve an overall goal.
requirements.yml - Some playbooks may depend on collections or other roles and are specified here for installation with the ansible-galaxy command.
vars-example.yml - We may provide example vars files to use and customize when running a playbook for your environment. This is where we would recommend specifying any variable values instead of editing the playbook files themselves.

Roles

Ansible roles can be thought of as playbooks inside of playbooks and meant to be reusable. Our Photon OS playbooks may be a dependency in another playbook and used as a role so that we do not have to maintain multiple copies of the Photon playbook.

They have the same folder structure as a playbook and will be inside a roles folder in the playbook or specified as a dependency in the playbook.yml.

Example playbook.yml with roles. Note the Photon role is external to this playbooks structure.

- name: vmware-vcsa-8.0-stig-ansible-hardening
  hosts: all
  roles:
    - role: vmware-photon-3.0-stig-ansible-hardening
      vars:
        var_syslog_authpriv_log: '/var/log/audit/sshinfo.log'
    - role: eam
    - role: envoy
    - role: lookup
    - role: perfcharts
    - role: postgresql
    - role: sts
    - role: ui
    - role: vami

Collections/Modules

A format in which Ansible content is distributed that can contain playbooks, roles, modules, and plugins. You can install and use collections through Ansible Galaxy.

In this project we primarily use collections to install modules which are the code or binaries that Ansible copies to and executes on each managed node (when needed) to accomplish the action defined in each Task. Each module has a particular use, from administering users on a specific type of database to managing VLAN interfaces on a specific type of network device.

In the example below we are using the ansible.builtin.template module.

###################################################################################################################################
- name: PHTN-40-000003 - Update audit.STIG.rules file
  tags: [PHTN-40-000003, PHTN-40-000019, PHTN-40-000031, PHTN-40-000076, PHTN-40-000078, PHTN-40-000107, PHTN-40-000173, PHTN-40-000175, PHTN-40-000204, PHTN-40-000238, auditd]
  when: run_auditd_rules | bool
  block:
    - name: PHTN-40-000003 - Copy auditd rules template
      ansible.builtin.template:
        src: audit.STIG.rules
        dest: '{{ var_auditd_rule_file }}'
        owner: root
        group: root
        mode: '0640'
        force: true
      notify:
        - reload auditd

For a list of all available modules, see Index of all Modules.

Installing Collections and Roles

# Install a collection directly from ansible galaxy
ansible-galaxy collection install ansible-posix

# Install a collection from a downloaded tar.gz
ansible-galaxy collection install ansible-posix-1.5.4.tar.gz

# Install a role from a downloaded tar.gz of the role
ansible-galaxy role install --roles-path /usr/share/ansible/roles vmware-photon-3.0-stig-ansible-hardening-v1r9.tar.gz

Tags

Tags in Ansible offer a way to only run a specific task or exclude tasks. In the playbooks provided we tag tasks with STIG IDs and sometimes a category such as sshd if there are many tasks that touch ssh.

When running a playbook you can specify --tags or --skip-tags at the cli followed by a list of tags.

Inventory

Ansible automates tasks on managed nodes or “hosts” in your infrastructure, using a list or group of lists known as inventory. You can pass host names at the command line, but most Ansible users create inventory files. Your inventory defines the managed nodes you automate, with groups so you can run automation tasks on multiple hosts at the same time. Once your inventory is defined, you use patterns to select the hosts or groups you want Ansible to run against.

The examples we provide in this documentation just pass host names at the command line but if creating inventory files is desired that can be done as well but is outside of the scope here.

For more information on inventory, see Building Ansible inventories.

Check mode

Check mode runs a playbook and simulates the results. Not all modules support check mode and we do not write our playbooks with check mode in mind.

Running Ansible Examples and Common Arguments

The examples below are for running Ansible with the vSphere 8 VCSA profile.

# Run all controls on a target vCenter. Prompts for user password(-k), displays verbose output(-v).
ansible-playbook -i '10.1.1.1', -u 'root' /path/to/vmware-vcsa-8.0-stig-ansible-hardening/playbook.yml -k -v

# Specify a vars files to pass variables to the playbook.
ansible-playbook -i '10.1.1.1', -u 'root' /path/to/vmware-vcsa-8.0-stig-ansible-hardening/playbook.yml -k -v --extra-vars @/path/to/vmware-vcsa-8.0-stig-ansible-hardening/vars-example.yml

# Specify a tag to only run tasks that match the tag.
ansible-playbook -i '10.1.1.1', -u 'root' /path/to/vmware-vcsa-8.0-stig-ansible-hardening/playbook.yml -k -v --tags VCEM-80-000001

# Specify a tag to skip tasks that match the tag.
ansible-playbook -i '10.1.1.1', -u 'root' /path/to/vmware-vcsa-8.0-stig-ansible-hardening/playbook.yml -k -v --skip-tags VCEM-80-000001

The arguments provided in the example can be combined as needed.

For more options, see ansible-playbook.

Host Key Checking

Ansible enables host key checking by default. Checking host keys guards against server spoofing and man-in-the-middle attacks. If a host is not trusted before running Ansible you may see an error that the authenticity of the host cannot be verified.

This can be corrected by running the following:

ssh-keyscan -H <IP or FQDN> >> /root/.ssh/known_hosts

See managing-host-key-checking for more details.

References

For the full Ansible documentation, see Ansible Documentation.

3.4 - SAF CLI

How to use and install MITRE’s SAF CLI

The MITRE Security Automation Framework (SAF) Command Line Interface (CLI) brings together applications, techniques, libraries, and tools developed by MITRE and the security community to streamline security automation for systems and DevOps pipelines.

In this context the SAF CLI is used for the following tasks:

  • Creating and applying manual attestations to InSpec results.
  • Converting InSpec results to a STIG checklist(CKL) format.
  • Converting STIG XCCDF files to InSpec profiles to stub out a new profile.

Prerequisites

  • Windows, Linux, and MAC are supported.

Installation

Download the package for your OS for a release here.

For a full list of installation options, see Installation.

Usage

Creating and applying manual attestations

Manual attestation is helpful in scenarios where a control can’t be automated for some reason(no API, policy based, etc) but you would still like to include an evaluation of these controls with your automated reports.

The example covered will work with InSpec results but this process can be applied to any report from various supported security tools in the SAF ecosystem.

Creating a manual attestation file

An attestation file can be created using SAF CLI or by just manually creating a file.

Using SAF CLI to create a file

# Provide your report.json as input and in this example we are using yml as the format but json is also supported
saf attest create -i .\vSphere_ESXi_8.0.1_GA_21495797_ootb_04-12-2023-09-05.json -o .\attestation-example.yml -t yml

# You can search for controls by entering a partial STIG ID
Enter a control ID, search for a control, or enter 'q' to exit: esxi-80-00000
        ESXI-80-000005: The ESXi host must enforce the limit of three consecutive invalid logon attempts by a user.
        ESXI-80-000006: The ESXi host must display the Standard Mandatory DOD Notice and Consent Banner before granting access to the system via the Direct Console User Interface (DCUI).
        ESXI-80-000008: The ESXi host must enable lockdown mode.
# For the control you want to attest to you must enter the control ID exactly since this is case sensitive. You will then be prompted to fill out some questions.
Enter a control ID, search for a control, or enter 'q' to exit: ESXI-80-000006
Attestation explanation: The banner is displayed
Frequency (1d/3d/1wk/2wk/1m/3m/6m/1y/1.5y/custom): 1y
Enter status ((p)assed/(f)ailed): passed
Updated By: RL
Enter a control ID, search for a control, or enter 'q' to exit: q

This results in a yaml file that looks like the following:

- control_id: ESXI-80-000006
  explanation: The banner is displayed
  frequency: 1y
  status: passed
  updated: 2023-05-17T13:32:32.945Z
  updated_by: RL

Now that you know the format it may be easier to just add all of the controls needing manual attestation to the attestation file directly.

Applying an attestation file to a result file

The next step is to apply the attestation file to our original report to then create a new one that includes our manual attestations.

# Provide the original report followed by the attestation file created then for the output provide a name for a new report
saf attest apply -i .\vSphere_ESXi_8.0.1_GA_21495797_ootb_04-12-2023-09-05.json .\attestation-example.yml -o .\My_new_report_with_attestations.json

If we examine the new report we will see this on the control we provided an attestation for:

{
  "code_desc": "Manually verified status provided through attestation",
  "status": "passed",
  "message": "Attestation:\nStatus: passed\nExplanation: The banner is displayed\n\nUpdated: 2023-05-17T13:32:32.945Z\nUpdated By: RL\nFrequency: 1y",
  "start_time": "2023-05-17T13:49:06.601Z"
}

Now when we convert this to a CKL file this information will be carried forward.

Converting InSpec results to CKL

saf convert hdf2ckl -i .\My_new_report_with_attestations.json -o my_new_ckl.ckl --hostname myesxihost --fqdn myesxihost.local --ip 10.1.2.3 --mac 00:00:00:00:00:00

After importing into STIG viewer you can see the manual attestion on the ESXI-80-000006 in the finding details.
alt text

The host info provided is also populated in the target data.
alt text

Converting XCCDF to InSpec

When starting a new profile for a STIG it would not be feasible to manually populate all of a STIGs metadata (title,check,fix,discussion,ids,severity,etc) into the control files.

SAF CLI offers a command to take an XCCDF xml file from a STIG as an input and output a stubbed out InSpec profile that includes all of this data where you then only need to add your tests for each control.

# The -T argument sets which ID to use as the control ID for InSpec. In this case we prefer STIG IDs as they are easier to reference. Other options are rule(Rule ID) and group(Vul ID)
saf generate xccdf_benchmark2inspec_stub -T version -i .\U_VMware_vSphere_8_ESXi_STIG_Readiness_Guide_V1R1-xccdf.xml -o my_esxi_profile

This will give us a profile with this folder structure:

my_esxi_profile
├── controls
│   ├── ESXI-80-000005.rb
│   └── ESXI-80-000006.rb
│   └── ...
├── libraries
└── inspec.yml

Control file example:

control 'ESXI-80-000005' do
  title 'The ESXi host must enforce the limit of three consecutive invalid logon attempts by a user.'
  desc 'By limiting the number of failed logon attempts, the risk of unauthorized access via user password guessing, otherwise known as brute forcing, is reduced. Once the configured number of attempts is reached, the account is locked by the ESXi host.'
  desc 'check', 'From the vSphere Client, go to Hosts and Clusters.

Select the ESXi Host >> Configure >> System >> Advanced System Settings.

Select the "Security.AccountLockFailures" value and verify it is set to "3".

or

From a PowerCLI command prompt while connected to the ESXi host, run the following command:

Get-VMHost | Get-AdvancedSetting -Name Security.AccountLockFailures

If the "Security.AccountLockFailures" setting is set to a value other than "3", this is a finding.'
  desc 'fix', 'From the vSphere Client, go to Hosts and Clusters.

Select the ESXi Host >> Configure >> System >> Advanced System Settings.

Click "Edit". Select the "Security.AccountLockFailures" value and configure it to "3".

or

From a PowerCLI command prompt while connected to the ESXi host, run the following command:

Get-VMHost | Get-AdvancedSetting -Name Security.AccountLockFailures | Set-AdvancedSetting -Value 3'
  impact 0.5
  tag check_id: 'N/A'
  tag severity: 'medium'
  tag gid: 'V-ESXI-80-000005'
  tag rid: 'SV-ESXI-80-000005'
  tag stig_id: 'ESXI-80-000005'
  tag gtitle: 'SRG-OS-000021-VMM-000050'
  tag documentable: nil
  tag cci: ['CCI-000044']
  tag nist: ['AC-7 a']
end

References

For the more information, see the SAF CLI Documentation.

3.5 - Heimdall

How to use and install MITRE’s Heimdall Server

MITRE’s Heimdall Server allows you to visualize, store, and compare scan results from various security tools.

Prerequisites

  • Infrastructure to deploy Heimdall Server on.

Installation

Heimdall is most easily deployed via Docker or Kubernetes.

Demo instances are available at Heimdall Lite or Heimdall.

Note: The demo environments are for demonstration use only, please do not provide any personal identifying information or load real mission data into this system, even if the data is from non-production environments.

For a full list of installation options, see Installation.

Usage

All of the documentation below will be in the context of working with InSpec results. Using results from other tools may vary.

Viewing Results

After login in you can simply drag your files over to the window to load or click “Choose files to upload” and browse to your result file.
alt text

After loading a result you are shown a visualization of that result where you can view the compliance status and filter the results based on any available criteria, for example, only showing controls that failed.
alt text

Further down the page you can drill down into the specifics of each control and the test results.
alt text

Exporting Results

Results can also be exported to various other formats as shown in the screenshot below.
alt text

Comparing Results

If you have more than one scan you would like to compare from like scan results you can load them both and enable the comparison view using the button show below.
alt text

After the comparison view is enabled you are presented with visualization of the differences between the two results and which controls changed status.
alt text

References

For the more information, see the Heimdall Github Page.

4 - Tutorials

How to use the automation examples for VMware products.

4.1 - NSX

Performing compliance automation tasks for NSX.

4.1.1 - Audit NSX 4.x

Auditing NSX 4.x for STIG Compliance

Overview

Auditing NSX 4.x for STIG compliance involves scanning the NSX Managers, DFW, and any gateways deployed.

To audit NSX using InSpec we utilize the local transport to connect via the REST API and query it’s configuration.

Prerequisites

Versions listed below were used for this documentation. Other versions of these tools may work as well but if issues are found it is recommended to try the versions listed here.

  • InSpec/CINC Auditor 6.6.0
  • SAF CLI 1.4.0
  • STIG Viewer 2.17
  • An NSX 4.x environment. The environment used in these examples has 1 T0 Gateway configured with BGP to an upstream router and 1 T1 Gateway deployed.

Assumptions

  • Commands are being ran from a Linux machine. Windows will also work but paths and commands may need to be adjusted from the examples.
  • The DOD Compliance and Automation repository downloaded and extracted to /usr/share/stigs.
  • CINC Auditor is used in lieu of InSpec. If InSpec is used replace cinc-auditor with inspec when running commands.

Auditing NSX

Generate API Session Token

This profile uses Session-Based authentication to authenticate with NSX for auditing. A session token and cookie must be generated and provided an input for the profile. This can be generated in various ways via curl, tools like Postman, etc. For more information see the NSX API Documentation.

Note: If the user is a remote user, append “@domain” to the username, for example, “joe@example.com”. The domain must match a domain for a configured VIDM identity source or a configured LDAP identity source.

Curl example:

curl -k -i -X POST -d 'j_username=admin&j_password=C3.UwJ7TTK1P' https://10.215.77.149/api/session/create

# Example response
HTTP/1.1 200 OK
set-cookie: JSESSIONID=A6903A10F3AE7EB328F12EAF796053F5; Path=/; Secure; HttpOnly; SameSite=Lax
x-xsrf-token: ead781b8-0e0c-456f-a04a-584e9ae2e45a
cache-control: no-cache, no-store, max-age=0, must-revalidate
pragma: no-cache
expires: 0
x-xss-protection: 1; mode=block
x-frame-options: SAMEORIGIN
x-content-type-options: nosniff
content-type: application/json
content-length: 107
date: Thu, 29 Jun 2023 21:39:58 GMT
strict-transport-security: max-age=31536000; includeSubDomains
content-security-policy: frame-src 'self' blob:; frame-ancestors 'self'
server: envoy

{"roles":[{"role":"superusers","permissions":["read-api","read-write-api","read-cli","read-write-cli"]}]}
curl -k -i -X POST -d 'j_username=admin&j_password=C3.UwJ7TTK1P' https://10.215.77.149/api/session/create

# Example response
HTTP/1.1 200 OK
set-cookie: JSESSIONID=A6903A10F3AE7EB328F12EAF796053F5; Path=/; Secure; HttpOnly; SameSite=Lax
x-xsrf-token: ead781b8-0e0c-456f-a04a-584e9ae2e45a
cache-control: no-cache, no-store, max-age=0, must-revalidate
pragma: no-cache
expires: 0
x-xss-protection: 1; mode=block
x-frame-options: SAMEORIGIN
x-content-type-options: nosniff
content-type: application/json
content-length: 107
date: Thu, 29 Jun 2023 21:39:58 GMT
strict-transport-security: max-age=31536000; includeSubDomains
content-security-policy: frame-src 'self' blob:; frame-ancestors 'self'
server: envoy

{"roles":[{"role":"superusers","permissions":["read-api","read-write-api","read-cli","read-write-cli"]}]}

Update profile inputs

Included in the vmware-nsx-4.x-stig-baseline is an example inputs file with variables relevant to NSX. This is used to provide InSpec with values specific to the environment being audited.

Open the inputs file for editing.

# Navigate to the InSpec profile folder
cd /usr/share/stigs/nsx/4.x/v1r2-srg/inspec/vmware-nsx-4.x-stig-baseline/

# Edit the inputs file
vi inputs-nsx-4.x-example.yml
# Navigate to the InSpec profile folder
cd /usr/share/stigs/nsx/4.x/v1r1-srg/inspec/vmware-nsx-4.x-stig-baseline/

# Edit the inputs file
vi inputs-nsx-4.x-example.yml

Update the inputs as shown below with values relevant to your environment. Specifically nsxManager,sessionToken,sessionCookieId,syslogServers,sftpServer,ntpServers,ntpServers,and nsxtVersion at a minimum. The other inputs are optional depending on your environment.

# NSX Manager IP or FQDN
nsxManager: '10.1.2.3'
# Session token generated for access to NSX. Example ead781b8-0e0c-456f-a04a-584e9ae2e45a
sessionToken: ''
# Session cookie id generated for access to NSX. Example 'JSESSIONID=2A165FCF851CA50FCD038DFC8E770038'
sessionCookieId: ''
# Manager
# Provide a list of authorized users and their roles to validate assigned permissions in NSX. The default local users and their roles are provided as an example. This currently only validates roles assigned to all of NSX and not to Projects or other scopes.
authorizedPermissions:
  admin:
    role: 'Enterprise Admin'
  audit:
    role: 'Auditor'
  guestuser1:
    role: 'Auditor'
  guestuser2:
    role: 'Auditor'
# Enter the environment specific syslog server vCenter should be forwarding logs to.
syslogServers:
  - 'loginsight.test.com'
# Enter the environment specific time servers.
ntpServers:
  - 'time-a-g.nist.gov'
  - 'time-b-g.nist.gov'
# Enter latest NSX version. Example '4.1.1.0'
nsxtVersion: '4.1.2.3'
# Enter an array of T0 Gateways that are approved to have multicast enabled.
t0multicastlist: []
# Enter an array of T0 Gateways interfaces that are approved to have multicast enabled.
t0mcinterfacelist: []
# Enter an array of T0 Gateways that are approved to have DHCP enabled.
t0dhcplist: []
# Enter an array of T1 Gateways that are approved to have DHCP enabled.
t1dhcplist: []
# Enter an array of T1 Gateways that are approved to have multicast enabled.
t1multicastlist: []
# NSX Manager IP or FQDN
nsxManager: ''
# Session token generated for access to NSX
sessionToken: ''
# Session cookie id generated for access to NSX. Example 'JSESSIONID=2A165FCF851CA50FCD038DFC8E770038'
sessionCookieId: ''
# Manager
# Enter the environment specific syslog server vCenter should be forwarding logs to.
syslogServers:
  - 'loginsight.test.com'
# Enter the environment specific time servers.
ntpServer1: 'time-a-g.nist.gov'
ntpServer2: 'time-b-g.nist.gov'
# Enter latest NSX version. Example '4.1.1.0'
nsxtVersion: '4.1.1.0'
# Enter an array of T0 Gateways that are approved to have multicast enabled.
t0multicastlist: []
# Enter an array of T0 Gateways interfaces that are approved to have multicast enabled.
t0mcinterfacelist: []
# Enter an array of T0 Gateways that are approved to have DHCP enabled.
t0dhcplist: []
# Enter an array of T1 Gateways that are approved to have DHCP enabled.
t1dhcplist: []
# Enter an array of T1 Gateways that are approved to have multicast enabled.
t1multicastlist: []

Run the audit

In this example we will be scanning all NSX components, specifying an inputs file, and outputting a report to the CLI and to a JSON file.

# Navigate to the InSpec profile folder
cd /usr/share/stigs/nsx/4.x/v1r2-srg/inspec/vmware-nsx-4.x-stig-baseline/

# Run the audit
cinc-auditor exec . --show-progress --enhanced-outcomes --input-file inputs-nsx-4.x-example.yml --reporter=cli json:/tmp/reports/MyNSXReport.json

# Shown below is the last part of the output at the CLI.
  ×  NT1F-4X-000020: The NSX Tier-1 Gateway Firewall must be configured to send traffic log entries to a central audit server. (1 failed)
     ✔  HTTP GET on https://10.215.77.149/policy/api/v1/search?query=( resource_type:TransportNode AND node_deployment_info.resource_type:EdgeNode ) status is expected to cmp == 200
     ✔  HTTP GET on https://10.215.77.149/api/v1/transport-nodes/a40c4ea4-16a1-11ee-8640-000c296f3e4c/node/services/syslog/exporters status is expected to cmp == 200
     ×  No syslog servers are configured on Edge Node: rlakey-svc.nsxedge-ob-21981742-1-stigtest is expected not to cmp == []

     expected: []
          got: []

     (compared using `cmp` matcher)

  ↺  NT1F-4X-000027: The NSX Tier-1 Gateway Firewall must be configured to inspect traffic at the application layer. (1 skipped)
     ✔  HTTP GET on https://10.215.77.149/policy/api/v1/infra/tier-1s status is expected to cmp == 200
     ↺  This check is a manual or policy based check and must be reviewed manually.


Profile:   VMware NSX 4.x Tier-1 Gateway Router STIG InSpec Profile (VMware NSX 4.x Tier-1 Gateway Router STIG InSpec Profile)
Version:   1.1
Target:    local://
Target ID: e45dd517-9256-59e3-8503-3351c863444c

  ↺  NT1R-4X-000016: The NSX Tier-1 Gateway must be configured to have all inactive interfaces removed. (1 skipped)
     ✔  HTTP GET on https://10.215.77.149/policy/api/v1/infra/tier-1s status is expected to cmp == 200
     ↺  This is a manual check. Review T1 interfaces and determine if any existing interfaces are orphaned and should be removed.
  ✔  NT1R-4X-000027: The NSX Tier-1 Gateway must be configured to have the DHCP service disabled if not in use.
     ✔  HTTP GET on https://10.215.77.149/policy/api/v1/infra/tier-1s status is expected to cmp == 200
{"tier0_path"=>"/infra/tier-0s/Tier0Gateway1", "failover_mode"=>"NON_PREEMPTIVE", "enable_standby_relocation"=>false, "route_advertisement_types"=>["TIER1_CONNECTED", "TIER1_STATIC_ROUTES"], "route_advertisement_rules"=>[{"name"=>"Rule 1", "subnets"=>["192.168.1.0/24", "192.168.2.0/24"], "prefix_operator"=>"GE", "action"=>"PERMIT"}], "force_whitelisting"=>false, "default_rule_logging"=>false, "disable_firewall"=>false, "ipv6_profile_paths"=>["/infra/ipv6-ndra-profiles/default", "/infra/ipv6-dad-profiles/default"], "pool_allocation"=>"ROUTING", "advanced_config"=>{"traffic_back_to_source"=>false, "centralized_mode_enabled"=>false}, "resource_type"=>"Tier1", "id"=>"Tier1Gateway1", "display_name"=>"Tier1Gateway1", "description"=>"Tier1-1 created through automation", "path"=>"/infra/tier-1s/Tier1Gateway1", "relative_path"=>"Tier1Gateway1", "parent_path"=>"/infra", "remote_path"=>"", "unique_id"=>"4f4dd7f0-30d7-4dff-8e9b-14524d6284a1", "realization_id"=>"4f4dd7f0-30d7-4dff-8e9b-14524d6284a1", "owner_id"=>"f1a08ebb-158a-4bed-908d-14cd342e4f9a", "marked_for_delete"=>false, "overridden"=>false, "_create_time"=>1688059851013, "_create_user"=>"admin", "_last_modified_time"=>1688059851013, "_last_modified_user"=>"admin", "_system_owned"=>false, "_protection"=>"NOT_PROTECTED", "_revision"=>0} ["dhcp_config_paths"] is expected to equal nil
  ↺  NT1R-4X-000102: The NSX Tier-1 Gateway must be configured to advertise a hop limit of at least 32 in Router Advertisement messages for IPv6 stateless auto-configuration deployments. (1 skipped)
     ✔  HTTP GET on https://10.215.77.149/policy/api/v1/infra/global-config status is expected to cmp == 200
     ↺  IPv6 Forwarding is not enabled. This is Not Applicable.
  ✔  NT1R-4X-000107: The NSX Tier-1 Gateway must be configured to have multicast disabled if not in use.
     ✔  HTTP GET on https://10.215.77.149/policy/api/v1/infra/tier-1s status is expected to cmp == 200
     ✔  HTTP GET on https://10.215.77.149/policy/api/v1/infra/tier-1s/Tier1Gateway1/locale-services/Tier1LocalServices-1/multicast status is expected to cmp == 404


Profile Summary: 21 successful controls, 30 control failures, 10 controls skipped
Test Summary: 162 successful, 57 failures, 12 skipped
# Navigate to the InSpec profile folder
cd /usr/share/stigs/nsx/4.x/v1r1-srg/inspec/vmware-nsx-4.x-stig-baseline/

# Run the audit
cinc-auditor exec . --show-progress --enhanced-outcomes --input-file inputs-nsx-4.x-example.yml --reporter=cli json:/tmp/reports/MyNSXReport.json

# Shown below is the last part of the output at the CLI.
  ×  NT1F-4X-000020: The NSX Tier-1 Gateway Firewall must be configured to send traffic log entries to a central audit server. (1 failed)
     ✔  HTTP GET on https://10.215.77.149/policy/api/v1/search?query=( resource_type:TransportNode AND node_deployment_info.resource_type:EdgeNode ) status is expected to cmp == 200
     ✔  HTTP GET on https://10.215.77.149/api/v1/transport-nodes/a40c4ea4-16a1-11ee-8640-000c296f3e4c/node/services/syslog/exporters status is expected to cmp == 200
     ×  No syslog servers are configured on Edge Node: rlakey-svc.nsxedge-ob-21981742-1-stigtest is expected not to cmp == []

     expected: []
          got: []

     (compared using `cmp` matcher)

  ↺  NT1F-4X-000027: The NSX Tier-1 Gateway Firewall must be configured to inspect traffic at the application layer. (1 skipped)
     ✔  HTTP GET on https://10.215.77.149/policy/api/v1/infra/tier-1s status is expected to cmp == 200
     ↺  This check is a manual or policy based check and must be reviewed manually.


Profile:   VMware NSX 4.x Tier-1 Gateway Router STIG InSpec Profile (VMware NSX 4.x Tier-1 Gateway Router STIG InSpec Profile)
Version:   1.1
Target:    local://
Target ID: e45dd517-9256-59e3-8503-3351c863444c

  ↺  NT1R-4X-000016: The NSX Tier-1 Gateway must be configured to have all inactive interfaces removed. (1 skipped)
     ✔  HTTP GET on https://10.215.77.149/policy/api/v1/infra/tier-1s status is expected to cmp == 200
     ↺  This is a manual check. Review T1 interfaces and determine if any existing interfaces are orphaned and should be removed.
  ✔  NT1R-4X-000027: The NSX Tier-1 Gateway must be configured to have the DHCP service disabled if not in use.
     ✔  HTTP GET on https://10.215.77.149/policy/api/v1/infra/tier-1s status is expected to cmp == 200
{"tier0_path"=>"/infra/tier-0s/Tier0Gateway1", "failover_mode"=>"NON_PREEMPTIVE", "enable_standby_relocation"=>false, "route_advertisement_types"=>["TIER1_CONNECTED", "TIER1_STATIC_ROUTES"], "route_advertisement_rules"=>[{"name"=>"Rule 1", "subnets"=>["192.168.1.0/24", "192.168.2.0/24"], "prefix_operator"=>"GE", "action"=>"PERMIT"}], "force_whitelisting"=>false, "default_rule_logging"=>false, "disable_firewall"=>false, "ipv6_profile_paths"=>["/infra/ipv6-ndra-profiles/default", "/infra/ipv6-dad-profiles/default"], "pool_allocation"=>"ROUTING", "advanced_config"=>{"traffic_back_to_source"=>false, "centralized_mode_enabled"=>false}, "resource_type"=>"Tier1", "id"=>"Tier1Gateway1", "display_name"=>"Tier1Gateway1", "description"=>"Tier1-1 created through automation", "path"=>"/infra/tier-1s/Tier1Gateway1", "relative_path"=>"Tier1Gateway1", "parent_path"=>"/infra", "remote_path"=>"", "unique_id"=>"4f4dd7f0-30d7-4dff-8e9b-14524d6284a1", "realization_id"=>"4f4dd7f0-30d7-4dff-8e9b-14524d6284a1", "owner_id"=>"f1a08ebb-158a-4bed-908d-14cd342e4f9a", "marked_for_delete"=>false, "overridden"=>false, "_create_time"=>1688059851013, "_create_user"=>"admin", "_last_modified_time"=>1688059851013, "_last_modified_user"=>"admin", "_system_owned"=>false, "_protection"=>"NOT_PROTECTED", "_revision"=>0} ["dhcp_config_paths"] is expected to equal nil
  ↺  NT1R-4X-000102: The NSX Tier-1 Gateway must be configured to advertise a hop limit of at least 32 in Router Advertisement messages for IPv6 stateless auto-configuration deployments. (1 skipped)
     ✔  HTTP GET on https://10.215.77.149/policy/api/v1/infra/global-config status is expected to cmp == 200
     ↺  IPv6 Forwarding is not enabled. This is Not Applicable.
  ✔  NT1R-4X-000107: The NSX Tier-1 Gateway must be configured to have multicast disabled if not in use.
     ✔  HTTP GET on https://10.215.77.149/policy/api/v1/infra/tier-1s status is expected to cmp == 200
     ✔  HTTP GET on https://10.215.77.149/policy/api/v1/infra/tier-1s/Tier1Gateway1/locale-services/Tier1LocalServices-1/multicast status is expected to cmp == 404


Profile Summary: 21 successful controls, 30 control failures, 10 controls skipped
Test Summary: 162 successful, 57 failures, 12 skipped

Convert the results to CKL

If a STIG Viewer CKL file is needed then the results from the scans can be converted to CKL with the SAF CLI.

# Converting the scan results from the prior section to CKL
saf convert hdf2ckl -i /tmp/reports/MyNSXReport.json -o /tmp/reports/MyNSXReport.ckl --hostname 10.215.77.149 --fqdn 10.215.77.149 --ip 10.215.77.149 --mac 00:00:00:00:00:00

Opening the CKL file in STIG Viewer will look like the screenshot below. Note the InSpec results are included in the Finding Details pane.

alt text

4.1.2 - Remediate NSX 4.x

Remediating NSX 4.x for STIG Compliance

Overview

Remediating NSX 4.x for STIG compliance involves configuring the NSX Managers, DFW, and any gateways deployed.

To remediate NSX, Ansible is the automation tool used to interact with the NSX REST API.

Prerequisites

Versions listed below were used for this documentation. Other versions of these tools may work as well but if issues are found it is recommended to try the versions listed here.

  • Ansible 2.14.2
  • Install JMESPath for community.general.json_query collection.
  • An NSX 4.x environment. The environment used in these examples has 1 T0 Gateway configured with BGP to an upstream router and 1 T1 Gateway deployed.
  • An account with sufficient privileges to configure NSX.

Assumptions

  • Commands are being ran from a Linux machine.
  • The DOD Compliance and Automation repository downloaded and extracted to /usr/share/stigs.
  • Ansible installed and all playbook dependencies resolved as provided in the requirements.yml file in each playbook. Install with ansible-galaxy roles install -r requirements.yml.

Important Considerations

Below is a table of controls selected for consideration but all controls should be examined for impact before implementing.

These can be turned on/off by with a variable that must be set to true as a condition for these tasks to run. See Update vars file for more details.

STIG IDTitleNotes
NDFW-4X-000015The NSX Distributed Firewall must limit the effects of packet flooding types of denial-of-service (DoS) attacks.
NDFW-4X-000016The NSX Distributed Firewall must deny network communications traffic by default and allow network communications traffic by exception.Ensure DFW rules are created to allow authorized traffic.
NDFW-4X-000029The NSX Distributed Firewall must configure SpoofGuard to restrict it from accepting outbound packets that contain an illegitimate address in the source address.Develop an operational plan to manage Spoofguard and identity workloads multiple IPs, etc, that may have issues.
NDFW-4X-000034The NSX Distributed Firewall must configure an IP Discovery profile to disable trust on every use methods.Develop an operational plan to manage Spoofguard and identity workloads multiple IPs, etc, that may have issues.
NT0F-4X-000015The NSX Tier-0 Gateway Firewall must manage excess bandwidth to limit the effects of packet flooding types of denial-of-service (DoS) attacks.
NT0F-4X-000016The NSX Tier-0 Gateway Firewall must deny network communications traffic by default and allow network communications traffic by exception.Ensure gateway firewall rules are created to allow authorized traffic.
NT0R-4X-000013The NSX Tier-0 Gateway must be configured to disable Protocol Independent Multicast (PIM) on all interfaces that are not required to support multicast routing.Ensure any gateways that are authorized to enable multicast are listed in the vars file.
NT0R-4X-000027The NSX Tier-0 Gateway must be configured to have the DHCP service disabled if not in use.Ensure any gateways that are authorized to enable DHCP are listed in the vars file.
NT0R-4X-000107The NSX Tier-0 Gateway must be configured to have multicast disabled if not in use.Ensure any gateways that are authorized to enable multicast are listed in the vars file.
NT1F-4X-000015The NSX Tier-1 Gateway Firewall must manage excess bandwidth to limit the effects of packet flooding types of denial-of-service (DoS) attacks.
NT1F-4X-000016The NSX Tier-1 Gateway Firewall must deny network communications traffic by default and allow network communications traffic by exception.Ensure gateway firewall rules are created to allow authorized traffic.
NT1R-4X-000027The NSX Tier-1 Gateway must be configured to have the DHCP service disabled if not in use.Ensure any gateways that are authorized to enable DHCP are listed in the vars file.
NT1R-4X-000107The NSX Tier-1 Gateway must be configured to have multicast disabled if not in use.Ensure any gateways that are authorized to enable multicast are listed in the vars file.

Also not all controls are covered by the Ansible playbook and may require manual remediation.

Remediating NSX

To remediate NSX we have provided an Ansible playbook that will target an NSX Manager over the REST API and configure any non-compliant controls.

Generate API Session Token

This profile uses Session-Based authentication to authenticate with NSX for auditing. A session token and cookie must be generated and provided an input for the profile. This can be generated in various ways via curl, tools like Postman, etc. For more information see the NSX API Documentation.

Note: If the user is a remote user, append “@domain” to the username, for example, “joe@example.com”. The domain must match a domain for a configured VIDM identity source or a configured LDAP identity source.

Curl example:

curl -k -i -X POST -d 'j_username=admin&j_password=C3.UwJ7TTK1P' https://10.215.77.149/api/session/create

# Example response
HTTP/1.1 200 OK
set-cookie: JSESSIONID=A6903A10F3AE7EB328F12EAF796053F5; Path=/; Secure; HttpOnly; SameSite=Lax
x-xsrf-token: ead781b8-0e0c-456f-a04a-584e9ae2e45a
cache-control: no-cache, no-store, max-age=0, must-revalidate
pragma: no-cache
expires: 0
x-xss-protection: 1; mode=block
x-frame-options: SAMEORIGIN
x-content-type-options: nosniff
content-type: application/json
content-length: 107
date: Thu, 29 Jun 2023 21:39:58 GMT
strict-transport-security: max-age=31536000; includeSubDomains
content-security-policy: frame-src 'self' blob:; frame-ancestors 'self'
server: envoy

{"roles":[{"role":"superusers","permissions":["read-api","read-write-api","read-cli","read-write-cli"]}]}
curl -k -i -X POST -d 'j_username=admin&j_password=C3.UwJ7TTK1P' https://10.215.77.149/api/session/create

# Example response
HTTP/1.1 200 OK
set-cookie: JSESSIONID=A6903A10F3AE7EB328F12EAF796053F5; Path=/; Secure; HttpOnly; SameSite=Lax
x-xsrf-token: ead781b8-0e0c-456f-a04a-584e9ae2e45a
cache-control: no-cache, no-store, max-age=0, must-revalidate
pragma: no-cache
expires: 0
x-xss-protection: 1; mode=block
x-frame-options: SAMEORIGIN
x-content-type-options: nosniff
content-type: application/json
content-length: 107
date: Thu, 29 Jun 2023 21:39:58 GMT
strict-transport-security: max-age=31536000; includeSubDomains
content-security-policy: frame-src 'self' blob:; frame-ancestors 'self'
server: envoy

{"roles":[{"role":"superusers","permissions":["read-api","read-write-api","read-cli","read-write-cli"]}]}

Update vars file

In order to run the playbook, environment specific values need to be provided. An example vars file vars-nsx-4x-example.yml is provided.

In order to run the playbook, environment specific values need to be provided. An example vars file vars-nsx-4x-example.yml is provided and values need to be updated for the var_nsx_manager, var_jsession_id, var_session_token, var_ntp_server1, var_ntp_server2 variables at a minimum.

Open the inputs file for editing.

# Navigate to the InSpec profile folder
cd /usr/share/stigs/nsx/4.x/v1r2-srg/ansible/vmware-nsx-4.x-stig-ansible-hardening

# Edit the inputs file
vi vars-nsx-4x-example.yml
# Navigate to the InSpec profile folder
cd /usr/share/stigs/nsx/4.x/v1r1-srg/ansible/vmware-nsx-4.x-stig-ansible-hardening

# Edit the inputs file
vi vars-nsx-4x-example.yml

Update the variables as shown below with values relevant to your environment. Specifically var_nsx_manager, var_jsession_id, var_session_token, var_ntp_server1, var_ntp_server2 variables at a minimum.

# Connection information
var_nsx_manager: '10.180.98.230'
var_jsession_id: 'JSESSIONID=BDE1B5A54690B453F8968293D3C8A1E4'
var_session_token: '1d140509-ee7c-4cbf-9c22-9efdef982631'

# Manager
var_ntp_server1: 'time-a-g.nist.gov'
var_ntp_server2: 'time-b-g.nist.gov'

# DFW
# NDFW-4X-000004
run_dfw_enable_rule_logging: true
# NDFW-4X-000015
run_dfw_flood_protection: true
# NDFW-4X-000016
run_dfw_default_rule_action: false
var_dfw_default_rule_action: 'DROP'
# NDFW-4X-000029
run_dfw_spoofguard_profile: true
# NDFW-4X-000034
run_dfw_ip_discovery_profile: false

# T0 Firewall
# NT0F-4X-000016
run_t0fw_default_rule_action: false
var_t0fw_default_rule_action: 'DROP'

# T0 Router
# NT0R-4X-000013
run_t0rtr_disable_pim_on_interfaces: false
# array of t0 interface ids that should have PIM enabled
var_t0rtr_gateway_interfaces_with_multicast_enabled:
  - Tier0Interface1
# NT0R-4X-000027
run_t0rtr_disable_dhcp: false
# array of t0 ids that should have dhcp enabled
var_t0rtr_gateways_with_dhcp_enabled: []
# NT0R-4X-000107
run_t0rtr_disable_multicast: true
# array of t0 ids that should have multicast enabled
var_t0rtr_gateways_with_multicast_enabled:
  - Tier0Gateway1

# T1 Firewall
# NT1F-4X-000016
run_t1fw_default_rule_action: true
var_t1fw_default_rule_action: 'DROP'

# T1 Router
# NT1R-4X-000027
run_t1rtr_disable_dhcp: true
# array of t1 ids that should have dhcp enabled
var_t1rtr_gateways_with_dhcp_enabled: []
# NT1R-4X-000107
run_t1rtr_disable_multicast: true
# array of t1 ids that should have multicast enabled
var_t1rtr_gateways_with_multicast_enabled:
  - Tier1Gateway1
# Example vars file
# Connection information
var_nsx_manager: '10.180.98.230'
var_jsession_id: 'JSESSIONID=BDE1B5A54690B453F8968293D3C8A1E4'
var_session_token: '1d140509-ee7c-4cbf-9c22-9efdef982631'

# Manager
var_ntp_server1: 'time-a-g.nist.gov'
var_ntp_server2: 'time-b-g.nist.gov'

# DFW
# NDFW-4X-000004
run_dfw_enable_rule_logging: true
# NDFW-4X-000015
run_dfw_flood_protection: true
# NDFW-4X-000016
run_dfw_default_rule_action: false
var_dfw_default_rule_action: 'DROP'
# NDFW-4X-000029
run_dfw_spoofguard_profile: true
# NDFW-4X-000034
run_dfw_ip_discovery_profile: false

# T0 Firewall
# NT0F-4X-000016
run_t0fw_default_rule_action: false
var_t0fw_default_rule_action: 'DROP'

# T0 Router
# NT0R-4X-000013
run_t0rtr_disable_pim_on_interfaces: false
# array of t0 interface ids that should have PIM enabled
var_t0rtr_gateway_interfaces_with_multicast_enabled:
  - Tier0Interface1
# NT0R-4X-000027
run_t0rtr_disable_dhcp: false
# array of t0 ids that should have dhcp enabled
var_t0rtr_gateways_with_dhcp_enabled: []
# NT0R-4X-000107
run_t0rtr_disable_multicast: true
# array of t0 ids that should have multicast enabled
var_t0rtr_gateways_with_multicast_enabled:
  - Tier0Gateway1

# T1 Firewall
# NT1F-4X-000016
run_t1fw_default_rule_action: true
var_t1fw_default_rule_action: 'DROP'

# T1 Router
# NT1R-4X-000027
run_t1rtr_disable_dhcp: true
# array of t1 ids that should have dhcp enabled
var_t1rtr_gateways_with_dhcp_enabled: []
# NT1R-4X-000107
run_t1rtr_disable_multicast: true
# array of t1 ids that should have multicast enabled
var_t1rtr_gateways_with_multicast_enabled:
  - Tier1Gateway1

Running the playbook

To run all of the NSX controls, follow the example below.

# Navigate to the InSpec profile folder
cd /usr/share/stigs/nsx/4.x/v1r2-srg/ansible/vmware-nsx-4.x-stig-ansible-hardening

# Run the playbook
ansible-playbook playbook.yml -v --extra-vars @vars-nsx-4x-example.yml

# Output example
PLAY [NSX 4.x Remediation Automation] ***************************************************************************************************************************************************************************************

TASK [dfw : NDFW-4X-000016 - Find DFW default layer 3 rule] ***********************************************************************************************************************************************************
ok: [127.0.0.1] => {"cache_control": "no-cache, no-store, max-age=0, must-revalidate", "changed": false, "connection": "close", "content_type": "application/json", "cookies": {}, "cookies_string": "", "date": "Mon, 10 Jul 2023 16:49:52 GMT", "elapsed": 0, "expires": "0", "json": {"_create_time": 1688751880285, "_create_user": "system", "_last_modified_time": 1689007787614, "_last_modified_user": "admin", "_protection": "NOT_PROTECTED", "_revision": 1, "_system_owned": false, "action": "ALLOW", "destination_groups": ["ANY"], "destinations_excluded": false, "direction": "IN_OUT", "disabled": false, "display_name": "default-layer3-rule", "id": "default-layer3-rule", "ip_protocol": "IPV4_IPV6", "is_default": true, "logged": true, "marked_for_delete": false, "origin_site_id": "9d96be5a-afca-498c-8c04-8ca4514f7b40", "overridden": false, "owner_id": "9d96be5a-afca-498c-8c04-8ca4514f7b40", "parent_path": "/infra/domains/default/security-policies/default-layer3-section", "path": "/infra/domains/default/security-policies/default-layer3-section/rules/default-layer3-rule", "profiles": ["ANY"], "realization_id": "aa423bd5-1ab7-41b0-958c-aa101f264df6", "relative_path": "default-layer3-rule", "remote_path": "", "resource_type": "Rule", "rule_id": 2, "scope": ["ANY"], "sequence_number": 2147483647, "services": ["ANY"], "source_groups": ["ANY"], "sources_excluded": false, "unique_id": "aa423bd5-1ab7-41b0-958c-aa101f264df6"}, "msg": "OK (unknown bytes)", "pragma": "no-cache", "redirected": false, "server": "envoy", "status": 200, "strict_transport_security": "max-age=31536000; includeSubDomains", "transfer_encoding": "chunked", "url": "https://10.180.98.230/policy/api/v1/infra/domains/default/security-policies/default-layer3-section/rules/default-layer3-rule", "vary": "Accept-Encoding", "x_content_type_options": "nosniff", "x_envoy_upstream_service_time": "20", "x_frame_options": "SAMEORIGIN", "x_nsx_requestid": "1b66a182-4959-4cbf-8438-ec304ce83c7b", "x_xss_protection": "1; mode=block"}

TASK [dfw : NDFW-4X-000016 - Update DFW default layer 3 rule action to desired value] *********************************************************************************************************************************
changed: [127.0.0.1] => {"cache_control": "no-cache, no-store, max-age=0, must-revalidate", "changed": true, "connection": "close", "content_length": "0", "cookies": {}, "cookies_string": "", "date": "Mon, 10 Jul 2023 16:49:54 GMT", "elapsed": 0, "expires": "0", "msg": "OK (0 bytes)", "pragma": "no-cache", "redirected": false, "server": "envoy", "status": 200, "strict_transport_security": "max-age=31536000; includeSubDomains", "url": "https://10.180.98.230/policy/api/v1/infra/domains/default/security-policies/default-layer3-section/rules/default-layer3-rule", "x_content_type_options": "nosniff", "x_envoy_upstream_service_time": "69", "x_frame_options": "SAMEORIGIN", "x_nsx_requestid": "ce242eda-7340-4097-a72c-ff10ae72c4e8", "x_xss_protection": "1; mode=block"}
# Navigate to the InSpec profile folder
cd /usr/share/stigs/nsx/4.x/v1r1-srg/ansible/vmware-nsx-4.x-stig-ansible-hardening

# Run the playbook
ansible-playbook playbook.yml -v --extra-vars @vars-nsx-4x-example.yml

# Output example
PLAY [NSX 4.x Remediation Automation] ***************************************************************************************************************************************************************************************

TASK [dfw : NDFW-4X-000016 - Find DFW default layer 3 rule] ***********************************************************************************************************************************************************
ok: [127.0.0.1] => {"cache_control": "no-cache, no-store, max-age=0, must-revalidate", "changed": false, "connection": "close", "content_type": "application/json", "cookies": {}, "cookies_string": "", "date": "Mon, 10 Jul 2023 16:49:52 GMT", "elapsed": 0, "expires": "0", "json": {"_create_time": 1688751880285, "_create_user": "system", "_last_modified_time": 1689007787614, "_last_modified_user": "admin", "_protection": "NOT_PROTECTED", "_revision": 1, "_system_owned": false, "action": "ALLOW", "destination_groups": ["ANY"], "destinations_excluded": false, "direction": "IN_OUT", "disabled": false, "display_name": "default-layer3-rule", "id": "default-layer3-rule", "ip_protocol": "IPV4_IPV6", "is_default": true, "logged": true, "marked_for_delete": false, "origin_site_id": "9d96be5a-afca-498c-8c04-8ca4514f7b40", "overridden": false, "owner_id": "9d96be5a-afca-498c-8c04-8ca4514f7b40", "parent_path": "/infra/domains/default/security-policies/default-layer3-section", "path": "/infra/domains/default/security-policies/default-layer3-section/rules/default-layer3-rule", "profiles": ["ANY"], "realization_id": "aa423bd5-1ab7-41b0-958c-aa101f264df6", "relative_path": "default-layer3-rule", "remote_path": "", "resource_type": "Rule", "rule_id": 2, "scope": ["ANY"], "sequence_number": 2147483647, "services": ["ANY"], "source_groups": ["ANY"], "sources_excluded": false, "unique_id": "aa423bd5-1ab7-41b0-958c-aa101f264df6"}, "msg": "OK (unknown bytes)", "pragma": "no-cache", "redirected": false, "server": "envoy", "status": 200, "strict_transport_security": "max-age=31536000; includeSubDomains", "transfer_encoding": "chunked", "url": "https://10.180.98.230/policy/api/v1/infra/domains/default/security-policies/default-layer3-section/rules/default-layer3-rule", "vary": "Accept-Encoding", "x_content_type_options": "nosniff", "x_envoy_upstream_service_time": "20", "x_frame_options": "SAMEORIGIN", "x_nsx_requestid": "1b66a182-4959-4cbf-8438-ec304ce83c7b", "x_xss_protection": "1; mode=block"}

TASK [dfw : NDFW-4X-000016 - Update DFW default layer 3 rule action to desired value] *********************************************************************************************************************************
changed: [127.0.0.1] => {"cache_control": "no-cache, no-store, max-age=0, must-revalidate", "changed": true, "connection": "close", "content_length": "0", "cookies": {}, "cookies_string": "", "date": "Mon, 10 Jul 2023 16:49:54 GMT", "elapsed": 0, "expires": "0", "msg": "OK (0 bytes)", "pragma": "no-cache", "redirected": false, "server": "envoy", "status": 200, "strict_transport_security": "max-age=31536000; includeSubDomains", "url": "https://10.180.98.230/policy/api/v1/infra/domains/default/security-policies/default-layer3-section/rules/default-layer3-rule", "x_content_type_options": "nosniff", "x_envoy_upstream_service_time": "69", "x_frame_options": "SAMEORIGIN", "x_nsx_requestid": "ce242eda-7340-4097-a72c-ff10ae72c4e8", "x_xss_protection": "1; mode=block"}

A more conservative and preferred approach is to target any non-compliant controls or run each component separately allowed you to perform any functional testing in between.

# Providing the tag "dfw" will instruct the playbook to only run the dfw role. This tag can be seen in each roles task/main.yml file.
> ansible-playbook playbook.yml -v --extra-vars @vars-nsx-4.x-example.yml --tags dfw

# Providing the tag " NDFW-4X-000004" will instruct the playbook to only run task tagged with the STIG ID of  NDFW-4X-000004.
> ansible-playbook playbook.yml -v --extra-vars @vars-nsx-4.x-example.yml --tags NDFW-4X-000004
# Providing the tag "dfw" will instruct the playbook to only run the dfw role. This tag can be seen in each roles task/main.yml file.
> ansible-playbook playbook.yml -v --extra-vars @vars-nsx-4.x-example.yml --tags dfw

# Providing the tag " NDFW-4X-000004" will instruct the playbook to only run task tagged with the STIG ID of  NDFW-4X-000004.
> ansible-playbook playbook.yml -v --extra-vars @vars-nsx-4.x-example.yml --tags NDFW-4X-000004

4.1.3 - Audit NSX-T 3.x

Auditing NSX-T 3.x for STIG Compliance

Overview

Auditing NSX-T 3.x for STIG compliance involves scanning the NSX Managers, DFW, and any gateways deployed.

To audit NSX-T using InSpec we utilize the local transport to connect via the REST API and query it’s configuration.

Prerequisites

Versions listed below were used for this documentation. Other versions of these tools may work as well but if issues are found it is recommended to try the versions listed here.

  • The vmware-nsxt-3.x-stig-baseline profile downloaded.
  • InSpec/Cinc Auditor 5.22.3
  • SAF CLI 1.2.20
  • STIG Viewer 2.17
  • An NSX-T 3.x environment. 3.2.3 was used in these examples with 1 T0 Gateway configured with BGP to an upstream router and 1 T1 Gateway deployed.

Auditing NSX-T

Generate API Session Token

This profile uses Session-Based authentication to authenticate with NSX for auditing. A session token and cookie must be generated and provided an input for the profile. This can be generated in various ways via curl, tools like Postman, etc. For more information see the NSX API Documentation.

Note: If the user is a remote user, append “@domain” to the username, for example, “joe@example.com”. The domain must match a domain for a configured VIDM identity source or a configured LDAP identity source.

Curl example

curl -k -i -X POST -d 'j_username=admin&j_password=replacethis' https://10.43.173.83/api/session/create

# Example response
HTTP/1.1 200
Set-Cookie: JSESSIONID=6A0F43FCD07947BB21890CDA05DF26C0; Path=/; Secure; HttpOnly
X-XSRF-TOKEN: fe3d6167-09d5-4302-b6cd-be2e20947d58
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
Content-Type: application/json
Content-Length: 107
Date: Thu, 06 Jul 2023 17:15:07 GMT
Server: NSX

{"roles":[{"role":"superusers","permissions":["read-api","read-write-api","read-cli","read-write-cli"]}]}

Update profile inputs

Included in the vmware-nsxt-3.x-stig-baseline is an example inputs-nsxt-3.x.yml file with the following inputs relevant to NSX-T.

Update the inputs as shown below with values relevant to your environment.

# General
# NSX Manager IP or FQDN
nsxManager: '10.43.173.83'
# Session token generated for access to NSX
sessionToken: 'fe3d6167-09d5-4302-b6cd-be2e20947d58'
# Session cookie id generated for access to NSX. Example 'JSESSIONID=2A165FCF851CA50FCD038DFC8E770038'
sessionCookieId: 'JSESSIONID=6A0F43FCD07947BB21890CDA05DF26C0'
# Manager
# Enter the environment specific syslog server vCenter should be forwarding logs to.
syslogServers:
  - 'loginsight.test.com'
  - 'loginsight2.test.com'
# Enter the environment specific time servers.
ntpServer1: 'time-a-g.nist.gov'
ntpServer2: 'time-b-g.nist.gov'
# Enter latest NSX version. Example '3.2.3.0'
nsxtVersion: '3.2.3.0'
# Enter an array of T0 Gateways that are approved to have multicast enabled.
t0multicastlist: []
# Enter an array of T0 Gateways interfaces that are approved to have multicast enabled.
t0mcinterfacelist: []
# Enter an array of T0 Gateways that are approved to have DHCP enabled.
t0dhcplist: []
# Enter an array of T1 Gateways that are approved to have DHCP enabled.
t1dhcplist: []
# Enter an array of T1 Gateways that are approved to have multicast enabled.
t1multicastlist: []

Run the audit

In this example we will be scanning all NSX components, specifying an inputs file, and outputting a report to the CLI and to a JSON file.

# Note this command is being ran from the root of the profile folder. Update paths as needed if running from a different location.
> inspec exec . --show-progress --input-file inputs-nsxt-3.x.yml --reporter=cli json:/mnt/c/Inspec/Reports/MyNSX3Report.json

# Shown below is the last part of the output at the CLI.
  ×  T1FW-3X-000036: The NSX-T Tier-1 Gateway Firewall must configure SpoofGuard to block outbound IP packets that contain illegitimate packet attributes. (6 failed)
     ✔  HTTP GET on https://10.43.173.83/api/v1/logical-switches status is expected to cmp == 200
     ✔  HTTP GET on https://10.43.173.83/policy/api/v1/search?query=( resource_type:SpoofGuardProfile AND unique_id:fad98876-d7ff-11e4-b9d6-1681e6b88ec1 ) status is expected to cmp == 200
     ×  JSON content address_binding_allowlist is expected to cmp == "true"

     expected: true
          got: false

     (compared using `cmp` matcher)

     ×  JSON content address_binding_whitelist is expected to cmp == "true"

     expected: true
          got: false

     (compared using `cmp` matcher)

     ✔  HTTP GET on https://10.43.173.83/policy/api/v1/search?query=( resource_type:SpoofGuardProfile AND unique_id:fad98876-d7ff-11e4-b9d6-1681e6b88ec1 ) status is expected to cmp == 200
     ×  JSON content address_binding_allowlist is expected to cmp == "true"

     expected: true
          got: false

     (compared using `cmp` matcher)

     ×  JSON content address_binding_whitelist is expected to cmp == "true"

     expected: true
          got: false

     (compared using `cmp` matcher)

     ✔  HTTP GET on https://10.43.173.83/policy/api/v1/search?query=( resource_type:SpoofGuardProfile AND unique_id:fad98876-d7ff-11e4-b9d6-1681e6b88ec1 ) status is expected to cmp == 200
     ×  JSON content address_binding_allowlist is expected to cmp == "true"

     expected: true
          got: false

     (compared using `cmp` matcher)

     ×  JSON content address_binding_whitelist is expected to cmp == "true"

     expected: true
          got: false

     (compared using `cmp` matcher)



Profile:   VMware NSX-T Tier 1 Gateway RTR STIG InSpec Profile (VMware NSX-T Tier 1 Gateway RTR STIG InSpec Profile)
Version:   1.1
Target:    local://
Target ID: 91850cb0-e902-5c20-9e21-05288aec4f93

  ↺  T1RT-3X-000016: The NSX-T Tier-1 Gateway must be configured to have all inactive interfaces removed. (1 skipped)
     ✔  HTTP GET on https://10.43.173.83/policy/api/v1/infra/tier-1s status is expected to cmp == 200
     ↺  This is a manual check. Review T1 interfaces and determine if any existing interfaces are orphaned and should be removed.
  ✔  T1RT-3X-000027: The NSX-T Tier-1 Gateway must be configured to have the DHCP service disabled if not in use.
     ✔  HTTP GET on https://10.43.173.83/policy/api/v1/infra/tier-1s status is expected to cmp == 200
{"tier0_path"=>"/infra/tier-0s/Tier0Gateway1", "failover_mode"=>"NON_PREEMPTIVE", "enable_standby_relocation"=>false, "route_advertisement_types"=>["TIER1_CONNECTED", "TIER1_STATIC_ROUTES"], "route_advertisement_rules"=>[{"name"=>"Rule 1", "subnets"=>["192.168.1.0/24", "192.168.2.0/24"], "prefix_operator"=>"GE", "action"=>"PERMIT"}], "force_whitelisting"=>false, "default_rule_logging"=>false, "disable_firewall"=>false, "ipv6_profile_paths"=>["/infra/ipv6-ndra-profiles/default", "/infra/ipv6-dad-profiles/default"], "pool_allocation"=>"ROUTING", "advanced_config"=>{"traffic_back_to_source"=>false}, "resource_type"=>"Tier1", "id"=>"Tier1Gateway1", "display_name"=>"Tier1Gateway1", "description"=>"Tier1-1 created through automation", "path"=>"/infra/tier-1s/Tier1Gateway1", "relative_path"=>"Tier1Gateway1", "parent_path"=>"/infra", "unique_id"=>"74a2d444-07e6-49c9-bdb8-973c1ad81524", "realization_id"=>"74a2d444-07e6-49c9-bdb8-973c1ad81524", "marked_for_delete"=>false, "overridden"=>false, "_create_time"=>1688661706117, "_create_user"=>"admin", "_last_modified_time"=>1688661706117, "_last_modified_user"=>"admin", "_system_owned"=>false, "_protection"=>"NOT_PROTECTED", "_revision"=>0} ["dhcp_config_paths"] is expected to equal nil
  ↺  T1RT-3X-000034: The NSX-T Tier-1 Gateway must be configured to enforce a Quality-of-Service (QoS) policy to limit the effects of packet flooding denial-of-service (DoS) attacks. (1 skipped)
     ✔  HTTP GET on https://10.43.173.83/policy/api/v1/infra/tier-1s status is expected to cmp == 200
     ↺  This is a manual check. Review that QoS policies support traffic priorities specified by the Combatant Commands/Services/Agencies needed to ensure sufficient capacity for mission-critical traffic.
  ✔  T1RT-3X-000084: The NSX-T Tier-1 Gateway must be configured to have multicast disabled if not in use.
     ✔  HTTP GET on https://10.43.173.83/policy/api/v1/infra/tier-1s status is expected to cmp == 200
     ✔  HTTP GET on https://10.43.173.83/policy/api/v1/infra/tier-1s/Tier1Gateway1/locale-services/Tier1LocalServices-1/multicast status is expected to cmp == 404


Profile Summary: 24 successful controls, 35 control failures, 12 controls skipped
Test Summary: 176 successful, 60 failures, 15 skipped

Convert the results to CKL

If a STIG Viewer CKL file is needed then the results from the scans can be converted to CKL with the SAF CLI.

# Converting the scan results from the prior section to CKL
saf convert hdf2ckl -i C:\inspec\Reports\MyNSX3Report.json -o C:\inspec\Reports\MyNSX3Report.ckl --hostname 10.43.173.83 --fqdn 10.43.173.83 --ip 10.43.173.83 --mac 00:00:00:00:00:00

Opening the CKL file in STIG Viewer will look like the screenshot below. Note the InSpec results are included in the Finding Details pane.

alt text

4.1.4 - Remediate NSX-T 3.x

Remediating NSX-T 3.x for STIG Compliance

Overview

Remediating NSX-T 3.x for STIG compliance involves configuring the NSX Managers, DFW, and any gateways deployed.

To remediate NSX-T, Ansible is the automation tool used to interact with the NSX-T REST API.

Prerequisites

Versions listed below were used for this documentation. Other versions of these tools may work as well but if issues are found it is recommended to try the versions listed here.

  • The vmware-nsxt-3.x-stig-ansible-hardening playbook downloaded.
  • Ansible 2.14.4
  • Install JMESPath for community.general.json_query collection.
  • An NSX-T 3.x environment. 3.2.3 was used in this example.
  • An account with sufficient privileges to configure NSX-T.

Important Considerations

Please read carefully before proceeding!

Some NSX-T STIG controls can be very impactful to your environment if care is not taken during implementation especially in a brownfield scenario. For example, changing the default DFW rule to deny traffic without first creating rules to allow authorized traffic.

Below is a table of controls selected for consideration but all controls should be examined for impact before implementing.

These can be turned on/off by with a variable that must be set to true as a condition for these tasks to run. See Update vars file for more details.

STIG IDTitleNotes
TDFW-3X-000019The NSX-T Distributed Firewall must block outbound traffic containing denial-of-service (DoS) attacks to protect against the use of internal information systems to launch any DoS attacks against other networks or endpoints.
TDFW-3X-000021The NSX-T Distributed Firewall must deny network communications traffic by default and allow network communications traffic by exception (i.e., deny all, permit by exception).Ensure DFW rules are created to allow authorized traffic.
TDFW-3X-000036The NSX-T Distributed Firewall must configure SpoofGuard to block outbound IP packets that contain illegitimate packet attributes.Develop an operational plan to manage Spoofguard and identity workloads multiple IPs, etc, that may have issues.
T0FW-3X-000019The NSX-T Tier-0 Gateway Firewall must block outbound traffic containing denial-of-service (DoS) attacks to protect against the use of internal information systems to launch any DoS attacks against other networks or endpoints.
T0FW-3X-000021The NSX-T Tier-0 Gateway Firewall must deny network communications traffic by default and allow network communications traffic by exception (i.e., deny all, permit by exception).Ensure gateway firewall rules are created to allow authorized traffic.
T0FW-3X-000036The NSX-T Tier-0 Gateway Firewall must configure SpoofGuard to block outbound IP packets that contain illegitimate packet attributes.Develop an operational plan to manage Spoofguard and identity workloads multiple IPs, etc, that may have issues.
T1FW-3X-000019The NSX-T Tier-1 Gateway Firewall must block outbound traffic containing denial-of-service (DoS) attacks to protect against the use of internal information systems to launch any DoS attacks against other networks or endpoints.
T1FW-3X-000021The NSX-T Tier-1 Gateway Firewall must deny network communications traffic by default and allow network communications traffic by exception (i.e., deny all, permit by exception).Ensure gateway firewall rules are created to allow authorized traffic.
T1FW-3X-000036The NSX-T Tier-1 Gateway Firewall must configure SpoofGuard to block outbound IP packets that contain illegitimate packet attributes.Develop an operational plan to manage Spoofguard and identity workloads multiple IPs, etc, that may have issues.

Also not all controls are covered by the Ansible playbook and may require manual remediation.

Remediating NSX-T

To remediate NSX-T we have provided an Ansible playbook that will target an NSX-T Manager over the REST API and configure any non-compliant controls.

Since Ansible can only be ran from Linux based systems, the examples below are being ran on an Ubuntu 22.04 WSL2 instance on Windows 11 for reference.

Generate API Session Token

This playbook uses Session-Based authentication to authenticate with NSX for remediation. A session token and cookie must be generated and provided an input for the profile. This can be generated in various ways via curl, tools like Postman, etc. For more information see the NSX API Documentation.

Note: If the user is a remote user, append “@domain” to the username, for example, “joe@example.com”. The domain must match a domain for a configured VIDM identity source or a configured LDAP identity source.

Curl example

curl -k -i -X POST -d 'j_username=admin&j_password=replacethis' https://10.43.173.83/api/session/create

# Example response
HTTP/1.1 200
Set-Cookie: JSESSIONID=6A0F43FCD07947BB21890CDA05DF26C0; Path=/; Secure; HttpOnly
X-XSRF-TOKEN: fe3d6167-09d5-4302-b6cd-be2e20947d58
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
Content-Type: application/json
Content-Length: 107
Date: Thu, 06 Jul 2023 17:15:07 GMT
Server: NSX

{"roles":[{"role":"superusers","permissions":["read-api","read-write-api","read-cli","read-write-cli"]}]}

Update vars file

In order to run the playbook, environment specific values need to be provided. An example vars file vars-nsxt-3.x-example.yml is provided and values need to be updated for the var_nsx_manager, var_jsession_id, var_session_token, var_ntp_server1, var_ntp_server2 variables at a minimum.

# Manager variables
# NSX Manager IP or FQDN
var_nsx_manager: '10.43.173.83'
# Session cookie id generated for access to NSX. Example 'JSESSIONID=2A165FCF851CA50FCD038DFC8E770038'
var_jsession_id: 'JSESSIONID=77EE4288C048073598F50493167A881A'
# Session token generated for access to NSX
var_session_token: 'cabda93b-f2e9-406d-bcfa-ec56b9a07bce'
# Enter the environment specific time servers.
var_ntp_server1: 'time-a-g.nist.gov'
var_ntp_server2: 'time-b-g.nist.gov'

## Set to true/false to enable or disable controls
# DFW
# TDFW-3X-000002
run_dfw_unpublished_rules: true
# TDFW-3X-000005
run_dfw_rule_logging: true
# TDFW-3X-000019-28
run_dfw_floodprotprof: true
# TDFW-3X-000021 !!Caution if set to true this will set the default DFW rule to DROP!!
run_dfw_default_rule_action: false
var_dfw_default_rule_action_desired: "DROP"
# TDFW-3X-000026
run_dfw_syslog: true
# TDFW-3X-000036
run_dfw_spoofguard_prof: false
# TDFW-3X-000042
run_dfw_verify_time_based_rules: true

# Manager
# TNDM-3X-000012 TNDM-3X-000041
run_mgr_auth_policy: true
# TNDM-3X-000052 TNDM-3X-000080 TNDM-3X-000101
run_mgr_api_session_timeout: true
run_mgr_cli_timeout: true
# TNDM-3X-000068
run_mgr_ntp_servers: true
# TNDM-3X-000069
run_mgr_timezone: true
# TNDM-3X-000083
run_service_log_levels: true
# TNDM-3X-000098
run_mgr_disable_ceip_acceptance: true
# TNDM-3X-000099
run_mgr_disable_ssh: true
# TNDM-3X-000100
run_mgr_disable_local_accounts: true
# TNDM-3X-000103
run_mgr_enable_fips_for_lbs: true

# T0FW
# T0FW-3X-000002
run_t0fw_unpublished_rules: true
# T0FW-3X-000006
run_t0fw_rule_logging: true
# T0FW-3X-000011
run_t0fw_syslog_tls: true
# T0FW-3X-000019-28
run_t0fw_floodprotprof: true
# T0FW-3X-000021
run_t0fw_default_rule_action: false
var_t0fw_default_rule_action_desired: "DROP"
# T0FW-3X-000030
run_t0fw_gwfw_rules: true
# T0FW-3X-000036
run_t0fw_spoofguard_prof: false

# T0RT
# T0RT-3X-000003
run_t0rt_bgp_reject_advertisements: true
# T0RT-3X-000013
run_t0rt_gateway_interface_pim_multicast: true
# array of t0 interface ids that should have multicast enabled
var_t0rt_gateway_interfaces_with_multicast_enabled: []
# T0RT-3X-000016
run_t0rt_remove_inactive_interfaces: true
# T0RT-3X-000027
run_t0rt_disable_dhcp: true
# array of t0 ids that should have dhcp enabled
var_t0rt_gateways_with_dhcp_enabled: []
# T0RT-3X-000034
run_t0rt_qos_segment_profile: true
# T0RT-3X-000038
run_t0rt_restrict_traffic: true
# T0RT-3X-000051
run_t0rt_gateway_urpf: true
# T0RT-3X-000054
run_t0rt_auth_routing_protocols: true
# T0RT-3X-000055
run_t0rt_uniq_key_per_as: true
# T0RT-3X-000064,65,66
run_t0rt_gateway_icmp: true
# T0RT-3X-000067
run_t0rt_bgp_nbr_maxroutes: true
var_t0rt_upd_bgp_nbr_route_filter_max_routes: 200
# T0RT-3X-000084
run_t0rt_loopback_source_ibgp: true
# T0RT-3X-000095
run_t0rt_gateway_bgp_ospf: true
# T0RT-3X-000096
run_t0rt_gateway_multicast: true
# array of t0 ids that should have multicast enabled
var_t0rt_gateways_with_multicast_enabled: []

# T1FW
# T1FW-3X-000002
run_t1fw_unpublished_rules: true
# T1FW-3X-000005-06
run_t1fw_rule_logging: true
# T1FW-3X-000011-26
run_t1fw_syslog_tls: true
# T1FW-3X-000019-28
run_t1fw_floodprotprof: true
# T1FW-3X-000021
run_t1fw_default_rule_action: false
var_t1fw_default_rule_action_desired: "DROP"
# T1FW-3X-000030
run_t1fw_gwfw_rules: true
# T1FW-3X-000036
run_t1fw_spoofguard_prof: false

# T1RT
# T1RT-3X-000016
run_t1rt_remove_inactive_interfaces: true
# T1RT-3X-000027
run_t1rt_disable_dhcp: true
# array of t1 ids that should have dhcp enabled
var_t1rt_gateways_with_dhcp_enabled: []
# T1RT-3X-000034
run_t1rt_qos: true
# T1RT-3X-000084
run_t1rt_gateway_multicast: true
# array of t1 ids that should have multicast enabled
var_t1rt_gateways_with_multicast_enabled: []

Running the playbook

To run all of the NSX-T controls, follow the example below.

# The -k parameter will prompt for password and we are using extra-vars to specify a variable file for the playbook to use. Command assumes it is being ran from the playbook folder.
> ansible-playbook playbook.yml -v --extra-vars @vars-nsxt-3.x-example.yml

# Output example
PLAY [NSX-T 3.x Remediation Automation] ***************************************************************************************************************************************************************************************

TASK [dfw : Include DFW] ******************************************************************************************************************************************************************************************************
included: /mnt/c/gitlab/vmware-nsxt-3.x-stig-ansible-hardening/roles/dfw/tasks/dfw.yml for 127.0.0.1

TASK [dfw : TDFW-3X-000005 - Find DFW rules without logging enabled excluding the default layer 2 rule] ***********************************************************************************************************************
ok: [127.0.0.1] => {"cache_control": "no-cache, no-store, max-age=0, must-revalidate", "changed": false, "connection": "close", "content_type": "application/json", "cookies": {}, "cookies_string": "", "date": "Fri, 07 Jul 2023 01:04:54 GMT", "elapsed": 0, "expires": "0", "json": {"cursor": "3", "result_count": 3, "results": [{"action": "ALLOW", "id": "default-layer3-rule", "logged": false, "path": "/infra/domains/default/security-policies/default-layer3-section/rules/default-layer3-rule", "rule_id": 2, "sequence_number": 2147483647}, {"action": "ALLOW", "id": "default_rule_DHCP", "logged": false, "path": "/infra/domains/default/security-policies/default-layer3-section/rules/default_rule_DHCP", "rule_id": 4, "sequence_number": 50000}, {"action": "ALLOW", "id": "default_rule_NDP", "logged": false, "path": "/infra/domains/default/security-policies/default-layer3-section/rules/default_rule_NDP", "rule_id": 3, "sequence_number": 25000}]}, "msg": "OK (unknown bytes)", "pragma": "no-cache", "redirected": false, "server": "NSX", "status": 200, "strict_transport_security": "max-age=31536000 ; includeSubDomains", "transfer_encoding": "chunked", "url": "https://10.43.173.83/policy/api/v1/search?query=(resource_type:Rule%20AND%20logged:false%20AND%20!id:default-layer2-rule%20AND%20parent_path:?infra?domains?default?security-policies*)&included_fields=id,rule_id,logged,path,sequence_number,action", "vary": "accept-encoding", "x_content_type_options": "nosniff", "x_frame_options": "SAMEORIGIN", "x_nsx_requestid": "dfc6dbcf-e0df-4893-ad42-29c7b5a55c40", "x_xss_protection": "1; mode=block"}

TASK [dfw : TDFW-3X-000005 - Enable logging on DFW rules without logging enabled excluding the default layer 2 rule] **********************************************************************************************************
changed: [127.0.0.1] => (item={'rule_id': 2, 'sequence_number': 2147483647, 'path': '/infra/domains/default/security-policies/default-layer3-section/rules/default-layer3-rule', 'logged': False, 'action': 'ALLOW', 'id': 'default-layer3-rule'}) => {"ansible_loop_var": "item", "cache_control": "no-cache, no-store, max-age=0, must-revalidate", "changed": true, "connection": "close", "content_length": "0", "cookies": {}, "cookies_string": "", "date": "Fri, 07 Jul 2023 01:04:56 GMT", "elapsed": 1, "expires": "0", "item": {"action": "ALLOW", "id": "default-layer3-rule", "logged": false, "path": "/infra/domains/default/security-policies/default-layer3-section/rules/default-layer3-rule", "rule_id": 2, "sequence_number": 2147483647}, "msg": "OK (0 bytes)", "pragma": "no-cache", "redirected": false, "server": "NSX", "status": 200, "strict_transport_security": "max-age=31536000 ; includeSubDomains", "url": "https://10.43.173.83/policy/api/v1/infra/domains/default/security-policies/default-layer3-section/rules/default-layer3-rule", "x_content_type_options": "nosniff", "x_frame_options": "SAMEORIGIN", "x_nsx_requestid": "9d03bce2-d284-46b6-8898-c12d6003f453", "x_xss_protection": "1; mode=block"}
changed: [127.0.0.1] => (item={'rule_id': 4, 'sequence_number': 50000, 'path': '/infra/domains/default/security-policies/default-layer3-section/rules/default_rule_DHCP', 'logged': False, 'action': 'ALLOW', 'id': 'default_rule_DHCP'}) => {"ansible_loop_var": "item", "cache_control": "no-cache, no-store, max-age=0, must-revalidate", "changed": true, "connection": "close", "content_length": "0", "cookies": {}, "cookies_string": "", "date": "Fri, 07 Jul 2023 01:04:57 GMT", "elapsed": 0, "expires": "0", "item": {"action": "ALLOW", "id": "default_rule_DHCP", "logged": false, "path": "/infra/domains/default/security-policies/default-layer3-section/rules/default_rule_DHCP", "rule_id": 4, "sequence_number": 50000}, "msg": "OK (0 bytes)", "pragma": "no-cache", "redirected": false, "server": "NSX", "status": 200, "strict_transport_security": "max-age=31536000 ; includeSubDomains", "url": "https://10.43.173.83/policy/api/v1/infra/domains/default/security-policies/default-layer3-section/rules/default_rule_DHCP", "x_content_type_options": "nosniff", "x_frame_options": "SAMEORIGIN", "x_nsx_requestid": "16ecd5a7-2b74-4255-8e2e-a16d4c33f076", "x_xss_protection": "1; mode=block"}
changed: [127.0.0.1] => (item={'rule_id': 3, 'sequence_number': 25000, 'path': '/infra/domains/default/security-policies/default-layer3-section/rules/default_rule_NDP', 'logged': False, 'action': 'ALLOW', 'id': 'default_rule_NDP'}) => {"ansible_loop_var": "item", "cache_control": "no-cache, no-store, max-age=0, must-revalidate", "changed": true, "connection": "close", "content_length": "0", "cookies": {}, "cookies_string": "", "date": "Fri, 07 Jul 2023 01:04:57 GMT", "elapsed": 0, "expires": "0", "item": {"action": "ALLOW", "id": "default_rule_NDP", "logged": false, "path": "/infra/domains/default/security-policies/default-layer3-section/rules/default_rule_NDP", "rule_id": 3, "sequence_number": 25000}, "msg": "OK (0 bytes)", "pragma": "no-cache", "redirected": false, "server": "NSX", "status": 200, "strict_transport_security": "max-age=31536000 ; includeSubDomains", "url": "https://10.43.173.83/policy/api/v1/infra/domains/default/security-policies/default-layer3-section/rules/default_rule_NDP", "x_content_type_options": "nosniff", "x_frame_options": "SAMEORIGIN", "x_nsx_requestid": "88ad2a48-7039-41d6-a758-84999467a2b3", "x_xss_protection": "1; mode=block"}

A more conservative and preferred approach is to target any non-compliant controls or run each component separately allowed you to perform any functional testing in between.

# Providing the tag "dfw" will instruct the playbook to only run the dfw role. This tag can be seen in each roles task/main.yml file.
> ansible-playbook playbook.yml -v --extra-vars @vars-nsxt-3.x-example.yml --tags dfw

# Providing the tag " TDFW-3X-000005" will instruct the playbook to only run task tagged with the STIG ID of  TDFW-3X-000005.
> ansible-playbook playbook.yml -v --extra-vars @vars-nsxt-3.x-example.yml --tags TDFW-3X-000005

4.2 - vSphere

Performing compliance automation tasks for vSphere.

4.2.1 - Audit vSphere 8

Auditing vSphere 8 for STIG Compliance

Overview

Auditing vSphere for STIG compliance involves scanning ESXi, Virtual Machines, vCenter, and the vCenter appliance.

When auditing vSphere we will split up tasks between product and appliance based controls which are defined as follows:

  • Product Control: Configurations that interact with the Product via the User Interface or API that are exposed to administrators. Whether these are Default or Non-Default, the risk of mis-configuration effecting availability of the product is low but could impact how the environment is operated if not assessed.
  • Appliance Control: Appliance controls deal with the underlying components (databases, web servers, Photon OS, etc) that make up the product. Altering these add risk to product availability if precautionary steps and care in implementation are not taken. Identifying and relying on Default settings in this category makes this category less risky (Default Appliance Controls should be seen as a positive).

To audit vSphere using InSpec we utilize the VMware transport(train-vmware) which connects to vCenter via PowerCLI and performs queries. For the vCenter appliance the auditing is performed via SSH. It is recommended to disable SSH on vCenter after the auditing is complete.

Prerequisites

Versions listed below were used for this documentation. Other versions of these tools may work as well but if issues are found it is recommended to try the versions listed here.

  • Powershell 7.3.4/PowerCLI 13.1 or newer
  • VMware.Vsphere.SsoAdmin PowerCLI Module 1.3.9 or newer
  • InSpec/Cinc Auditor 6.6.0
  • train-vmware 0.2.0
  • SAF CLI 1.4.0
  • STIG Viewer 2.17
  • A vSphere 8.x U1 or newer environment.
  • An account with sufficient privileges to view SSO configuration in vCenter.
  • Example distributed switches, VMs, and a content library were created in the testbed to produce audit results for those objects.

Assumptions

  • Commands are being ran from a Linux machine. Windows will also work but paths and commands may need to be adjusted from the examples.
  • The DOD Compliance and Automation repository downloaded and extracted to /usr/share/stigs.
  • CINC Auditor is used in lieu of InSpec. If InSpec is used replace cinc-auditor with inspec when running commands.

Install the custom VMware transport for InSpec

To extend the functionality of the VMware transport that ships with InSpec we have created a custom one that also incorporates the VMware.Vsphere.SsoAdmin module to extend automation coverage to the vCenter SSO STIG controls.

To install the plugin that is included with the vmware-vsphere-8.0-stig-baseline profile, do the following:

# Install the custom train-vmware plugin. Update the path to the gem as needed. The command will be the same on Windows and Linux.
> cinc-auditor plugin install /usr/share/stigs/vsphere/8.0/v1r1-stig/vsphere/inspec/vmware-vsphere-8.0-stig-baseline/train-vmware-0.2.0.gem

# To verify the installation
> cinc-auditor plugin list

┌────────────────────────────────────────┬─────────┬──────────────┬─────────┬────────────────────────────────────────────────────────────────────────┐
              Plugin Name                Version      Via       ApiVer                                Description                               
├────────────────────────────────────────┼─────────┼──────────────┼─────────┼────────────────────────────────────────────────────────────────────────┤
 inspec-compliance                       6.6.0    core          2        Plugin to perform operations with Chef Automate                        
 inspec-habitat                          6.6.0    core          2        Plugin to create/upload habitat package                                
 inspec-init                             6.6.0    core          2        Plugin for scaffolding profile, plugin or a resource                   
 inspec-license                          6.6.0    core          2        Plugin to list user licenses.                                          
 inspec-parallel                         6.6.0    core          2        Plugin to handle parallel InSpec scan operations over multiple targets 
 inspec-plugin-manager-cli               6.6.0    core          2        CLI plugin for InSpec                                                  
 inspec-reporter-html2                   6.6.0    core          2        Improved HTML reporter plugin                                          
 inspec-reporter-json-min                6.6.0    core          2        Json-min json reporter plugin                                          
 inspec-reporter-junit                   6.6.0    core          2        JUnit XML reporter plugin                                              
 inspec-sign                             6.6.0    core          2                                                                               
 inspec-streaming-reporter-progress-bar  6.6.0    core          2        Displays a real-time progress bar and control title as output          
 inspec-supermarket                      6.6.0    core          0                                                                               
 train-aws                               0.2.36   gem (system)  train-1  AWS API Transport for Train                                            
 train-habitat                           0.2.22   gem (system)  train-1  Habitat API Transport for Train                                        
 train-kubernetes                        0.1.12   gem (system)  train-1  Train Kubernetes                                                       
 train-vmware                            0.2.0    gem (user)    train-1  Train Plugin for VMware PowerCLI                                       
 train-winrm                             0.2.13   gem (system)  train-1  Windows WinRM API Transport for Train                                  
└────────────────────────────────────────┴─────────┴──────────────┴─────────┴────────────────────────────────────────────────────────────────────────┘
 17 plugin(s) total

Auditing vSphere (Product Controls)

Setup environment variables for vCenter connection

Connectivity to vCenter is established via environment variables. Take care to clear your history and close the Powershell session to avoid any credentials left in memory/history.

#Enter Powershell
pwsh

# Note: VISERVER is referencing vCenter and not an ESXi host.
$env:VISERVER='10.186.30.81'
$env:VISERVER_USERNAME='Administrator@vsphere.local'
$env:VISERVER_PASSWORD='password'

Note: If your password has a single ’ in it you must substitute it with ’’’’ for it to be properly escaped all the way through the process.

Auditing ESXi

Update profile inputs

Included in the vmware-vsphere-8.0-stig-baseline is an example inputs-example.yml file with variables relevant to ESXi. This is used to provide InSpec with values specific to the environment being audited.

Open the inputs file for editing.

# Navigate to the InSpec profile folder
cd /usr/share/stigs/vsphere/8.0/v1r1-stig/vsphere/inspec/vmware-vsphere-8.0-stig-baseline

# Edit the inputs file
vi inputs-example.yml
# Navigate to the InSpec profile folder
cd /usr/share/stigs/vsphere/8.0/v1r1-srg/vsphere/inspec/vmware-vsphere-8.0-stig-baseline

# Edit the inputs file
vi inputs-example.yml

Update the inputs as shown below with values relevant to your environment.

# Choose whether to scan a single host, all hosts in a cluster, or all hosts in vCenter.
vmhostName: '10.186.25.26'
cluster: ''
allesxi: false
# Set to true if hosts are joined to active directory for authentication
adJoined: false
# If ESXi is joined to AD, enter the AD group that has administrative access to ESXi.
adAdminGroup: 'MyAdAdminGroup'
# Enter the environment specific syslog server ESXi should be forwarding logs to
syslogServer: 'tcp://log.test.local:514'
# Enter the environment specific time servers.
esxiNtpServers:
  - 'time-a-g.nist.gov'
  - 'time-b-g.nist.gov'
# Enter the environment specific vMotion VLAN Id.
vMotionVlanId: '100'
# Enter the environment specific Management VLAN Id.
mgtVlanId: '101'
# Enter an array of users that should be in the lockdown mode exceptions list.
exceptionUsers:
  - root
  - dcui
# If snmp is used in the environment change to true.
snmpEnabled: 'false'
# Enter the latest build number for ESXi.
esxiBuildNumber: '22380479'
# Choose whether to scan a single host, all hosts in a cluster, or all hosts in vCenter.
vmhostName: '10.186.25.26'
cluster: ''
allesxi: false
# Set to true if hosts are joined to active directory for authentication
adJoined: false
# If ESXi is joined to AD, enter the AD group that has administrative access to ESXi.
adAdminGroup: 'MyAdAdminGroup'
# Enter the environment specific syslog server ESXi should be forwarding logs to
syslogServer: 'tcp://log.test.local:514'
# Enter the environment specific time servers.
esxiNtpServers:
  - 'time-a-g.nist.gov'
  - 'time-b-g.nist.gov'
# Enter the environment specific vMotion VLAN Id.
vMotionVlanId: '100'
# Enter the environment specific Management VLAN Id.
mgtVlanId: '101'
# Enter an array of users that should be in the lockdown mode exceptions list.
exceptionUsers:
  - root
  - dcui
# If snmp is used in the environment change to true.
snmpEnabled: 'false'
# Enter the latest build number for ESXi.
esxiBuildNumber: '21813344'

Run the audit

In this example we will be scanning a single ESXi host attached to the target vCenter, specifying an inputs file, enabling enhanced outcomes in InSpec, and outputting a report to the CLI and to a JSON file.

# Navigate to the InSpec profile folder
cd /usr/share/stigs/vsphere/8.0/v1r1-stig/vsphere/inspec/vmware-vsphere-8.0-stig-baseline

# Run the audit
> cinc-auditor exec ./esxi/ -t vmware:// --show-progress --enhanced-outcomes --input-file ./inputs-example.yml --reporter cli json:/tmp/reports/MyESXi8Report.json

# Shown below is the last part of the output at the CLI.
  [N/A]  ESXI-80-000241: The ESXi host must not use the default Active Directory ESX Admin group.
     [SKIP]  The ESXi host 10.186.25.26 is not joined to AD, so this control is not applicable.
  [PASS]  ESXI-80-000243: The ESXi host must configure a persistent log location for all locally stored logs.
     [PASS]  PowerCLI Command: $vmhost = Get-VMHost -Name 10.186.25.26; $esxcli = Get-EsxCli -VMHost $vmhost -V2; $esxcli.system.syslog.config.get.Invoke() | Select-Object -ExpandProperty LocalLogOutputIsPersistent stdout.strip is expected to cmp == "true"
  [FAIL]  ESXI-80-000244: The ESXi host must enforce the exclusive running of executables from approved VIBs.
     [FAIL]  PowerCLI Command: Get-VMHost -Name 10.186.25.26 | Get-AdvancedSetting -Name VMkernel.Boot.execInstalledOnly | Select-Object -ExpandProperty Value stdout.strip is expected to cmp == "true"

     expected: true
          got: False

     (compared using `cmp` matcher)

  [PASS]  ESXI-80-000245: The ESXi host must use sufficient entropy for cryptographic operations.
     [PASS]  PowerCLI Command: $vmhost = Get-VMHost -Name 10.186.25.26; $esxcli = Get-EsxCli -VMHost $vmhost -V2; $esxcli.system.settings.kernel.list.invoke()| Where {$_.Name -eq "disableHwrng"} | Select-Object -ExpandProperty Configured stdout.strip is expected to cmp == "FALSE"
     [PASS]  PowerCLI Command: $vmhost = Get-VMHost -Name 10.186.25.26; $esxcli = Get-EsxCli -VMHost $vmhost -V2; $esxcli.system.settings.kernel.list.invoke()| Where {$_.Name -eq "entropySources"} | Select-Object -ExpandProperty Configured stdout.strip is expected to cmp == "0"
  [PASS]  ESXI-80-000246: The ESXi host must not enable log filtering.
     [PASS]  PowerCLI Command: $vmhost = Get-VMHost -Name 10.186.25.26; $esxcli = Get-EsxCli -VMHost $vmhost -V2; $esxcli.system.syslog.config.logfilter.get.invoke() | Select-Object -ExpandProperty LogFilteringEnabled stdout.strip is expected to cmp == "false"

Profile Summary: 29 successful controls, 26 control failures, 18 controls not reviewed, 4 controls not applicable, 0 controls have error
Test Summary: 41 successful, 51 failures, 23 skipped
# Navigate to the InSpec profile folder
cd /usr/share/stigs/vsphere/8.0/v1r1-srg/vsphere/inspec/vmware-vsphere-8.0-stig-baseline

# Run the audit
> cinc-auditor exec ./esxi/ -t vmware:// --show-progress --enhanced-outcomes --input-file ./inputs-example.yml --reporter cli json:/tmp/reports/MyESXi8Report.json

# Shown below is the last part of the output at the CLI.
  [N/A]  ESXI-80-000241: The ESXi host must not use the default Active Directory ESX Admin group.
     [SKIP]  The ESXi host 10.186.25.26 is not joined to AD, so this control is not applicable.
  [PASS]  ESXI-80-000243: The ESXi host must configure a persistent log location for all locally stored logs.
     [PASS]  PowerCLI Command: $vmhost = Get-VMHost -Name 10.186.25.26; $esxcli = Get-EsxCli -VMHost $vmhost -V2; $esxcli.system.syslog.config.get.Invoke() | Select-Object -ExpandProperty LocalLogOutputIsPersistent stdout.strip is expected to cmp == "true"
  [FAIL]  ESXI-80-000244: The ESXi host must enforce the exclusive running of executables from approved VIBs.
     [FAIL]  PowerCLI Command: Get-VMHost -Name 10.186.25.26 | Get-AdvancedSetting -Name VMkernel.Boot.execInstalledOnly | Select-Object -ExpandProperty Value stdout.strip is expected to cmp == "true"

     expected: true
          got: False

     (compared using `cmp` matcher)

  [PASS]  ESXI-80-000245: The ESXi host must use sufficient entropy for cryptographic operations.
     [PASS]  PowerCLI Command: $vmhost = Get-VMHost -Name 10.186.25.26; $esxcli = Get-EsxCli -VMHost $vmhost -V2; $esxcli.system.settings.kernel.list.invoke()| Where {$_.Name -eq "disableHwrng"} | Select-Object -ExpandProperty Configured stdout.strip is expected to cmp == "FALSE"
     [PASS]  PowerCLI Command: $vmhost = Get-VMHost -Name 10.186.25.26; $esxcli = Get-EsxCli -VMHost $vmhost -V2; $esxcli.system.settings.kernel.list.invoke()| Where {$_.Name -eq "entropySources"} | Select-Object -ExpandProperty Configured stdout.strip is expected to cmp == "0"
  [PASS]  ESXI-80-000246: The ESXi host must not enable log filtering.
     [PASS]  PowerCLI Command: $vmhost = Get-VMHost -Name 10.186.25.26; $esxcli = Get-EsxCli -VMHost $vmhost -V2; $esxcli.system.syslog.config.logfilter.get.invoke() | Select-Object -ExpandProperty LogFilteringEnabled stdout.strip is expected to cmp == "false"

Profile Summary: 29 successful controls, 26 control failures, 18 controls not reviewed, 4 controls not applicable, 0 controls have error
Test Summary: 41 successful, 51 failures, 23 skipped

Auditing Virtual Machines

Update profile inputs

Included in the vmware-vsphere-8.0-stig-baseline is an example inputs-example.yml file with variables relevant to VMs. This is used to provide InSpec with values specific to the environment being audited.

Open the inputs file for editing.

# Navigate to the InSpec profile folder
cd /usr/share/stigs/vsphere/8.0/v1r1-stig/vsphere/inspec/vmware-vsphere-8.0-stig-baseline

# Edit the inputs file
vi inputs-example.yml
# Navigate to the InSpec profile folder
cd /usr/share/stigs/vsphere/8.0/v1r1-srg/vsphere/inspec/vmware-vsphere-8.0-stig-baseline

# Edit the inputs file
vi inputs-example.yml

Update the inputs as shown below with values relevant to your environment.

# Choose whether to scan a single VM or all VMs in vCenter.
vmName: ""
allvms: true
# Choose whether to scan a single VM or all VMs in vCenter.
vmName: ""
allvms: true

Run the audit

In this example we will be scanning all VMs in the target vCenter, specifying an inputs file, enabling enhanced outcomes in InSpec, and outputting a report to the CLI and to a JSON file.

# Navigate to the InSpec profile folder
cd /usr/share/stigs/vsphere/8.0/v1r1-stig/vsphere/inspec/vmware-vsphere-8.0-stig-baseline

# Run the audit
cinc-auditor exec ./vm/ -t vmware:// --show-progress --enhanced-outcomes --input-file ./inputs-example.yml --reporter cli json:/tmp/reports/MyVMs8Report.json

# Shown below is the last part of the output at the CLI.
  [PASS]  VMCH-80-000207: Virtual machines (VMs) must enable logging.
     [PASS]  VM: stig vm2 is expected to cmp == "true"
     [PASS]  VM: stigvm1 is expected to cmp == "true"
     [PASS]  VM: vCLS-1446f2cc-b6b7-4778-84b7-f73f758dd46c is expected to cmp == "true"
     [PASS]  VM: vCLS-28a51340-7070-4437-b4b1-a87b7480ac7d is expected to cmp == "true"
     [PASS]  VM: vCLS-b680b5a0-5434-48a0-8420-82c95e5ab481 is expected to cmp == "true"
  [PASS]  VMCH-80-000208: Virtual machines (VMs) must not use independent, non-persistent disks.
     [PASS]  Checking the VM: stig vm2 for Non-Persistent Hard Disks is expected not to cmp == "IndependentNonPersistent"
     [PASS]  Checking the VM: stigvm1 for Non-Persistent Hard Disks is expected not to cmp == "IndependentNonPersistent"
     [PASS]  Checking the VM: vCLS-1446f2cc-b6b7-4778-84b7-f73f758dd46c for Non-Persistent Hard Disks is expected not to cmp == "IndependentNonPersistent"
     [PASS]  Checking the VM: vCLS-28a51340-7070-4437-b4b1-a87b7480ac7d for Non-Persistent Hard Disks is expected not to cmp == "IndependentNonPersistent"
     [PASS]  Checking the VM: vCLS-b680b5a0-5434-48a0-8420-82c95e5ab481 for Non-Persistent Hard Disks is expected not to cmp == "IndependentNonPersistent"
  [PASS]  VMCH-80-000209: Virtual machines (VMs) must remove unneeded floppy devices.
     [PASS]  Checking the VM: stig vm2 for Floppy drives is expected to be empty
     [PASS]  Checking the VM: stigvm1 for Floppy drives is expected to be empty
     [PASS]  Checking the VM: vCLS-1446f2cc-b6b7-4778-84b7-f73f758dd46c for Floppy drives is expected to be empty
     [PASS]  Checking the VM: vCLS-28a51340-7070-4437-b4b1-a87b7480ac7d for Floppy drives is expected to be empty
     [PASS]  Checking the VM: vCLS-b680b5a0-5434-48a0-8420-82c95e5ab481 for Floppy drives is expected to be empty
  [PASS]  VMCH-80-000210: Virtual machines (VMs) must remove unneeded CD/DVD devices.
     [PASS]  Checking the VM: stig vm2 for CD/DVD drives is expected to cmp == "false"
     [PASS]  Checking the VM: stigvm1 for CD/DVD drives is expected to cmp == "false"
     [PASS]  Checking the VM: vCLS-1446f2cc-b6b7-4778-84b7-f73f758dd46c for CD/DVD drives is expected to be empty
     [PASS]  Checking the VM: vCLS-28a51340-7070-4437-b4b1-a87b7480ac7d for CD/DVD drives is expected to be empty
     [PASS]  Checking the VM: vCLS-b680b5a0-5434-48a0-8420-82c95e5ab481 for CD/DVD drives is expected to be empty
  [PASS]  VMCH-80-000211: Virtual machines (VMs) must remove unneeded parallel devices.
     [PASS]  Checking the VM: stig vm2 for parallel devices is expected not to match "Parallel"
     [PASS]  Checking the VM: stigvm1 for parallel devices is expected not to match "Parallel"
     [PASS]  Checking the VM: vCLS-1446f2cc-b6b7-4778-84b7-f73f758dd46c for parallel devices is expected not to match "Parallel"
     [PASS]  Checking the VM: vCLS-28a51340-7070-4437-b4b1-a87b7480ac7d for parallel devices is expected not to match "Parallel"
     [PASS]  Checking the VM: vCLS-b680b5a0-5434-48a0-8420-82c95e5ab481 for parallel devices is expected not to match "Parallel"
  [PASS]  VMCH-80-000212: Virtual machines (VMs) must remove unneeded serial devices.
     [PASS]  Checking the VM: stig vm2 for serial devices is expected not to match "Serial"
     [PASS]  Checking the VM: stigvm1 for serial devices is expected not to match "Serial"
     [PASS]  Checking the VM: vCLS-1446f2cc-b6b7-4778-84b7-f73f758dd46c for serial devices is expected not to match "Serial"
     [PASS]  Checking the VM: vCLS-28a51340-7070-4437-b4b1-a87b7480ac7d for serial devices is expected not to match "Serial"
     [PASS]  Checking the VM: vCLS-b680b5a0-5434-48a0-8420-82c95e5ab481 for serial devices is expected not to match "Serial"
  [FAIL]  VMCH-80-000213: Virtual machines (VMs) must remove unneeded USB devices. (2 failed)
     [FAIL]  Checking the VM: stig vm2 for USB devices is expected not to match "USB"
     expected "IDE 0\r\nIDE 1\r\nPS2 controller 0\r\nPCI controller 0\r\nSIO controller 0\r\nKeyboard \r\nPointing ...er \r\nSCSI controller 0\r\nSATA controller 0\r\nCD/DVD drive 1\r\nHard disk 1\r\nNetwork adapter 1" not to match "USB"

     [FAIL]  Checking the VM: stigvm1 for USB devices is expected not to match "USB"
     expected "IDE 0\r\nIDE 1\r\nPS2 controller 0\r\nPCI controller 0\r\nSIO controller 0\r\nKeyboard \r\nPointing ...er \r\nSCSI controller 0\r\nSATA controller 0\r\nCD/DVD drive 1\r\nHard disk 1\r\nNetwork adapter 1" not to match "USB"

     [PASS]  Checking the VM: vCLS-1446f2cc-b6b7-4778-84b7-f73f758dd46c for USB devices is expected not to match "USB"
     [PASS]  Checking the VM: vCLS-28a51340-7070-4437-b4b1-a87b7480ac7d for USB devices is expected not to match "USB"
     [PASS]  Checking the VM: vCLS-b680b5a0-5434-48a0-8420-82c95e5ab481 for USB devices is expected not to match "USB"
  [PASS]  VMCH-80-000214: Virtual machines (VMs) must disable DirectPath I/O devices when not required.
     [PASS]  Checking the VM: stig vm2 for PCI passthrough devices is expected to be empty
     [PASS]  Checking the VM: stigvm1 for PCI passthrough devices is expected to be empty
     [PASS]  Checking the VM: vCLS-1446f2cc-b6b7-4778-84b7-f73f758dd46c for PCI passthrough devices is expected to be empty
     [PASS]  Checking the VM: vCLS-28a51340-7070-4437-b4b1-a87b7480ac7d for PCI passthrough devices is expected to be empty
     [PASS]  Checking the VM: vCLS-b680b5a0-5434-48a0-8420-82c95e5ab481 for PCI passthrough devices is expected to be empty

Profile Summary: 23 successful controls, 2 control failures, 0 controls not reviewed, 0 controls not applicable, 0 controls have error
Test Summary: 121 successful, 4 failures, 0 skipped
# Navigate to the InSpec profile folder
cd /usr/share/stigs/vsphere/8.0/v1r1-srg/vsphere/inspec/vmware-vsphere-8.0-stig-baseline

# Run the audit
cinc-auditor exec ./vm/ -t vmware:// --show-progress --enhanced-outcomes --input-file ./inputs-example.yml --reporter cli json:/tmp/reports/MyVMs8Report.json

# Shown below is the last part of the output at the CLI.
  [PASS]  VMCH-80-000207: Virtual machines (VMs) must enable logging.
     [PASS]  VM: stig vm2 is expected to cmp == "true"
     [PASS]  VM: stigvm1 is expected to cmp == "true"
     [PASS]  VM: vCLS-1446f2cc-b6b7-4778-84b7-f73f758dd46c is expected to cmp == "true"
     [PASS]  VM: vCLS-28a51340-7070-4437-b4b1-a87b7480ac7d is expected to cmp == "true"
     [PASS]  VM: vCLS-b680b5a0-5434-48a0-8420-82c95e5ab481 is expected to cmp == "true"
  [PASS]  VMCH-80-000208: Virtual machines (VMs) must not use independent, non-persistent disks.
     [PASS]  Checking the VM: stig vm2 for Non-Persistent Hard Disks is expected not to cmp == "IndependentNonPersistent"
     [PASS]  Checking the VM: stigvm1 for Non-Persistent Hard Disks is expected not to cmp == "IndependentNonPersistent"
     [PASS]  Checking the VM: vCLS-1446f2cc-b6b7-4778-84b7-f73f758dd46c for Non-Persistent Hard Disks is expected not to cmp == "IndependentNonPersistent"
     [PASS]  Checking the VM: vCLS-28a51340-7070-4437-b4b1-a87b7480ac7d for Non-Persistent Hard Disks is expected not to cmp == "IndependentNonPersistent"
     [PASS]  Checking the VM: vCLS-b680b5a0-5434-48a0-8420-82c95e5ab481 for Non-Persistent Hard Disks is expected not to cmp == "IndependentNonPersistent"
  [PASS]  VMCH-80-000209: Virtual machines (VMs) must remove unneeded floppy devices.
     [PASS]  Checking the VM: stig vm2 for Floppy drives is expected to be empty
     [PASS]  Checking the VM: stigvm1 for Floppy drives is expected to be empty
     [PASS]  Checking the VM: vCLS-1446f2cc-b6b7-4778-84b7-f73f758dd46c for Floppy drives is expected to be empty
     [PASS]  Checking the VM: vCLS-28a51340-7070-4437-b4b1-a87b7480ac7d for Floppy drives is expected to be empty
     [PASS]  Checking the VM: vCLS-b680b5a0-5434-48a0-8420-82c95e5ab481 for Floppy drives is expected to be empty
  [PASS]  VMCH-80-000210: Virtual machines (VMs) must remove unneeded CD/DVD devices.
     [PASS]  Checking the VM: stig vm2 for CD/DVD drives is expected to cmp == "false"
     [PASS]  Checking the VM: stigvm1 for CD/DVD drives is expected to cmp == "false"
     [PASS]  Checking the VM: vCLS-1446f2cc-b6b7-4778-84b7-f73f758dd46c for CD/DVD drives is expected to be empty
     [PASS]  Checking the VM: vCLS-28a51340-7070-4437-b4b1-a87b7480ac7d for CD/DVD drives is expected to be empty
     [PASS]  Checking the VM: vCLS-b680b5a0-5434-48a0-8420-82c95e5ab481 for CD/DVD drives is expected to be empty
  [PASS]  VMCH-80-000211: Virtual machines (VMs) must remove unneeded parallel devices.
     [PASS]  Checking the VM: stig vm2 for parallel devices is expected not to match "Parallel"
     [PASS]  Checking the VM: stigvm1 for parallel devices is expected not to match "Parallel"
     [PASS]  Checking the VM: vCLS-1446f2cc-b6b7-4778-84b7-f73f758dd46c for parallel devices is expected not to match "Parallel"
     [PASS]  Checking the VM: vCLS-28a51340-7070-4437-b4b1-a87b7480ac7d for parallel devices is expected not to match "Parallel"
     [PASS]  Checking the VM: vCLS-b680b5a0-5434-48a0-8420-82c95e5ab481 for parallel devices is expected not to match "Parallel"
  [PASS]  VMCH-80-000212: Virtual machines (VMs) must remove unneeded serial devices.
     [PASS]  Checking the VM: stig vm2 for serial devices is expected not to match "Serial"
     [PASS]  Checking the VM: stigvm1 for serial devices is expected not to match "Serial"
     [PASS]  Checking the VM: vCLS-1446f2cc-b6b7-4778-84b7-f73f758dd46c for serial devices is expected not to match "Serial"
     [PASS]  Checking the VM: vCLS-28a51340-7070-4437-b4b1-a87b7480ac7d for serial devices is expected not to match "Serial"
     [PASS]  Checking the VM: vCLS-b680b5a0-5434-48a0-8420-82c95e5ab481 for serial devices is expected not to match "Serial"
  [FAIL]  VMCH-80-000213: Virtual machines (VMs) must remove unneeded USB devices. (2 failed)
     [FAIL]  Checking the VM: stig vm2 for USB devices is expected not to match "USB"
     expected "IDE 0\r\nIDE 1\r\nPS2 controller 0\r\nPCI controller 0\r\nSIO controller 0\r\nKeyboard \r\nPointing ...er \r\nSCSI controller 0\r\nSATA controller 0\r\nCD/DVD drive 1\r\nHard disk 1\r\nNetwork adapter 1" not to match "USB"

     [FAIL]  Checking the VM: stigvm1 for USB devices is expected not to match "USB"
     expected "IDE 0\r\nIDE 1\r\nPS2 controller 0\r\nPCI controller 0\r\nSIO controller 0\r\nKeyboard \r\nPointing ...er \r\nSCSI controller 0\r\nSATA controller 0\r\nCD/DVD drive 1\r\nHard disk 1\r\nNetwork adapter 1" not to match "USB"

     [PASS]  Checking the VM: vCLS-1446f2cc-b6b7-4778-84b7-f73f758dd46c for USB devices is expected not to match "USB"
     [PASS]  Checking the VM: vCLS-28a51340-7070-4437-b4b1-a87b7480ac7d for USB devices is expected not to match "USB"
     [PASS]  Checking the VM: vCLS-b680b5a0-5434-48a0-8420-82c95e5ab481 for USB devices is expected not to match "USB"
  [PASS]  VMCH-80-000214: Virtual machines (VMs) must disable DirectPath I/O devices when not required.
     [PASS]  Checking the VM: stig vm2 for PCI passthrough devices is expected to be empty
     [PASS]  Checking the VM: stigvm1 for PCI passthrough devices is expected to be empty
     [PASS]  Checking the VM: vCLS-1446f2cc-b6b7-4778-84b7-f73f758dd46c for PCI passthrough devices is expected to be empty
     [PASS]  Checking the VM: vCLS-28a51340-7070-4437-b4b1-a87b7480ac7d for PCI passthrough devices is expected to be empty
     [PASS]  Checking the VM: vCLS-b680b5a0-5434-48a0-8420-82c95e5ab481 for PCI passthrough devices is expected to be empty

Profile Summary: 23 successful controls, 2 control failures, 0 controls not reviewed, 0 controls not applicable, 0 controls have error
Test Summary: 121 successful, 4 failures, 0 skipped

Auditing vCenter

Update profile inputs

Included in the vmware-vsphere-8.0-stig-baseline is an example inputs-example.yml file with variables relevant to vCenter. This is used to provide InSpec with values specific to the environment being audited.

Open the inputs file for editing.

# Navigate to the InSpec profile folder
cd /usr/share/stigs/vsphere/8.0/v1r1-stig/vsphere/inspec/vmware-vsphere-8.0-stig-baseline

# Edit the inputs file
vi inputs-example.yml
# Navigate to the InSpec profile folder
cd /usr/share/stigs/vsphere/8.0/v1r1-srg/vsphere/inspec/vmware-vsphere-8.0-stig-baseline

# Edit the inputs file
vi inputs-example.yml

Update the inputs as shown below with values relevant to your environment.

# Enter the environment specific syslog server vCenter should be forwarding logs to.
syslogServers:
  - 'loginsight.vmware.com'
  - 'syslog.server2.com'
# Enter the environment specific time servers.
ntpServers:
  - 'time-a-g.nist.gov'
  - 'time-b-g.nist.gov'
# If an IPfix collector is used enter the IP.
ipfixCollectorAddress: ''
# List any users/groups that should be in the default roles that have crypto permissions. The default users/groups are provided below.
vcCryptoAdmins:
  - 'VSPHERE.LOCAL\Administrator'
  - 'VSPHERE.LOCAL\Administrators'
  - 'VSPHERE.LOCAL\vCLSAdmin'
# List any roles that are approved to have crypto permissions. The default roles are provided below.
vcCryptoRoles:
  - 'Admin'
  - 'NoTrustedAdmin'
  - 'vCLSAdmin'
  - 'vSphereKubernetesManager'
# Enter any approved users in the bash shell administrators users group
bashShellAdminUsers:
  - 'Administrator'
# Enter any approved group in the bash shell administrators group
bashShellAdminGroups: []
# Enter any approved users in the trusted admin users group
trustedAdminUsers: []
# Enter any approved users in the trusted admin group
trustedAdminGroups: []
# Set to false if file based backups are used via the VAMI
backup3rdParty: false
# Enter the environment specific syslog server vCenter should be forwarding logs to.
syslogServers:
  - 'loginsight.vmware.com'
  - 'syslog.server2.com'
# Enter the environment specific time servers.
ntpServers:
  - 'time-a-g.nist.gov'
  - 'time-b-g.nist.gov'
# If an IPfix collector is used enter the IP.
ipfixCollectorAddress: ''
# List any users/groups that should be in the default roles that have crypto permissions. The default users/groups are provided below.
vcCryptoAdmins:
  - 'VSPHERE.LOCAL\Administrator'
  - 'VSPHERE.LOCAL\Administrators'
  - 'VSPHERE.LOCAL\vCLSAdmin'
# List any roles that are approved to have crypto permissions. The default roles are provided below.
vcCryptoRoles:
  - 'Admin'
  - 'NoTrustedAdmin'
  - 'vCLSAdmin'
  - 'vSphereKubernetesManager'
# Enter any approved users in the bash shell administrators users group
bashShellAdminUsers:
  - 'Administrator'
# Enter any approved group in the bash shell administrators group
bashShellAdminGroups: []
# Enter any approved users in the trusted admin users group
trustedAdminUsers: []
# Enter any approved users in the trusted admin group
trustedAdminGroups: []
# Set to false if file based backups are used via the VAMI
backup3rdParty: false

Run the audit

In this example we will be scanning vCenter controls in the target vCenter, specifying an inputs file, enabling enhanced outcomes in InSpec, and outputting a report to the CLI and to a JSON file.

# Navigate to the InSpec profile folder
cd /usr/share/stigs/vsphere/8.0/v1r1-stig/vsphere/inspec/vmware-vsphere-8.0-stig-baseline

# Run the audit
cinc-auditor exec ./vcenter/ -t vmware:// --show-progress --enhanced-outcomes --input-file ./inputs-example.yml --reporter cli json:/tmp/reports/MyvCenter8Report.json

# Shown below is the last part of the output at the CLI.
  [PASS]  VCSA-80-000302: The vCenter Server must reset port configuration when virtual machines are disconnected.
     [PASS]  PowerCLI Command: (Get-VDPortgroup -Name "VDSwitch STIG 1-DVUplinks-40").ExtensionData.Config.Policy.PortConfigResetAtDisconnect stdout.strip is expected to cmp == "True"
     [PASS]  PowerCLI Command: (Get-VDPortgroup -Name "VD PG 1").ExtensionData.Config.Policy.PortConfigResetAtDisconnect stdout.strip is expected to cmp == "True"
     [PASS]  PowerCLI Command: (Get-VDPortgroup -Name "VD PG 2").ExtensionData.Config.Policy.PortConfigResetAtDisconnect stdout.strip is expected to cmp == "True"
     [PASS]  PowerCLI Command: (Get-VDPortgroup -Name "VDSwitch STIG 2-DVUplinks-44").ExtensionData.Config.Policy.PortConfigResetAtDisconnect stdout.strip is expected to cmp == "True"
     [PASS]  PowerCLI Command: (Get-VDPortgroup -Name "VD PG 3").ExtensionData.Config.Policy.PortConfigResetAtDisconnect stdout.strip is expected to cmp == "True"
     [PASS]  PowerCLI Command: (Get-VDPortgroup -Name "VD PG 4").ExtensionData.Config.Policy.PortConfigResetAtDisconnect stdout.strip is expected to cmp == "True"
  [FAIL]  VCSA-80-000303: The vCenter Server must disable Secure Shell (SSH) access.
     [FAIL]  True is expected not to cmp == "true"

     expected: true
          got: True

     (compared using `cmp` matcher)

  [FAIL]  VCSA-80-000304: The vCenter Server must enable data in transit encryption for vSAN.
     [FAIL]  PowerCLI Command: $vsanclusterconf = Get-VsanView -Id VsanVcClusterConfigSystem-vsan-cluster-config-system; $vsanclusterconf.VsanClusterGetConfig((Get-Cluster -Name cluster0).ExtensionData.MoRef).DataInTransitEncryptionConfig.Enabled stdout.strip is expected to cmp == "true"

     expected: true
          got:

     (compared using `cmp` matcher)

Profile Summary: 25 successful controls, 22 control failures, 16 controls not reviewed, 3 controls not applicable, 0 controls have error
Test Summary: 136 successful, 26 failures, 20 skipped
# Navigate to the InSpec profile folder
cd /usr/share/stigs/vsphere/8.0/v1r1-srg/vsphere/inspec/vmware-vsphere-8.0-stig-baseline

# Run the audit
cinc-auditor exec ./vcenter/ -t vmware:// --show-progress --enhanced-outcomes --input-file ./inputs-example.yml --reporter cli json:/tmp/reports/MyvCenter8Report.json

# Shown below is the last part of the output at the CLI.
  [PASS]  VCSA-80-000302: The vCenter Server must reset port configuration when virtual machines are disconnected.
     [PASS]  PowerCLI Command: (Get-VDPortgroup -Name "VDSwitch STIG 1-DVUplinks-40").ExtensionData.Config.Policy.PortConfigResetAtDisconnect stdout.strip is expected to cmp == "True"
     [PASS]  PowerCLI Command: (Get-VDPortgroup -Name "VD PG 1").ExtensionData.Config.Policy.PortConfigResetAtDisconnect stdout.strip is expected to cmp == "True"
     [PASS]  PowerCLI Command: (Get-VDPortgroup -Name "VD PG 2").ExtensionData.Config.Policy.PortConfigResetAtDisconnect stdout.strip is expected to cmp == "True"
     [PASS]  PowerCLI Command: (Get-VDPortgroup -Name "VDSwitch STIG 2-DVUplinks-44").ExtensionData.Config.Policy.PortConfigResetAtDisconnect stdout.strip is expected to cmp == "True"
     [PASS]  PowerCLI Command: (Get-VDPortgroup -Name "VD PG 3").ExtensionData.Config.Policy.PortConfigResetAtDisconnect stdout.strip is expected to cmp == "True"
     [PASS]  PowerCLI Command: (Get-VDPortgroup -Name "VD PG 4").ExtensionData.Config.Policy.PortConfigResetAtDisconnect stdout.strip is expected to cmp == "True"
  [FAIL]  VCSA-80-000303: The vCenter Server must disable Secure Shell (SSH) access.
     [FAIL]  True is expected not to cmp == "true"

     expected: true
          got: True

     (compared using `cmp` matcher)

  [FAIL]  VCSA-80-000304: The vCenter Server must enable data in transit encryption for vSAN.
     [FAIL]  PowerCLI Command: $vsanclusterconf = Get-VsanView -Id VsanVcClusterConfigSystem-vsan-cluster-config-system; $vsanclusterconf.VsanClusterGetConfig((Get-Cluster -Name cluster0).ExtensionData.MoRef).DataInTransitEncryptionConfig.Enabled stdout.strip is expected to cmp == "true"

     expected: true
          got:

     (compared using `cmp` matcher)

Profile Summary: 25 successful controls, 22 control failures, 16 controls not reviewed, 3 controls not applicable, 0 controls have error
Test Summary: 136 successful, 26 failures, 20 skipped

Run a combined scan for all vSphere product controls

Instead of running each STIG for product controls separately you can also run all of the vCenter, ESXi, and VM controls for a combined report.

# Navigate to the InSpec profile folder
cd /usr/share/stigs/vsphere/8.0/v1r1-stig/vsphere/inspec/vmware-vsphere-8.0-stig-baseline

# Run the script
cinc-auditor exec . -t vmware:// --show-progress --enhanced-outcomes --input-file ./inputs-example.yml --reporter cli json:/tmp/reports/MyvSphere8Report.json
# Navigate to the InSpec profile folder
cd /usr/share/stigs/vsphere/8.0/v1r1-srg/vsphere/inspec/vmware-vsphere-8.0-stig-baseline

# Run the audit
cinc-auditor exec . -t vmware:// --show-progress --enhanced-outcomes --input-file ./inputs-example.yml --reporter cli json:/tmp/reports/MyvSphere8Report.json

InSpec runner scripts

For accreditation purposes there may be a requirement to produce a CKL file for each ESXi host and/or VM. We have also created a PowerCLI script that acts as a runner for InSpec to loop through a list of hosts or VMs, then produce a json report for each, and if the SAF CLI is installed also create a CKL file.

With this script you can also provide an attestation file that will be applied to the results and incorporated into the CKL file.

Using the ESXi runner script

To use the runner script, do the following:

# Enter Powershell
pwsh

# If not already previously done setup the credential for the vCenter connection.
# Note: VISERVER is referencing vCenter and not an ESXi host.
$env:VISERVER='10.186.30.81'
$env:VISERVER_USERNAME='Administrator@vsphere.local'
$env:VISERVER_PASSWORD='password'

# Navigate to the powercli folder
cd /usr/share/stigs/vsphere/8.0/v1r1-stig/vsphere/powercli

# Run the script
./VMware_vSphere_8.0_STIG_ESXi_InSpec_Runner.ps1 -vcenter 10.186.30.81 -reportPath /tmp/reports -inspecPath /usr/share/stigs/vsphere/8.0/v1r1-stig/vsphere/inspec/vmware-vsphere-8.0-stig-baseline -inputsfile ./vmware-vsphere-8.0-stig-esxi-inspec-runner-inputs-example.yml

# You will be prompted for credentials to vCenter. This is to connect via PowerCLI before running InSpec to collect all of the host names to use as an input to InSpec for each individual host audit.
10:08:10 AM ...Enter credentials to connect to vCenter

PowerShell credential request
Enter credentials for vCenter
User: administrator@vsphere.local
Password for user administrator@vsphere.local: ****************

10:08:23 AM ...Connecting to vCenter Server 10.186.30.81
10:08:26 AM ...Getting PowerCLI objects for all ESXi hosts in vCenter: 10.186.30.81
10:08:27 AM ...Validated path for report at C:\Inspec\Reports\Runner
10:08:27 AM ...Report path is C:\Inspec\Reports\Runner and report file is C:\Inspec\Reports\Runner\VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.13-6-7-2023_10-8-4.json
10:08:27 AM ...Running InSpec exec against 10.186.16.13 with inspec exec $inspecPath -t vmware:// --input vmhostName=$name --input-file $inputsFile --show-progress --reporter=json:$reportFile
FFFF...F...*.FF*..FFFFF.**.*.FF*.FFF.F..F*F.**********............F..*F.FF.F*..FFFF**FFFFFFFFFFFFFFFFF.FFFFF**.F...
10:10:06 AM ...Detected saf cli...generating STIG Viewer Checklist for 10.186.16.13
10:10:11 AM ...Report path is C:\Inspec\Reports\Runner and report file is C:\Inspec\Reports\Runner\VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.134-6-7-2023_10-8-4.json
10:10:11 AM ...Running InSpec exec against 10.186.16.134 with inspec exec $inspecPath -t vmware:// --input vmhostName=$name --input-file $inputsFile --show-progress --reporter=json:$reportFile
FFFF...F...*.FF*..FFFFF.**.*.FF*.FFF.F..F*F.**********............F..*F.FF.F*..FFFF**FFFFFFFFFFFFFFFFF.FFFFF**.F...
10:11:51 AM ...Detected saf cli...generating STIG Viewer Checklist for 10.186.16.134
10:11:56 AM ...Report path is C:\Inspec\Reports\Runner and report file is C:\Inspec\Reports\Runner\VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.25.26-6-7-2023_10-8-4.json
10:11:56 AM ...Running InSpec exec against 10.186.25.26 with inspec exec $inspecPath -t vmware:// --input vmhostName=$name --input-file $inputsFile --show-progress --reporter=json:$reportFile
FFFF...F...*.FF*..FFFFF.**.*.FF*.FFF.F..F*F.**********............F..*F.FF.F*..FFFF**FFFFFFFFFFFFFFFFF.FFFFF**.F...
10:13:26 AM ...Detected saf cli...generating STIG Viewer Checklist for 10.186.25.26
10:13:30 AM ...Disconnecting from vCenter

# Resulting output
ls /tmp/reports

    Directory: /tmp/reports

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---            6/7/2023 10:10 AM         473286 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.13-6-7-2023_10-8-4.ckl
-a---            6/7/2023 10:10 AM         521076 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.13-6-7-2023_10-8-4.json
-a---            6/7/2023 10:11 AM         473364 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.134-6-7-2023_10-8-4.ckl
-a---            6/7/2023 10:11 AM         521228 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.134-6-7-2023_10-8-4.json
-a---            6/7/2023 10:13 AM         473286 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.25.26-6-7-2023_10-8-4.ckl
-a---            6/7/2023 10:13 AM         521082 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.25.26-6-7-2023_10-8-4.json

# If you want to specify a attestation file to incorporate into the CKL results you can add the attestation argument to the command as follows:
./VMware_vSphere_8.0_STIG_ESXi_InSpec_Runner.ps1 -vcenter 10.186.30.81 -reportPath /tmp/reports -inspecPath /usr/share/stigs/vsphere/8.0/v1r1-stig/vsphere/inspec/vmware-vsphere-8.0-stig-baseline -inputsfile ./vmware-vsphere-8.0-stig-esxi-inspec-runner-inputs-example.yml -attestationFile ./vmware-vsphere-8.0-stig-esxi-inspec-runner-attestation-example.yml

# Resulting output
ls /tmp/reports

    Directory: /tmp/reports

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---            6/7/2023 10:39 AM         473326 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.13-6-7-2023_10-37-15_with_Attestations.ckl
-a---            6/7/2023 10:39 AM         592992 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.13-6-7-2023_10-37-15_with_Attestations.json
-a---            6/7/2023 10:39 AM         521084 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.13-6-7-2023_10-37-15.json
-a---            6/7/2023 10:41 AM         473404 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.134-6-7-2023_10-37-15_with_Attestations.ckl
-a---            6/7/2023 10:41 AM         593137 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.134-6-7-2023_10-37-15_with_Attestations.json
-a---            6/7/2023 10:40 AM         521230 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.134-6-7-2023_10-37-15.json
-a---            6/7/2023 10:42 AM         473326 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.25.26-6-7-2023_10-37-15_with_Attestations.ckl
-a---            6/7/2023 10:42 AM         592988 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.25.26-6-7-2023_10-37-15_with_Attestations.json
-a---            6/7/2023 10:42 AM         521082 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.25.26-6-7-2023_10-37-15.json
# Enter Powershell
pwsh

# If not already previously done setup the credential for the vCenter connection.
# Note: VISERVER is referencing vCenter and not an ESXi host.
$env:VISERVER='10.186.30.81'
$env:VISERVER_USERNAME='Administrator@vsphere.local'
$env:VISERVER_PASSWORD='password'

# Navigate to the powercli folder
cd /usr/share/stigs/vsphere/8.0/v1r1-srg/vsphere/powercli

# Run the script
./VMware_vSphere_8.0_STIG_ESXi_InSpec_Runner.ps1 -vcenter 10.186.30.81 -reportPath /tmp/reports -inspecPath /usr/share/stigs/vsphere/8.0/v1r1-srg/vsphere/inspec/vmware-vsphere-8.0-stig-baseline -inputsfile ./vmware-vsphere-8.0-stig-esxi-inspec-runner-inputs-example.yml

# You will be prompted for credentials to vCenter. This is to connect via PowerCLI before running InSpec to collect all of the host names to use as an input to InSpec for each individual host audit.
10:08:10 AM ...Enter credentials to connect to vCenter

PowerShell credential request
Enter credentials for vCenter
User: administrator@vsphere.local
Password for user administrator@vsphere.local: ****************

10:08:23 AM ...Connecting to vCenter Server 10.186.30.81
10:08:26 AM ...Getting PowerCLI objects for all ESXi hosts in vCenter: 10.186.30.81
10:08:27 AM ...Validated path for report at C:\Inspec\Reports\Runner
10:08:27 AM ...Report path is C:\Inspec\Reports\Runner and report file is C:\Inspec\Reports\Runner\VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.13-6-7-2023_10-8-4.json
10:08:27 AM ...Running InSpec exec against 10.186.16.13 with inspec exec $inspecPath -t vmware:// --input vmhostName=$name --input-file $inputsFile --show-progress --reporter=json:$reportFile
FFFF...F...*.FF*..FFFFF.**.*.FF*.FFF.F..F*F.**********............F..*F.FF.F*..FFFF**FFFFFFFFFFFFFFFFF.FFFFF**.F...
10:10:06 AM ...Detected saf cli...generating STIG Viewer Checklist for 10.186.16.13
10:10:11 AM ...Report path is C:\Inspec\Reports\Runner and report file is C:\Inspec\Reports\Runner\VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.134-6-7-2023_10-8-4.json
10:10:11 AM ...Running InSpec exec against 10.186.16.134 with inspec exec $inspecPath -t vmware:// --input vmhostName=$name --input-file $inputsFile --show-progress --reporter=json:$reportFile
FFFF...F...*.FF*..FFFFF.**.*.FF*.FFF.F..F*F.**********............F..*F.FF.F*..FFFF**FFFFFFFFFFFFFFFFF.FFFFF**.F...
10:11:51 AM ...Detected saf cli...generating STIG Viewer Checklist for 10.186.16.134
10:11:56 AM ...Report path is C:\Inspec\Reports\Runner and report file is C:\Inspec\Reports\Runner\VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.25.26-6-7-2023_10-8-4.json
10:11:56 AM ...Running InSpec exec against 10.186.25.26 with inspec exec $inspecPath -t vmware:// --input vmhostName=$name --input-file $inputsFile --show-progress --reporter=json:$reportFile
FFFF...F...*.FF*..FFFFF.**.*.FF*.FFF.F..F*F.**********............F..*F.FF.F*..FFFF**FFFFFFFFFFFFFFFFF.FFFFF**.F...
10:13:26 AM ...Detected saf cli...generating STIG Viewer Checklist for 10.186.25.26
10:13:30 AM ...Disconnecting from vCenter

# Resulting output
ls /tmp/reports

    Directory: /tmp/reports

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---            6/7/2023 10:10 AM         473286 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.13-6-7-2023_10-8-4.ckl
-a---            6/7/2023 10:10 AM         521076 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.13-6-7-2023_10-8-4.json
-a---            6/7/2023 10:11 AM         473364 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.134-6-7-2023_10-8-4.ckl
-a---            6/7/2023 10:11 AM         521228 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.134-6-7-2023_10-8-4.json
-a---            6/7/2023 10:13 AM         473286 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.25.26-6-7-2023_10-8-4.ckl
-a---            6/7/2023 10:13 AM         521082 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.25.26-6-7-2023_10-8-4.json

# If you want to specify a attestation file to incorporate into the CKL results you can add the attestation argument to the command as follows:
./VMware_vSphere_8.0_STIG_ESXi_InSpec_Runner.ps1 -vcenter 10.186.30.81 -reportPath /tmp/reports -inspecPath /usr/share/stigs/vsphere/8.0/v1r1-srg/vsphere/inspec/vmware-vsphere-8.0-stig-baseline -inputsfile ./vmware-vsphere-8.0-stig-esxi-inspec-runner-inputs-example.yml -attestationFile ./vmware-vsphere-8.0-stig-esxi-inspec-runner-attestation-example.yml

# Resulting output
ls /tmp/reports

    Directory: /tmp/reports

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---            6/7/2023 10:39 AM         473326 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.13-6-7-2023_10-37-15_with_Attestations.ckl
-a---            6/7/2023 10:39 AM         592992 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.13-6-7-2023_10-37-15_with_Attestations.json
-a---            6/7/2023 10:39 AM         521084 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.13-6-7-2023_10-37-15.json
-a---            6/7/2023 10:41 AM         473404 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.134-6-7-2023_10-37-15_with_Attestations.ckl
-a---            6/7/2023 10:41 AM         593137 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.134-6-7-2023_10-37-15_with_Attestations.json
-a---            6/7/2023 10:40 AM         521230 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.16.134-6-7-2023_10-37-15.json
-a---            6/7/2023 10:42 AM         473326 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.25.26-6-7-2023_10-37-15_with_Attestations.ckl
-a---            6/7/2023 10:42 AM         592988 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.25.26-6-7-2023_10-37-15_with_Attestations.json
-a---            6/7/2023 10:42 AM         521082 VMware_vSphere_8.0_STIG_ESXi_Inspec_Report_10.186.25.26-6-7-2023_10-37-15.json

Auditing vCenter (Appliance Controls)

Auditing the vCenter appliance is done over SSH which must be enabled for the scan.

Update the default shell for root

The default shell for root must be changed to /bin/bash before running. The appliance shell causes issues with some controls running.

# SSH to vCenter
Connected to service

    * List APIs: "help api list"
    * List Plugins: "help pi list"
    * Launch BASH: "shell"

Command> shell.set --enabled true
Command> shell
Shell access is granted to root
root@sc1-10-182-131-166 [ ~ ]# chsh -s /bin/bash root

Run the audit

In this example we will be scanning the vCenter appliance, specifying an inputs file, and outputting a report to the CLI and to a JSON file.

Updating the inputs file is not required for this profile but the inputs-vcsa-8.0.yml should be specified because it contains inputs for the Photon profile.

# Navigate to the InSpec profile folder
cd /usr/share/stigs/vsphere/8.0/v1r1-stig/vcsa/inspec/vmware-vcsa-8.0-stig-baseline

# Run the audit
cinc-auditor exec . -t ssh://root@10.186.30.81 --password 'password' --show-progress --enhanced-outcomes --input-file ./inputs-vcsa-8.0.yml --reporter cli json:/tmp/reports/MyVCSA8Report.json

# Shown below is the last part of the output at the CLI.
  [PASS]  VCUI-80-000141: The vCenter UI service example applications must be removed.
     [PASS]  false is expected to cmp == "false"
  [PASS]  VCUI-80-000142: The vCenter UI service default ROOT web application must be removed.
     [PASS]  Command: `ls /usr/lib/vmware-vsphere-ui/server/webapps/ROOT` stdout.strip is expected to cmp == ""
  [PASS]  VCUI-80-000143: The vCenter UI service default documentation must be removed.
     [PASS]  false is expected to cmp == "false"
  [PASS]  VCUI-80-000151: The vCenter UI service must disable "ALLOW_BACKSLASH".
     [PASS]  is expected to be in nil and "false"
  [PASS]  VCUI-80-000152: The vCenter UI service must enable "ENFORCE_ENCODING_IN_GET_WRITER".
     [PASS]  is expected to be in nil and "true"
  [PASS]  VCUI-80-000154: The vCenter UI service manager webapp must be removed.
     [PASS]  false is expected to cmp == "false"
  [PASS]  VCUI-80-000155: The vCenter UI service host-manager webapp must be removed.
     [PASS]  false is expected to cmp == "false"

Profile Summary: 304 successful controls, 25 control failures, 0 controls skipped
Test Summary: 1240 successful, 80 failures, 0 skipped
# Navigate to the InSpec profile folder
cd /usr/share/stigs/vsphere/8.0/v1r1-srg/vcsa/inspec/vmware-vcsa-8.0-stig-baseline

# Run the audit
cinc-auditor exec . -t ssh://root@10.186.30.81 --password 'password' --show-progress --enhanced-outcomes --input-file ./inputs-vcsa-8.0.yml --reporter cli json:/tmp/reports/MyVCSA8Report.json

# Shown below is the last part of the output at the CLI.
  [PASS]  VCUI-80-000141: The vCenter UI service example applications must be removed.
     [PASS]  false is expected to cmp == "false"
  [PASS]  VCUI-80-000142: The vCenter UI service default ROOT web application must be removed.
     [PASS]  Command: `ls /usr/lib/vmware-vsphere-ui/server/webapps/ROOT` stdout.strip is expected to cmp == ""
  [PASS]  VCUI-80-000143: The vCenter UI service default documentation must be removed.
     [PASS]  false is expected to cmp == "false"
  [PASS]  VCUI-80-000151: The vCenter UI service must disable "ALLOW_BACKSLASH".
     [PASS]  is expected to be in nil and "false"
  [PASS]  VCUI-80-000152: The vCenter UI service must enable "ENFORCE_ENCODING_IN_GET_WRITER".
     [PASS]  is expected to be in nil and "true"
  [PASS]  VCUI-80-000154: The vCenter UI service manager webapp must be removed.
     [PASS]  false is expected to cmp == "false"
  [PASS]  VCUI-80-000155: The vCenter UI service host-manager webapp must be removed.
     [PASS]  false is expected to cmp == "false"

Profile Summary: 304 successful controls, 25 control failures, 0 controls skipped
Test Summary: 1240 successful, 80 failures, 0 skipped

Convert the results to CKL

If a STIG Viewer CKL file is needed then the results from the scans can be converted to CKL with the SAF CLI.

# Converting the VCSA scan results from the prior section to CKL
saf convert hdf2ckl -i /tmp/reports/MyVCSA8Report.json -o /tmp/reports/MyVCSA8Report.ckl --hostname 10.186.30.81 --fqdn myvcenter.local --ip 10.186.30.81 --mac 00:00:00:00:00:00

Opening the CKL file in STIG Viewer will look like the screenshot below. Note the InSpec results are included in the Finding Details pane.

alt text

4.2.2 - Remediate vSphere 8

Remediating vSphere 8 for STIG Compliance

Overview

Remediating vSphere for STIG compliance involves configuring ESXi, Virtual Machines, vCenter, and the vCenter appliance.

When remediating vSphere we will split up tasks between product and appliance based controls which are defined as follows:

  • Product Control: Configurations that interact with the Product via the User Interface or API that are exposed to administrators. Whether these are Default or Non-Default, the risk of mis-configuration effecting availability of the product is low but could impact how the environment is operated if not assessed.
  • Appliance Control: Appliance controls deal with the underlying components (databases, web servers, Photon OS, etc) that make up the product. Altering these add risk to product availability without precautionary steps and care in implementation. Identifying and relying on Default settings in this category makes this category less risky (Default Appliance Controls should be seen as a positive).

To remediate vSphere, PowerCLI is the automation tool used, while for the VCSA we will use Ansible. For the vCenter appliance the remediation is performed via SSH. It is recommended to disable SSH on vCenter after configuration is complete.

Prerequisites

Versions listed below were used for this documentation. Other versions of these tools may work as well but if issues are found it is recommended to try the versions listed here.

Assumptions

  • Commands are being ran from a Linux machine. Windows will also work (for the PowerCLI portions only) but paths and commands may need to be adjusted from the examples.
  • The DOD Compliance and Automation repository downloaded and extracted to /usr/share/stigs.
  • Ansible installed and all playbook dependencies resolved as provided in the requirements.yml file in each playbook. Install with ansible-galaxy roles install -r requirements.yml.
  • The dependent Photon OS Ansible roles(Photon 3.0 for U1 and Photon 4 for U2) installed and available. Verify role installation with ansible-galaxy role list.

Remediate vSphere (Product Controls)

Create Powershell credential for vCenter connection

The PowerCLI scripts provided use a Powershell Credential stored in a variable to authenticate to vCenter and should be established before attempting to run the scripts.

# Run the following command to generate a credential. Substitute the username as needed in your environment.
pwsh

$vccred = Get-Credential

PowerShell credential request
Enter your credentials.
User: administrator@vsphere.local
Password for user administrator@vsphere.local: ****************

Remediating ESXi product controls

To remediate ESXi hosts we have provided a PowerCLI script that will target a single host or a vSphere cluster based on parameters provided to the script.

Note: There are some controls that cannot be remediated with PowerCLI and are not addressed by this script. The output will indicate that these are manual controls.

Gather environment information

In order to run the script effectively it must be provided with the organizations environment specific information.

Review the below parameters and gather the information needed to run the script:

[CmdletBinding()]
param (
  [Parameter(Mandatory=$true)]
  [string]$vcenter,
  [Parameter(Mandatory=$true)]
  [pscredential]$vccred,
  [Parameter(Mandatory=$true,ParameterSetName="hostname")]
  [string]$hostname,
  [Parameter(Mandatory=$true,ParameterSetName="cluster")]
  [string]$cluster,
  [Parameter(Mandatory=$false,
  HelpMessage="Enter the path for the output report. Example /tmp")]
  [string]$reportpath,  
  [Parameter(Mandatory=$true,
  HelpMessage="Enter the Active Directory Admins group to use for administrative access to ESXi")]
  [string]$esxAdminGroup,
  [Parameter(Mandatory=$true,
  HelpMessage="Enter allowed IP ranges for the ESXi firewall in comma separated format.  For Example "192.168.0.0/16","10.0.0.0/8" ")]
  [string[]]$allowedIPs,
  [Parameter(Mandatory=$false,
  HelpMessage="Enter the syslog server for the ESXi server(s). Example tcp://log.domain.local:514")]
  [string]$syslogServer,
  [Parameter(Mandatory=$false,
  HelpMessage="Enable this option if VMware vRealize Log Insight is used to manage syslog on the ESXi host(s).")]
  [switch]$logInsight,
  [Parameter(Mandatory=$true,
  HelpMessage="Enter NTP servers.  For Example "10.1.1.1","10.1.1.2" ")]
  [string[]]$ntpServers,
  [Parameter(Mandatory=$false,
  HelpMessage="Specify the native VLAN Id configured on the ports going to the ESXi Hosts.  If none is specified the default of 1 will be used.")]
  [string]$nativeVLAN = "1"
)
[CmdletBinding()]
param (
  [Parameter(Mandatory=$true)]
  [string]$vcenter,
  [Parameter(Mandatory=$true)]
  [pscredential]$vccred,
  [Parameter(Mandatory=$true,ParameterSetName="hostname")]
  [string]$hostname,
  [Parameter(Mandatory=$true,ParameterSetName="cluster")]
  [string]$cluster,
  [Parameter(Mandatory=$false,
  HelpMessage="Enter the path for the output report. Example /tmp")]
  [string]$reportpath,  
  [Parameter(Mandatory=$true,
  HelpMessage="Enter the Active Directory Admins group to use for administrative access to ESXi")]
  [string]$esxAdminGroup,
  [Parameter(Mandatory=$true,
  HelpMessage="Enter allowed IP ranges for the ESXi firewall in comma separated format.  For Example "192.168.0.0/16","10.0.0.0/8" ")]
  [string[]]$allowedIPs,
  [Parameter(Mandatory=$false,
  HelpMessage="Enter the syslog server for the ESXi server(s). Example tcp://log.domain.local:514")]
  [string]$syslogServer,
  [Parameter(Mandatory=$false,
  HelpMessage="Enable this option if VMware vRealize Log Insight is used to manage syslog on the ESXi host(s).")]
  [switch]$logInsight,
  [Parameter(Mandatory=$true,
  HelpMessage="Enter NTP servers.  For Example "10.1.1.1","10.1.1.2" ")]
  [string[]]$ntpServers,
  [Parameter(Mandatory=$false,
  HelpMessage="Specify the native VLAN Id configured on the ports going to the ESXi Hosts.  If none is specified the default of 1 will be used.")]
  [string]$nativeVLAN = "1"
)

Disabling Controls

The script includes variables to enable or disable controls by STIG ID. All controls are all enabled by default and can be turned off by changing these variables to $false for a specific control.

A snippet of these variables is shown below.

##### Enable or Disable specific STIG Remediations #####
$controlsenabled = [ordered]@{
  ESXI80000005 = $true  #Account Lock Failures
  ESXI80000006 = $true  #Consent Banner Welcome
  ESXI80000008 = $true  #Lockdown Mode
  ESXI80000010 = $true  #Host Client Timeout

Run remediation script on target ESXi hosts

This example will remediate all hosts in the vSphere cluster named cluster0. If running on a single host is desired, specify the hostname parameter instead of cluster and provide the hostname as displayed in vCenter.

# Navigate to the powercli folder
cd /usr/share/stigs/vsphere/8.0/v1r1-stig/vsphere/powercli

# Running the script.
./VMware_vSphere_8.0_STIG_ESXi_Remediation.ps1 -vcenter 10.182.177.21 -vccred $vccred -cluster "cluster0" -esxAdminGroup "MyESXiGroup" -allowedIPs "10.10.10.0/24","10.10.11.0/24" -ntpServers "time-a-g.nist.gov","time-b-g.nist.gov" -syslogServer "tcp://loginsight.vmware.com:514" -reportpath /tmp/reports

# Snippet from the output of running the script.
2:11:17 PM ...Remediating STIG ID:ESXI-80-000244 with Title: The ESXi host must enforce the exclusive running of executables from approved VIBs.
2:11:17 PM ...Setting VMkernel.Boot.execInstalledOnly was incorrectly set to False on 10.182.180.5...setting to true
VMkernel.Boot.execI True                 VMHost
2:11:18 PM ...Setting VMkernel.Boot.execInstalledOnly was incorrectly set to False on 10.182.182.193...setting to true
VMkernel.Boot.execI True                 VMHost
2:11:20 PM ...Setting VMkernel.Boot.execInstalledOnly was incorrectly set to False on 10.182.183.107...setting to true
VMkernel.Boot.execI True                 VMHost
2:11:21 PM ...Remediating STIG ID:ESXI-80-000245 with Title: The ESXi host must use sufficient entropy for cryptographic operations.
2:11:22 PM ...disableHwrng set correctly to FALSE on 10.182.180.5
2:11:22 PM ...entropySources set correctly to 0 on 10.182.180.5
2:11:23 PM ...disableHwrng set correctly to FALSE on 10.182.182.193
2:11:24 PM ...entropySources set correctly to 0 on 10.182.182.193
2:11:25 PM ...disableHwrng set correctly to FALSE on 10.182.183.107
2:11:25 PM ...entropySources set correctly to 0 on 10.182.183.107
2:11:25 PM ...Remediating STIG ID:ESXI-80-000246 with Title: The ESXi host must not enable log filtering.
2:11:25 PM ...log filtering set correctly to false on 10.182.180.5
2:11:25 PM ...log filtering set correctly to false on 10.182.182.193
2:11:26 PM ...log filtering set correctly to false on 10.182.183.107
2:11:26 PM ...Remediating STIG ID:ESXI-80-000008 with Title: The ESXi host must enable lockdown mode.
2:11:26 PM ...Enabling Lockdown mode with level lockdownNormal on 10.182.180.5
2:11:26 PM ...Enabling Lockdown mode with level lockdownNormal on 10.182.182.193
2:11:27 PM ...Enabling Lockdown mode with level lockdownNormal on 10.182.183.107
2:11:27 PM ...Configuration Summary:
2:11:27 PM {
  "vcenter": "10.182.177.21",
  "hostname": "",
  "cluster": "cluster0",
  "vmhosts": [
    "10.182.180.5",
    "10.182.182.193",
    "10.182.183.107"
  ],
  "reportpath": "/tmp/reports",
  "ok": 99,
  "changed": 123,
  "skipped": 25,
  "failed": 5,

# A results file and Powershell transcript is provided in the report path specified.
Directory: /tmp/reports

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---            6/8/2023  2:11 PM           6578 VMware_vSphere_8.0_STIG_ESXi_Remediation_Results_6-8-2023_14-6-38.json
-a---            6/8/2023  2:11 PM          84552 VMware_vSphere_8.0_STIG_ESXi_Remediation_Transcript_6-8-2023_14-6-38.txt
# Navigate to the powercli folder
cd /usr/share/stigs/vsphere/8.0/v1r1-srg/vsphere/powercli

# Running the script.
./VMware_vSphere_8.0_STIG_ESXi_Remediation.ps1 -vcenter 10.182.177.21 -vccred $vccred -cluster "cluster0" -esxAdminGroup "MyESXiGroup" -allowedIPs "10.10.10.0/24","10.10.11.0/24" -ntpServers "time-a-g.nist.gov","time-b-g.nist.gov" -syslogServer "tcp://loginsight.vmware.com:514" -reportpath /tmp/reports

# Snippet from the output of running the script.
2:11:17 PM ...Remediating STIG ID:ESXI-80-000244 with Title: The ESXi host must enforce the exclusive running of executables from approved VIBs.
2:11:17 PM ...Setting VMkernel.Boot.execInstalledOnly was incorrectly set to False on 10.182.180.5...setting to true
VMkernel.Boot.execI True                 VMHost
2:11:18 PM ...Setting VMkernel.Boot.execInstalledOnly was incorrectly set to False on 10.182.182.193...setting to true
VMkernel.Boot.execI True                 VMHost
2:11:20 PM ...Setting VMkernel.Boot.execInstalledOnly was incorrectly set to False on 10.182.183.107...setting to true
VMkernel.Boot.execI True                 VMHost
2:11:21 PM ...Remediating STIG ID:ESXI-80-000245 with Title: The ESXi host must use sufficient entropy for cryptographic operations.
2:11:22 PM ...disableHwrng set correctly to FALSE on 10.182.180.5
2:11:22 PM ...entropySources set correctly to 0 on 10.182.180.5
2:11:23 PM ...disableHwrng set correctly to FALSE on 10.182.182.193
2:11:24 PM ...entropySources set correctly to 0 on 10.182.182.193
2:11:25 PM ...disableHwrng set correctly to FALSE on 10.182.183.107
2:11:25 PM ...entropySources set correctly to 0 on 10.182.183.107
2:11:25 PM ...Remediating STIG ID:ESXI-80-000246 with Title: The ESXi host must not enable log filtering.
2:11:25 PM ...log filtering set correctly to false on 10.182.180.5
2:11:25 PM ...log filtering set correctly to false on 10.182.182.193
2:11:26 PM ...log filtering set correctly to false on 10.182.183.107
2:11:26 PM ...Remediating STIG ID:ESXI-80-000008 with Title: The ESXi host must enable lockdown mode.
2:11:26 PM ...Enabling Lockdown mode with level lockdownNormal on 10.182.180.5
2:11:26 PM ...Enabling Lockdown mode with level lockdownNormal on 10.182.182.193
2:11:27 PM ...Enabling Lockdown mode with level lockdownNormal on 10.182.183.107
2:11:27 PM ...Configuration Summary:
2:11:27 PM {
  "vcenter": "10.182.177.21",
  "hostname": "",
  "cluster": "cluster0",
  "vmhosts": [
    "10.182.180.5",
    "10.182.182.193",
    "10.182.183.107"
  ],
  "reportpath": "/tmp/reports",
  "ok": 99,
  "changed": 123,
  "skipped": 25,
  "failed": 5,

# A results file and Powershell transcript is provided in the report path specified.
Directory: /tmp/reports

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---            6/8/2023  2:11 PM           6578 VMware_vSphere_8.0_STIG_ESXi_Remediation_Results_6-8-2023_14-6-38.json
-a---            6/8/2023  2:11 PM          84552 VMware_vSphere_8.0_STIG_ESXi_Remediation_Transcript_6-8-2023_14-6-38.txt

Remediating virtual machines

To remediate virtual machines we have provided a PowerCLI script that will target a single VM, all VMs in a cluster, or all VMs in vCenter based on parameters provided to the script.

Note: There are some controls that cannot be remediated with PowerCLI and are not addressed by this script. See the scripts description text for more details.

Disabling Controls

For processing efficiency it is not constructed to run each control individually so the STIG ID variables are not included to enabled/disable controls such as in the ESXi/vCenter scripts. If it is desired to skip some controls they could be commented out in the $vmconfig variable in the script.

Run remediation script on target virtual machines

This example will remediate all hosts in the vSphere cluster named cluster0. If running on a single host is desired, specify the hostname parameter instead of cluster and provide the hostname as displayed in vCenter.

# Navigate to the powercli folder
cd /usr/share/stigs/vsphere/8.0/v1r1-stig/vsphere/powercli

# Running the script.
./VMware_vSphere_8.0_STIG_VM_Remediation.ps1 -vcenter 10.182.177.21 -vccred $vccred -cluster "cluster0" -reportpath /tmp/reports

# Snippet from the output of running the script.
2:13:50 PM ...Connecting to vCenter Server 10.182.177.21
2:13:52 PM ...Getting PowerCLI objects for all virtual machines in cluster: cluster0
2:13:53 PM ...Remediating advanced settings on vCLS-1ef92498-69e3-4c68-b4fa-ef5a25b671b7 on 10.182.177.21
2:13:53 PM ...Setting isolation.device.connectable.disable does not exist on vCLS-1ef92498-69e3-4c68-b4fa-ef5a25b671b7 and is compliant by default...
2:13:53 PM ...Setting isolation.tools.copy.disable does not exist on vCLS-1ef92498-69e3-4c68-b4fa-ef5a25b671b7 and is compliant by default...
2:13:53 PM ...Setting isolation.tools.diskShrink.disable does not exist on vCLS-1ef92498-69e3-4c68-b4fa-ef5a25b671b7 and is compliant by default...
2:13:53 PM ...Setting isolation.tools.diskWiper.disable does not exist on vCLS-1ef92498-69e3-4c68-b4fa-ef5a25b671b7 and is compliant by default...

# A results file and Powershell transcript is provided in the report path specified.
Directory: /tmp/reports

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---            6/8/2023  2:14 PM          10743 VMware_vSphere_8.0_STIG_VM_Remediation_Transcript_6-8-2023_14-13-50.txt
-a---            6/8/2023  2:14 PM           1105 VMware_vSphere_8.0_STIG_VM_Remediation_Transcript_6-8-2023_14-14-7.txt
# Navigate to the powercli folder
cd /usr/share/stigs/vsphere/8.0/v1r1-srg/vsphere/powercli

# Running the script.
./VMware_vSphere_8.0_STIG_VM_Remediation.ps1 -vcenter 10.182.177.21 -vccred $vccred -cluster "cluster0" -reportpath /tmp/reports

# Snippet from the output of running the script.
2:13:50 PM ...Connecting to vCenter Server 10.182.177.21
2:13:52 PM ...Getting PowerCLI objects for all virtual machines in cluster: cluster0
2:13:53 PM ...Remediating advanced settings on vCLS-1ef92498-69e3-4c68-b4fa-ef5a25b671b7 on 10.182.177.21
2:13:53 PM ...Setting isolation.device.connectable.disable does not exist on vCLS-1ef92498-69e3-4c68-b4fa-ef5a25b671b7 and is compliant by default...
2:13:53 PM ...Setting isolation.tools.copy.disable does not exist on vCLS-1ef92498-69e3-4c68-b4fa-ef5a25b671b7 and is compliant by default...
2:13:53 PM ...Setting isolation.tools.diskShrink.disable does not exist on vCLS-1ef92498-69e3-4c68-b4fa-ef5a25b671b7 and is compliant by default...
2:13:53 PM ...Setting isolation.tools.diskWiper.disable does not exist on vCLS-1ef92498-69e3-4c68-b4fa-ef5a25b671b7 and is compliant by default...

# A results file and Powershell transcript is provided in the report path specified.
Directory: /tmp/reports

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---            6/8/2023  2:14 PM          10743 VMware_vSphere_8.0_STIG_VM_Remediation_Transcript_6-8-2023_14-13-50.txt
-a---            6/8/2023  2:14 PM           1105 VMware_vSphere_8.0_STIG_VM_Remediation_Transcript_6-8-2023_14-14-7.txt

Remediating vCenter

To remediate vCenter we have provided a PowerCLI script that will target a single vCenter server.

Note: There are some controls that cannot be remediated with PowerCLI and are not addressed by this script. The output will indicate that these are manual controls.

Gather environment information

In order to run the script effectively it must be provided with the organizations environment specific information.

This script also uses the VMware.Vsphere.SsoAdmin PowerCLI Module to configure vCenter SSO controls. This module connects to vCenter separately using the Connect-SsoAdminServer command that requires using an account that has sufficient privileges in vCenter to modify SSO settings.

Review the below parameters and gather the information needed to run the script:

[CmdletBinding()]
param (
  [Parameter(Mandatory=$true)]
  [string]$vcenter,
  [Parameter(Mandatory=$true)]
  [pscredential]$vccred,
  [Parameter(Mandatory=$false,
  HelpMessage="Enter the path for the output report. Example /tmp")]
  [string]$reportpath,
  [Parameter(Mandatory=$false,
  HelpMessage="If Netflow is used enter the collector IP address")]
  [string]$vcNetflowCollectorIp = "",
  [Parameter(Mandatory=$false,
  HelpMessage="To disable Netflow on all port groups if enabled set to true")]
  [boolean]$vcNetflowDisableonallPortGroups = $false
)
[CmdletBinding()]
param (
  [Parameter(Mandatory=$true)]
  [string]$vcenter,
  [Parameter(Mandatory=$true)]
  [pscredential]$vccred,
  [Parameter(Mandatory=$false,
  HelpMessage="Enter the path for the output report. Example /tmp")]
  [string]$reportpath,
  [Parameter(Mandatory=$false,
  HelpMessage="If Netflow is used enter the collector IP address")]
  [string]$vcNetflowCollectorIp = "",
  [Parameter(Mandatory=$false,
  HelpMessage="To disable Netflow on all port groups if enabled set to true")]
  [boolean]$vcNetflowDisableonallPortGroups = $false
)

Disabling Controls

The script includes variables to enable or disable controls by STIG ID. All controls are all enabled by default and can be turned off by changing these variables to $false for a specific control.

A snippet of these variables is shown below.

##### Enable or Disable specific STIG Remediations #####
$controlsenabled = [ordered]@{
  VCSA8000009 = $true  #TLS 1.2
  VCSA8000023 = $true  #SSO Login Attempts
  VCSA8000024 = $true  #SSO Banner - Manual
  VCSA8000034 = $true  #config.log.level

Run remediation script on target vCenter server

This example will remediate all controls on a target vCenter server.

# Navigate to the powercli folder
cd /usr/share/stigs/vsphere/8.0/v1r1-stig/vsphere/powercli

# Running the script.
./VMware_vSphere_8.0_STIG_vCenter_Remediation.ps1 -vcenter 10.182.177.21 -vccred $vccred -vcNetflowDisableonallPortGroups $true -reportpath /tmp/reports

# Snippet from the output of running the script.
2:27:42 PM ...Connecting to vCenter Server 10.182.177.21
2:27:44 PM ...Connecting to vCenter SSO Server 10.182.177.21
2:27:45 PM ...Verifying vCenter 10.182.177.21 is version 8.0.x
2:27:45 PM ...vCenter 10.182.177.21 is version 8.0.1 continuing...
2:27:45 PM ...Getting PowerCLI objects for all virtual distributed switches in vCenter: 10.182.177.21
2:27:45 PM ...Getting PowerCLI objects for all virtual distributed port groups in vCenter: 10.182.177.21
2:27:46 PM ...Remediating STIG ID: VCSA-80-000009 with Title: The vCenter Server must use TLS 1.2, at a minimum, to protect the confidentiality of sensitive data during electronic dissemination using remote access.
2:27:46 PM ...!!This control must be remediated manually!!
2:27:46 PM ...Remediating STIG ID: VCSA-80-000023 with Title: The vCenter Server must enforce the limit of three consecutive invalid logon attempts by a user.
2:27:47 PM ...SSO login attempts set incorrectly on 10.182.177.21
2:27:47 PM ...Remediating STIG ID: VCSA-80-000024 with Title: The vCenter Server must display the Standard Mandatory DoD Notice and Consent Banner before logon.
2:27:47 PM ...!!This control must be remediated manually!!
2:27:47 PM ...Remediating STIG ID: VCSA-80-000034 with Title: The vCenter Server must produce audit records containing information to establish what type of events occurred.
2:27:47 PM ...Setting config.log.level is already configured correctly to info on 10.182.177.21

# A results file and Powershell transcript is provided in the report path specified.
Directory: /tmp/reports

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---            6/8/2023  2:28 PM           2873 VMware_vSphere_8.0_STIG_vCenter_Remediation_Results_6-8-2023_14-27-42.json
-a---            6/8/2023  2:28 PM          25530 VMware_vSphere_8.0_STIG_vCenter_Remediation_Transcript_6-8-2023_14-27-42.txt
# Navigate to the powercli folder
cd /usr/share/stigs/vsphere/8.0/v1r1-srg/vsphere/powercli

# Running the script.
./VMware_vSphere_8.0_STIG_vCenter_Remediation.ps1 -vcenter 10.182.177.21 -vccred $vccred -vcNetflowDisableonallPortGroups $true -reportpath /tmp/reports

# Snippet from the output of running the script.
2:27:42 PM ...Connecting to vCenter Server 10.182.177.21
2:27:44 PM ...Connecting to vCenter SSO Server 10.182.177.21
2:27:45 PM ...Verifying vCenter 10.182.177.21 is version 8.0.x
2:27:45 PM ...vCenter 10.182.177.21 is version 8.0.1 continuing...
2:27:45 PM ...Getting PowerCLI objects for all virtual distributed switches in vCenter: 10.182.177.21
2:27:45 PM ...Getting PowerCLI objects for all virtual distributed port groups in vCenter: 10.182.177.21
2:27:46 PM ...Remediating STIG ID: VCSA-80-000009 with Title: The vCenter Server must use TLS 1.2, at a minimum, to protect the confidentiality of sensitive data during electronic dissemination using remote access.
2:27:46 PM ...!!This control must be remediated manually!!
2:27:46 PM ...Remediating STIG ID: VCSA-80-000023 with Title: The vCenter Server must enforce the limit of three consecutive invalid logon attempts by a user.
2:27:47 PM ...SSO login attempts set incorrectly on 10.182.177.21
2:27:47 PM ...Remediating STIG ID: VCSA-80-000024 with Title: The vCenter Server must display the Standard Mandatory DoD Notice and Consent Banner before logon.
2:27:47 PM ...!!This control must be remediated manually!!
2:27:47 PM ...Remediating STIG ID: VCSA-80-000034 with Title: The vCenter Server must produce audit records containing information to establish what type of events occurred.
2:27:47 PM ...Setting config.log.level is already configured correctly to info on 10.182.177.21

# A results file and Powershell transcript is provided in the report path specified.
Directory: /tmp/reports

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---            6/8/2023  2:28 PM           2873 VMware_vSphere_8.0_STIG_vCenter_Remediation_Results_6-8-2023_14-27-42.json
-a---            6/8/2023  2:28 PM          25530 VMware_vSphere_8.0_STIG_vCenter_Remediation_Transcript_6-8-2023_14-27-42.txt

Remediating vCenter (Appliance Controls)

To remediate vCenter we have provided an Ansible playbook that will target a single vCenter server appliance over SSH and configure any non-compliant controls.

Update the default shell for root

The default shell for root must be changed to /bin/bash before running. The appliance shell causes issues with some controls running.

# SSH to vCenter
Connected to service

    * List APIs: "help api list"
    * List Plugins: "help pi list"
    * Launch BASH: "shell"

Command> shell.set --enabled true
Command> shell
Shell access is granted to root
root@sc1-10-182-131-166 [ ~ ]# chsh -s /bin/bash root

Running the playbook

To run all of the VCSA controls, follow the example below:

# Navigate to the Ansible playbook folder
cd /usr/share/stigs/vsphere/8.0/v1r1-stig/vcsa/ansible/vmware-vcsa-8.0-stig-ansible-hardening

# The -k parameter will prompt for password and we are using extra-vars to specify a variable file for the playbook to use.
ansible-playbook -i 10.182.177.21, -u root playbook.yml -k -v --extra-vars @vars-vcenter-example.yml

# Output example
SSH password:

PLAY [all] ********************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] ********************************************************************************************************************************************************************************************************
ok: [10.182.177.21]

TASK [vmware-photon-3.0-stig-ansible-hardening : Include Photon] **************************************************************************************************************************************************************
included: /home/rlakey/.ansible/roles/vmware-photon-3.0-stig-ansible-hardening/tasks/photon.yml for 10.182.177.21

TASK [vmware-photon-3.0-stig-ansible-hardening : Create time stamp] ***********************************************************************************************************************************************************
ok: [10.182.177.21] => {"ansible_facts": {"backup_timestamp": "2023-05-25-12-25-58"}, "changed": false}

TASK [vmware-photon-3.0-stig-ansible-hardening : Backup files...if restoring be sure to restore permissions that original file had!!] *****************************************************************************************
ok: [10.182.177.21] => (item=/etc/rsyslog.conf) => {"ansible_loop_var": "item", "changed": false, "checksum": "7aa11dc58f144160e7e3dc2d40cb2f03a39a989c", "dest": "/tmp/ansible-backups-2023-05-25-12-25-58/rsyslog.conf", "gid": 0, "group": "root", "item": "/etc/rsyslog.conf", "md5sum": "d31d58ff2bbc5cff6b7f343c2580300c", "mode": "0644", "owner": "root", "size": 4000, "src": "/etc/rsyslog.conf", "state": "file", "uid": 0}
ok: [10.182.177.21] => (item=/etc/issue) => {"ansible_loop_var": "item", "changed": false, "checksum": "930cb25fc842aca6047cb9fc1bfbd6ea191e686f", "dest": "/tmp/ansible-backups-2023-05-25-12-25-58/issue", "gid": 0, "group": "root", "item": "/etc/issue", "md5sum": "f498b74a84aaa39e292d9b815899144d", "mode": "0644", "owner": "root", "size": 104, "src": "/etc/issue", "state": "file", "uid": 0}
ok: [10.182.177.21] => (item=/etc/audit/rules.d/audit.STIG.rules) => {"ansible_loop_var": "item", "changed": false, "checksum": "38f324fe67c6943e07ef1910b41dedeb0b256ca4", "dest": "/tmp/ansible-backups-2023-05-25-12-25-58/audit.STIG.rules", "gid": 0, "group": "root", "item": "/etc/audit/rules.d/audit.STIG.rules", "md5sum": "396d715044fc7a8d92a0332d3edb4112", "mode": "0640", "owner": "root", "size": 5080, "src": "/etc/audit/rules.d/audit.STIG.rules", "state": "file", "uid": 0}

TASK [vmware-photon-3.0-stig-ansible-hardening : PHTN-30-000001 - Update/Create audit.STIG.rules file] ************************************************************************************************************************
changed: [10.182.177.21] => {"changed": true, "checksum": "aaafa4e8c28743ce3cc22c818f28f4cb9a3f53b2", "dest": "/etc/audit/rules.d/audit.STIG.rules", "gid": 0, "group": "root", "md5sum": "91a31e7bbf9e3f0d7f390feb4360581b", "mode": "0640", "owner": "root", "size": 5180, "src": "/root/.ansible/tmp/ansible-tmp-1685039234.3606877-890-106251101523760/source", "state": "file", "uid": 0}
# Navigate to the Ansible playbook folder
cd /usr/share/stigs/vsphere/8.0/v1r1-srg/vcsa/ansible/vmware-vcsa-8.0-stig-ansible-hardening

# The -k parameter will prompt for password and we are using extra-vars to specify a variable file for the playbook to use.
ansible-playbook -i 10.182.177.21, -u root playbook.yml -k -v --extra-vars @vars-vcenter-example.yml

# Output example
SSH password:

PLAY [all] ********************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] ********************************************************************************************************************************************************************************************************
ok: [10.182.177.21]

TASK [vmware-photon-3.0-stig-ansible-hardening : Include Photon] **************************************************************************************************************************************************************
included: /home/rlakey/.ansible/roles/vmware-photon-3.0-stig-ansible-hardening/tasks/photon.yml for 10.182.177.21

TASK [vmware-photon-3.0-stig-ansible-hardening : Create time stamp] ***********************************************************************************************************************************************************
ok: [10.182.177.21] => {"ansible_facts": {"backup_timestamp": "2023-05-25-12-25-58"}, "changed": false}

TASK [vmware-photon-3.0-stig-ansible-hardening : Backup files...if restoring be sure to restore permissions that original file had!!] *****************************************************************************************
ok: [10.182.177.21] => (item=/etc/rsyslog.conf) => {"ansible_loop_var": "item", "changed": false, "checksum": "7aa11dc58f144160e7e3dc2d40cb2f03a39a989c", "dest": "/tmp/ansible-backups-2023-05-25-12-25-58/rsyslog.conf", "gid": 0, "group": "root", "item": "/etc/rsyslog.conf", "md5sum": "d31d58ff2bbc5cff6b7f343c2580300c", "mode": "0644", "owner": "root", "size": 4000, "src": "/etc/rsyslog.conf", "state": "file", "uid": 0}
ok: [10.182.177.21] => (item=/etc/issue) => {"ansible_loop_var": "item", "changed": false, "checksum": "930cb25fc842aca6047cb9fc1bfbd6ea191e686f", "dest": "/tmp/ansible-backups-2023-05-25-12-25-58/issue", "gid": 0, "group": "root", "item": "/etc/issue", "md5sum": "f498b74a84aaa39e292d9b815899144d", "mode": "0644", "owner": "root", "size": 104, "src": "/etc/issue", "state": "file", "uid": 0}
ok: [10.182.177.21] => (item=/etc/audit/rules.d/audit.STIG.rules) => {"ansible_loop_var": "item", "changed": false, "checksum": "38f324fe67c6943e07ef1910b41dedeb0b256ca4", "dest": "/tmp/ansible-backups-2023-05-25-12-25-58/audit.STIG.rules", "gid": 0, "group": "root", "item": "/etc/audit/rules.d/audit.STIG.rules", "md5sum": "396d715044fc7a8d92a0332d3edb4112", "mode": "0640", "owner": "root", "size": 5080, "src": "/etc/audit/rules.d/audit.STIG.rules", "state": "file", "uid": 0}

TASK [vmware-photon-3.0-stig-ansible-hardening : PHTN-30-000001 - Update/Create audit.STIG.rules file] ************************************************************************************************************************
changed: [10.182.177.21] => {"changed": true, "checksum": "aaafa4e8c28743ce3cc22c818f28f4cb9a3f53b2", "dest": "/etc/audit/rules.d/audit.STIG.rules", "gid": 0, "group": "root", "md5sum": "91a31e7bbf9e3f0d7f390feb4360581b", "mode": "0640", "owner": "root", "size": 5180, "src": "/root/.ansible/tmp/ansible-tmp-1685039234.3606877-890-106251101523760/source", "state": "file", "uid": 0}

A more conservative and preferred approach is to target any non-compliant controls or run each component separately allowed you to perform any functional testing in between.

# Providing the tag "eam" will instruct the playbook to only run the eam role. This tag can be seen in each roles task/main.yml file.
ansible-playbook -i 10.182.177.21, -u root playbook.yml -k -v --extra-vars @vars-vcenter-example.yml --tags eam

# Providing the tag "VCEM-70-000001" will instruct the playbook to only run task tagged with the STIG ID of VCEM-80-000001.
ansible-playbook -i 10.182.177.21, -u root playbook.yml -k -v --extra-vars @vars-vcenter-example.yml --tags VCEM-80-000001
# Providing the tag "eam" will instruct the playbook to only run the eam role. This tag can be seen in each roles task/main.yml file.
ansible-playbook -i 10.182.177.21, -u root playbook.yml -k -v --extra-vars @vars-vcenter-example.yml --tags eam

# Providing the tag "VCEM-70-000001" will instruct the playbook to only run task tagged with the STIG ID of VCEM-80-000001.
ansible-playbook -i 10.182.177.21, -u root playbook.yml -k -v --extra-vars @vars-vcenter-example.yml --tags VCEM-80-000001

4.2.3 - Audit vSphere 7

Auditing vSphere 7 for STIG Compliance

Overview

Auditing vSphere for STIG compliance involves scanning ESXi, Virtual Machines, vCenter, and the vCenter appliance.

When auditing vSphere we will split up tasks between product and appliance based controls which are defined as follows:

  • Product Control: Configurations that interact with the Product via the User Interface or API that are exposed to administrators. Whether these are Default or Non-Default, the risk of mis-configuration effecting availability of the product is low but could impact how the environment is operated if not assessed.
  • Appliance Control: Appliance controls deal with the underlying components (databases, web servers, Photon OS, etc) that make up the product. Altering these add risk to product availability if precautionary steps and care in implementation are not taken. Identifying and relying on Default settings in this category makes this category less risky (Default Appliance Controls should be seen as a positive).

To audit vSphere using InSpec we utilize the VMware transport(train-vmware) which connects to vCenter via PowerCLI and performs queries. For the vCenter appliance the auditing is performed via SSH. It is recommended to disable SSH on vCenter after the auditing is complete.

Prerequisites

Versions listed below were used for this documentation. Other versions of these tools may work as well but if issues are found it is recommended to try the versions listed here.

Install the custom VMware transport for InSpec

To extend the functionality of the VMware transport that ships with InSpec we have created a custom one that also incorporates the VMware.Vsphere.SsoAdmin module to extend automation coverage to the vCenter SSO STIG controls.

To install the plugin that is included with the vmware-vsphere-7.0-stig-baseline profile, do the following:

# Install the custom train-vmware plugin. Update the path to the gem as needed. The command will be the same on Windows and Linux.
> inspec plugin install C:\vmware-vsphere-7.0-stig-baseline\train-vmware-0.2.0.gem

# To verify the installation
> inspec plugin list

┌────────────────────────────────────────┬─────────┬──────────────┬─────────┬───────────────────────────────────────────────────────────────┐
              Plugin Name                Version      Via       ApiVer                            Description                          
├────────────────────────────────────────┼─────────┼──────────────┼─────────┼───────────────────────────────────────────────────────────────┤
 inspec-compliance                       5.22.3   core          2        Plugin to perform operations with Chef Automate               
 inspec-habitat                          5.22.3   core          2        Plugin to create/upload habitat package                       
 inspec-init                             5.22.3   core          2        Plugin for scaffolding profile, plugin or a resource          
 inspec-plugin-manager-cli               5.22.3   core          2        CLI plugin for InSpec                                         
 inspec-reporter-html2                   5.22.3   core          2        Improved HTML reporter plugin                                 
 inspec-reporter-json-min                5.22.3   core          2        Json-min json reporter plugin                                 
 inspec-reporter-junit                   5.22.3   core          2        JUnit XML reporter plugin                                     
 inspec-sign                             5.22.3   core          2                                                                      
 inspec-streaming-reporter-progress-bar  5.22.3   core          2        Displays a real-time progress bar and control title as output 
 inspec-supermarket                      5.22.3   core          0                                                                      
 train-aws                               0.2.24   gem (system)  train-1  AWS API Transport for Train                                   
 train-habitat                           0.2.22   gem (system)  train-1  Habitat API Transport for Train                               
 train-kubernetes                        0.1.12   gem (system)  train-1  Train Kubernetes                                              
 train-vmware                            0.2.0    gem (user)    train-1  Train Plugin for VMware PowerCLI                              
 train-winrm                             0.2.13   gem (system)  train-1  Windows WinRM API Transport for Train                         
└────────────────────────────────────────┴─────────┴──────────────┴─────────┴───────────────────────────────────────────────────────────────┘
 15 plugin(s) total

Auditing ESXi Hosts

Update profile inputs

Included in the vmware-vsphere-7.0-stig-baseline is an example inputs-example.yml file with the following inputs relevant to ESXi.

Update the inputs as shown below with values relevant to your environment.

# Choose whether to scan a single host, all hosts in a cluster, or all hosts in vCenter.
vmhostName: ""
cluster: ""
allesxi: true
# Enter an array of users that should be in the lockdown mode exceptions list.
exceptionUsers: []
# Enter the environment specific syslog server ESXi should be forwarding logs to.
syslogServer: "tcp://log.test.local:514"
# If ESXi is joined to AD, enter the AD group that has administrative access to ESXi.
adAdminGroup: "MyAdAdminGroup"
# Enter the environment specific time servers.
esxiNtpServers:
  - 'time-a-g.nist.gov'
  - 'time-b-g.nist.gov'
# Enter the environment specific vMotion VLAN Id.
vMotionVlanId: "100"
# Enter the environment specific Management VLAN Id.
mgtVlanId: "101"
# If snmp is used in the environment change to true.
snmpEnabled: "false"
# Enter the latest build number for ESXi.
esxiBuildNumber: "21424296"

Setup environment variables for vCenter connection

Connectivity to vCenter is established via environment variables. Take care to clear your history and close the Powershell session to avoid any credentials left in memory/history.

# Note: VISERVER is referencing vCenter and not an ESXi host.
> $env:VISERVER='10.186.30.81'
> $env:VISERVER_USERNAME='Administrator@vsphere.local'
> $env:VISERVER_PASSWORD='password'

Note: If your password has a single ’ in it you must substitute it with ’’’’ for it to be properly escaped all the way through the process.

Run the audit

In this example we will be scanning all ESXi hosts attached to the target vCenter, specifying an inputs file, enabling enhanced outcomes in InSpec, and outputting a report to the CLI and to a JSON file.

# Note this command is being ran from the root of the profile folder. Update paths as needed if running from a different location.
> inspec exec .\esxi\ -t vmware:// --show-progress --input-file .\inputs-example.yml --enhanced-outcomes --reporter=cli json:C:\InSpec\Reports\MyESXiReport.json

# Shown below is the last part of the output at the CLI.
  [FAIL]  ESXI-70-000097: The ESXi Common Information Model (CIM) service must be disabled. (2 failed)
     [FAIL]  PowerCLI Command: Get-VMHost -Name 10.182.131.186 | Get-VMHostService | Where {$_.Label -eq 'CIM Server'} | Select-Object -ExpandProperty Policy stdout.strip is expected to cmp == "off"

     expected: off
          got: on

     (compared using `cmp` matcher)

     [PASS]  PowerCLI Command: Get-VMHost -Name 10.182.131.186 | Get-VMHostService | Where {$_.Label -eq 'CIM Server'} | Select-Object -ExpandProperty Running stdout.strip is expected to cmp == "false"
     [FAIL]  PowerCLI Command: Get-VMHost -Name 10.182.132.6 | Get-VMHostService | Where {$_.Label -eq 'CIM Server'} | Select-Object -ExpandProperty Policy stdout.strip is expected to cmp == "off"

     expected: off
          got: on

     (compared using `cmp` matcher)

     [PASS]  PowerCLI Command: Get-VMHost -Name 10.182.132.6 | Get-VMHostService | Where {$_.Label -eq 'CIM Server'} | Select-Object -ExpandProperty Running stdout.strip is expected to cmp == "false"
     [PASS]  PowerCLI Command: Get-VMHost -Name 10.182.138.1 | Get-VMHostService | Where {$_.Label -eq 'CIM Server'} | Select-Object -ExpandProperty Policy stdout.strip is expected to cmp == "off"
     [PASS]  PowerCLI Command: Get-VMHost -Name 10.182.138.1 | Get-VMHostService | Where {$_.Label -eq 'CIM Server'} | Select-Object -ExpandProperty Running stdout.strip is expected to cmp == "false"
  [N/R]  ESXI-70-000274: The ESXi host SSH daemon must be configured to only use FIPS 140-2 validated ciphers.
     [SKIP]  This must be reviewed manually

Profile Summary: 25 successful controls, 27 control failures, 20 controls not reviewed, 3 controls not applicable, 0 controls have error
Test Summary: 143 successful, 120 failures, 34 skipped

Auditing Virtual Machines

Update profile inputs

Included in the vmware-vsphere-7.0-stig-baseline is an example inputs-example.yml file with the following inputs relevant to VMs.

Update the inputs as shown below with values relevant to your environment.

# Choose whether to scan a single VM or all VMs in vCenter.
vmName: ""
allvms: true

Setup environment variables for vCenter connection

Connectivity to vCenter is established via environment variables. Take care to clear your history and close the Powershell session to avoid any credentials left in memory/history.

If was done in the previous step it is not necessary to do again.

# Note: VISERVER is referencing vCenter and not an ESXi host.
> $env:VISERVER='10.186.30.81'
> $env:VISERVER_USERNAME='Administrator@vsphere.local'
> $env:VISERVER_PASSWORD='password'

Note: If your password has a single ’ in it you must substitute it with ’’’’ for it to be properly escaped all the way through the process.

Run the audit

In this example we will be scanning all VMs in the target vCenter, specifying an inputs file, enabling enhanced outcomes in InSpec, and outputting a report to the CLI and to a JSON file.

# Note this command is being ran from the root of the profile folder. Update paths as needed if running from a different location.
> inspec exec .\vm\ -t vmware:// --show-progress --input-file .\inputs-example.yml --enhanced-outcomes --reporter=cli json:C:\InSpec\Reports\MyVMsReport.json

# Shown below is the last part of the output at the CLI.
  [FAIL]  VMCH-70-000027: Log retention must be configured properly on the virtual machine (VM). (2 failed)
     [FAIL]  PowerCLI Command: Get-VM -Name 'stig space test' | Get-AdvancedSetting -Name log.keepOld | Select-Object -ExpandProperty Value stdout.strip is expected to cmp == "10"

     expected: 10
          got:

     (compared using `cmp` matcher)

     [FAIL]  PowerCLI Command: Get-VM -Name 'stigvmtest1' | Get-AdvancedSetting -Name log.keepOld | Select-Object -ExpandProperty Value stdout.strip is expected to cmp == "10"

     expected: 10
          got:

     (compared using `cmp` matcher)

     [PASS]  PowerCLI Command: Get-VM -Name 'vCLS-189ef61c-56dc-4d5f-a255-ac43798a77b3' | Get-AdvancedSetting -Name log.keepOld | Select-Object -ExpandProperty Value stdout.strip is expected to cmp == "10"
     [PASS]  PowerCLI Command: Get-VM -Name 'vCLS-6e74013e-53a1-4589-a2f7-47f11674d089' | Get-AdvancedSetting -Name log.keepOld | Select-Object -ExpandProperty Value stdout.strip is expected to cmp == "10"
     [PASS]  PowerCLI Command: Get-VM -Name 'vCLS-d7018f26-8dab-48c7-8161-56311f5eb077' | Get-AdvancedSetting -Name log.keepOld | Select-Object -ExpandProperty Value stdout.strip is expected to cmp == "10"
  [PASS]  VMCH-70-000028: DirectPath I/O must be disabled on the virtual machine (VM) when not required.
     [PASS]  PowerCLI Command: Get-VM -Name 'stig space test' | Get-AdvancedSetting -Name pciPassthru*.present | Select-Object -ExpandProperty Value stdout.strip is expected to be empty
     [PASS]  PowerCLI Command: Get-VM -Name 'stigvmtest1' | Get-AdvancedSetting -Name pciPassthru*.present | Select-Object -ExpandProperty Value stdout.strip is expected to be empty
     [PASS]  PowerCLI Command: Get-VM -Name 'vCLS-189ef61c-56dc-4d5f-a255-ac43798a77b3' | Get-AdvancedSetting -Name pciPassthru*.present | Select-Object -ExpandProperty Value stdout.strip is expected to be empty
     [PASS]  PowerCLI Command: Get-VM -Name 'vCLS-6e74013e-53a1-4589-a2f7-47f11674d089' | Get-AdvancedSetting -Name pciPassthru*.present | Select-Object -ExpandProperty Value stdout.strip is expected to be empty
     [PASS]  PowerCLI Command: Get-VM -Name 'vCLS-d7018f26-8dab-48c7-8161-56311f5eb077' | Get-AdvancedSetting -Name pciPassthru*.present | Select-Object -ExpandProperty Value stdout.strip is expected to be empty
  [PASS]  VMCH-70-000029: Encryption must be enabled for Fault Tolerance on the virtual machine (VM).
     [PASS]  PowerCLI Command: (Get-VM -Name 'stig space test').ExtensionData.Config.FtEncryptionMode stdout.strip is expected to be in "ftEncryptionOpportunistic" and "ftEncryptionRequired"
     [PASS]  PowerCLI Command: (Get-VM -Name 'stigvmtest1').ExtensionData.Config.FtEncryptionMode stdout.strip is expected to be in "ftEncryptionOpportunistic" and "ftEncryptionRequired"
     [PASS]  PowerCLI Command: (Get-VM -Name 'vCLS-189ef61c-56dc-4d5f-a255-ac43798a77b3').ExtensionData.Config.FtEncryptionMode stdout.strip is expected to be in "ftEncryptionOpportunistic" and "ftEncryptionRequired"
     [PASS]  PowerCLI Command: (Get-VM -Name 'vCLS-6e74013e-53a1-4589-a2f7-47f11674d089').ExtensionData.Config.FtEncryptionMode stdout.strip is expected to be in "ftEncryptionOpportunistic" and "ftEncryptionRequired"
     [PASS]  PowerCLI Command: (Get-VM -Name 'vCLS-d7018f26-8dab-48c7-8161-56311f5eb077').ExtensionData.Config.FtEncryptionMode stdout.strip is expected to be in "ftEncryptionOpportunistic" and "ftEncryptionRequired"

Profile Summary: 11 successful controls, 15 control failures, 2 controls not reviewed, 0 controls not applicable, 0 controls have error
Test Summary: 75 successful, 55 failures, 2 skipped

Auditing vCenter (Product Controls)

Update profile inputs

Included in the vmware-vsphere-7.0-stig-baseline is an example inputs-example.yml file with the following inputs relevant to vCenter.

Update the inputs as shown below with values relevant to your environment.

# Enter the environment specific syslog server vCenter should be forwarding logs to.
syslogServers:
  - "loginsight.test.com"
  - "syslog.server2.com"
# Enter the environment specific time servers.
ntpServers:
  - 'time-a-g.nist.gov'
  - 'time-b-g.nist.gov'
# If an IPfix collector is used enter the IP.
ipfixCollectorAddress: ""
# Enter any approved users in the bash shell administrators users group
bashShellAdminUsers:
  - 'Administrator'
# Enter any approved group in the bash shell administrators group
bashShellAdminGroups: []
# Enter any approved users in the trusted admin users group
trustedAdminUsers: []
# Enter any approved users in the trusted admin group
trustedAdminGroups: []
# Set to false if file based backups are used via the VAMI
backup3rdParty: false

Setup environment variables for vCenter connection

Connectivity to vCenter is established via environment variables. Take care to clear your history and close the Powershell session to avoid any credentials left in memory/history.

If was done in the previous step it is not necessary to do again.

# Note: VISERVER is referencing vCenter and not an ESXi host.
> $env:VISERVER='10.186.30.81'
> $env:VISERVER_USERNAME='Administrator@vsphere.local'
> $env:VISERVER_PASSWORD='password'

Note: If your password has a single ’ in it you must substitute it with ’’’’ for it to be properly escaped all the way through the process.

Run the audit

In this example we will be scanning vCenter controls in the target vCenter, specifying an inputs file, enabling enhanced outcomes in InSpec, and outputting a report to the CLI and to a JSON file.

# Note this command is being ran from the root of the profile folder. Update paths as needed if running from a different location.
> inspec exec .\vcenter\ -t vmware:// --show-progress --input-file .\inputs-example.yml --enhanced-outcomes --reporter=cli json:C:\InSpec\Reports\MyvCenterReport.json

# Shown below is the last part of the output at the CLI.
  [PASS]  VCSA-70-000291: The vCenter Server must limit membership to the "TrustedAdmins" Single Sign-On (SSO) group.
     [PASS]  Stderr should be empty if no users found is expected to be empty
     [PASS]  No users found in TrustedAdmins is expected to be empty
     [PASS]  Stderr should be empty if no groups found is expected to be empty
     [PASS]  No groups found in TrustedAdmins is expected to be empty
  [FAIL]  VCSA-70-000292: The vCenter server configuration must be backed up on a regular basis.
     [FAIL]  File based backups should be enabled. is expected to cmp == "true"

     expected: true
          got:

     (compared using `cmp` matcher)

  [PASS]  VCSA-70-000293: vCenter task and event retention must be set to at least 30 days.
     [PASS]  PowerCLI Command: Get-AdvancedSetting -Entity $global:DefaultViServers.Name -Name event.maxAge | Select-Object -ExpandProperty Value stdout.strip is expected to cmp == "30"
     [PASS]  PowerCLI Command: Get-AdvancedSetting -Entity $global:DefaultViServers.Name -Name task.maxAge | Select-Object -ExpandProperty Value stdout.strip is expected to cmp == "30"
  [N/R]  VCSA-70-000294: vCenter Native Key Providers must be backed up with a strong password.
     [SKIP]  This must be reviewed manually

Profile Summary: 19 successful controls, 16 control failures, 22 controls not reviewed, 0 controls not applicable, 0 controls have error
Test Summary: 52 successful, 19 failures, 22 skipped

Run a combined scan for all vSphere product controls

Instead of running each STIG for product controls separately you can also run all of the vCenter, ESXi, and VM controls for a combined report.

# Note this command is being ran from the root of the profile folder. Update paths as needed if running from a different location.
> inspec exec . -t vmware:// --show-progress --input-file .\inputs-example.yml --reporter=cli json:C:\InSpec\Reports\MyvSphereReport.json

Using the InSpec runner script

For accredidation purposes there may be a requirement to produce a CKL file for each ESXi host and/or VM.

We have also created a PowerCLI script that acts as a runner for InSpec to loop through a list of hosts or VMs and then produce a json report for each and if the SAF CLI is installed also create a CKL file.

Currently we have an example for doing this with ESXi hosts available here.

With this script you can also provide an attestation file that will be applied to the results and incorporated into the CKL file.

To use the runner script, do the following:

# If not done already provide the credentials for InSpec to connect to vCenter.
# Note: VISERVER is referencing vCenter and not an ESXi host.
> $env:VISERVER='10.186.30.81'
> $env:VISERVER_USERNAME='Administrator@vsphere.local'
> $env:VISERVER_PASSWORD='password'
# Note: If your password has a single ' in it you must substitute it with '''' for it to be properly escaped all the way through the process.
# Adjust the paths in the command as needed. The inspec and inputs paths in the example are assuming this is being ran from the root of the InSpec profile folder.
> C:\github\VMware_vSphere_7.0_STIG_ESXi_InSpec_Runner.ps1 -vcenter 10.182.131.166 -reportPath C:\Inspec\Reports\Runner -inspecPath .\esxi\ -inputsfile .\inputs-example.yml

# You will be prompted for credentials to vCenter. This is to connect via PowerCLI before running InSpec to collect all of the host names to use as an input to InSpec for each individual host audit.
8:48:29 AM ...Enter credentials to connect to vCenter

PowerShell credential request
Enter credentials for vCenter
User: administrator@vsphere.local
Password for user administrator@vsphere.local: ****************

8:48:44 AM ...Connecting to vCenter Server 10.182.131.166
8:48:47 AM ...Getting PowerCLI objects for all ESXi hosts in vCenter: 10.182.131.166
8:48:48 AM ...Validated path for report at C:\Inspec\Reports\Runner
8:48:48 AM ...Report path is C:\Inspec\Reports\Runner and report file is C:\Inspec\Reports\Runner\VMware_vSphere_7.0_STIG_ESXi_Inspec_Report_10.182.131.186-5-19-2023_8-48-29.json
8:48:48 AM ...Running InSpec exec against 10.182.131.186 with inspec exec $inspecPath -t vmware:// --input vmhostName=$name --input-file $inputsFile --show-progress --reporter=json:$reportFile
FFF......FFFFF....FFFF.FFFF.*...***********...FF.FF.....F.F..FFFF..FFF***FFFF.FFF.FF.FF....FFFFFF..F...***FF*FF*FF**...***...FFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFFFFFF.FFFFF...................FF....FF...............................*......*FFF......*......F..FF..F....FF.***FF....FF....FF.**FFFFFFF.F...*
8:51:49 AM ...Detected saf cli...generating STIG Viewer Checklist for 10.182.131.186
8:51:53 AM ...Report path is C:\Inspec\Reports\Runner and report file is C:\Inspec\Reports\Runner\VMware_vSphere_7.0_STIG_ESXi_Inspec_Report_10.182.132.6-5-19-2023_8-48-29.json
8:51:53 AM ...Running InSpec exec against 10.182.132.6 with inspec exec $inspecPath -t vmware:// --input vmhostName=$name --input-file $inputsFile --show-progress --reporter=json:$reportFile
FFF......FFFFF....FFFF.FFFF.*...***********...FF.FF.....F.F..FFFF..FFF***FFFF.FFF.FF.FF....FFFFFF..F...***FF*FF*FF**...***...FFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFFFFFF.FFFFF...................FF....FF...............................*......*FFF......*......F..FF..F....FF.***FF....FF....FF.**FFFFFFF.F...*
8:54:54 AM ...Detected saf cli...generating STIG Viewer Checklist for 10.182.132.6
8:54:59 AM ...Report path is C:\Inspec\Reports\Runner and report file is C:\Inspec\Reports\Runner\VMware_vSphere_7.0_STIG_ESXi_Inspec_Report_10.182.138.1-5-19-2023_8-48-29.json
8:54:59 AM ...Running InSpec exec against 10.182.138.1 with inspec exec $inspecPath -t vmware:// --input vmhostName=$name --input-file $inputsFile --show-progress --reporter=json:$reportFile
FFF......FFFFF....FFFF.FFFF.*...***********...FF.FF.....F.F..FFFF..FFF***FFFF.FFF.FF.FF....FFFFFF..F...***FF*FF*FF**...***...FFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFFFFFF.FFFFF...................FF....FF...............................*......*FFF......*......F..FF..F....FF.***FF....FF....FF.**FFFFFFF.F...*
8:57:50 AM ...Detected saf cli...generating STIG Viewer Checklist for 10.182.138.1
8:57:54 AM ...Disconnecting from vCenter

# Resulting output
> dir C:\inspec\Reports\Runner\

    Directory: C:\Inspec\Reports\Runner

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---           5/19/2023  8:51 AM         507413 VMware_vSphere_7.0_STIG_ESXi_Inspec_Report_10.182.131.186-5-19-2023_8-48-29.ckl
-a---           5/19/2023  8:51 AM         580793 VMware_vSphere_7.0_STIG_ESXi_Inspec_Report_10.182.131.186-5-19-2023_8-48-29.json
-a---           5/19/2023  8:54 AM         507403 VMware_vSphere_7.0_STIG_ESXi_Inspec_Report_10.182.132.6-5-19-2023_8-48-29.ckl
-a---           5/19/2023  8:54 AM         580816 VMware_vSphere_7.0_STIG_ESXi_Inspec_Report_10.182.132.6-5-19-2023_8-48-29.json
-a---           5/19/2023  8:57 AM         507403 VMware_vSphere_7.0_STIG_ESXi_Inspec_Report_10.182.138.1-5-19-2023_8-48-29.ckl
-a---           5/19/2023  8:57 AM         580787 VMware_vSphere_7.0_STIG_ESXi_Inspec_Report_10.182.138.1-5-19-2023_8-48-29.json

Auditing vCenter (Appliance Controls)

Auditing the vCenter appliance is done over SSH which must be enabled for the scan.

Update the default shell for root

The default shell for root must be changed to /bin/bash before running. The appliance shell causes issues with some controls running.

# SSH to vCenter
Connected to service

    * List APIs: "help api list"
    * List Plugins: "help pi list"
    * Launch BASH: "shell"

Command> shell.set --enabled true
Command> shell
Shell access is granted to root
root@sc1-10-182-131-166 [ ~ ]# chsh -s /bin/bash root

Run the audit

In this example we will be scanning the vCenter appliance, specifying an inputs file, and outputting a report to the CLI and to a JSON file.

Updating the inputs file is not required for this profile but the inputs-vcsa-7.0.yml should be specified because it contains inputs for the Photon profile.

# Note this command is being ran from the root of the profile folder. Update paths as needed if running from a different location.
> inspec exec . -t ssh://root@10.182.131.166 --password 'password' --show-progress --input-file .\inputs-vcsa-7.0.yml --reporter=cli json:C:\InSpec\Reports\MyVCSAReport.json

# Shown below is the last part of the output at the CLI.
  [PASS]  VCUI-70-000028: vSphere UI must use a logging mechanism that is configured to allocate log record storage capacity large enough to accommodate the logging requirements of the web server.
     [PASS]  Command: `rpm -V vsphere-ui|grep serviceability.xml|grep "^..5......"` stdout.strip is expected to eq ""
  [PASS]  VCUI-70-000029: vSphere UI log files must be moved to a permanent repository in accordance with site policy.
     [PASS]  Command: `rpm -V VMware-visl-integration|grep vmware-services-vsphere-ui.conf|grep "^..5......"` stdout.strip is expected to eq ""
  [PASS]  VCUI-70-000030: vSphere UI must be configured with the appropriate ports.
     [PASS]  5090 is expected to eq "5090"
     [PASS]  443 is expected to eq "443"
  [PASS]  VCUI-70-000031: vSphere UI must disable the shutdown port.
     [PASS]  XML /usr/lib/vmware-vsphere-ui/server/conf/server.xml ["/Server/@port"] is expected to cmp == "${shutdown.port}"
     [PASS]  JSON /etc/vmware/vmware-vmon/svcCfgfiles/vsphere-ui.json StartCommandArgs is expected to include "-Dshutdown.port=-1"
  [PASS]  VCUI-70-000032: vSphere UI must set the secure flag for cookies.
     [PASS]  XML /usr/lib/vmware-vsphere-ui/server/conf/web.xml /web-app/session-config/cookie-config/secure is expected to cmp == "true"
  [PASS]  VCUI-70-000033: The vSphere UI default servlet must be set to "readonly".
     [PASS]  XML /usr/lib/vmware-vsphere-ui/server/conf/web.xml /web-app/servlet[servlet-name="default"]/init-param[param-name="readonly"]/param-value is expected to eq []


Profile Summary: 313 successful controls, 17 control failures, 0 controls skipped
Test Summary: 1516 successful, 106 failures, 0 skipped

Convert the results to CKL

If a STIG Viewer CKL file is needed then the results from the scans can be converted to CKL with the SAF CLI.

# Converting the VCSA scan results from the prior section to CKL
saf convert hdf2ckl -i C:\inspec\Reports\MyVCSAReport.json -o C:\inspec\Reports\MyVCSAReport.ckl --hostname 10.182.131.166 --fqdn myvcenter.local --ip 10.182.131.166 --mac 00:00:00:00:00:00

Opening the CKL file in STIG Viewer will look like the screenshot below. Note the InSpec results are included in the Finding Details pane.

alt text

4.2.4 - Remediate vSphere 7

Remediating vSphere 7 for STIG Compliance

Overview

Remediating vSphere for STIG compliance involves configuring ESXi, Virtual Machines, vCenter, and the vCenter appliance.

When remediating vSphere we will split up tasks between product and appliance based controls which are defined as follows:

  • Product Control: Configurations that interact with the Product via the User Interface or API that are exposed to administrators. Whether these are Default or Non-Default, the risk of mis-configuration effecting availability of the product is low but could impact how the environment is operated if not assessed.
  • Appliance Control: Appliance controls deal with the underlying components (databases, web servers, Photon OS, etc) that make up the product. Altering these add risk to product availability without precautionary steps and care in implementation. Identifying and relying on Default settings in this category makes this category less risky (Default Appliance Controls should be seen as a positive).

To remediate vSphere, PowerCLI is the automation tool used, while for the VCSA we will use Ansible. For the vCenter appliance the remediation is performed via SSH. It is recommended to disable SSH on vCenter after configuration is complete.

Prerequisites

Versions listed below were used for this documentation. Other versions of these tools may work as well but if issues are found it is recommended to try the versions listed here.

Create Powershell credential for vCenter connection

The PowerCLI scripts provided use a Powershell Credential stored in a varialbe to authenticate to vCenter and should be established before attempting to run the scripts.

# Run the following command to generate a credential. Substitute the username as needed in your environment. Note if ran in Powershell 5.x on Windows this will popup a window to enter the credentials.
$vccred = Get-Credential

PowerShell credential request
Enter your credentials.
User: administrator@vsphere.local
Password for user administrator@vsphere.local: ****************

Remediating ESXi product controls

To remediate ESXi hosts we have provided a PowerCLI script that will target a single host or a vSphere cluster based on parameters provided to the script.

Note: There are some controls that cannot be remediated with PowerCLI and are not addressed by this script. The output will indicate that these are manual controls.

Gather environment information

In order to run the script effectively it must be provided with the organizations environment specific information.

Review the below parameters and gather the information needed to run the script:

[CmdletBinding()]
param (
  [Parameter(Mandatory = $true)]
  [string]$vcenter,
  [Parameter(Mandatory = $true)]
  [pscredential]$vccred,
  [Parameter(Mandatory = $true, ParameterSetName = "hostname")]
  [string]$hostname,
  [Parameter(Mandatory = $true, ParameterSetName = "cluster")]
  [string]$cluster,
  [Parameter(Mandatory = $false,
    HelpMessage = "Enter the path for the output report. Example /tmp")]
  [string]$reportpath,    
  [Parameter(Mandatory = $true,
    HelpMessage = "Enter the Active Directory Admins group to use for administrative access to ESXi")]
  [string]$esxAdminGroup,
  [Parameter(Mandatory = $true,
    HelpMessage = "Enter allowed IP ranges for the ESXi firewall in comma separated format.  For Example `"192.168.0.0/16`",`"10.0.0.0/8`" ")]
  [string[]]$allowedIPs,
  [Parameter(Mandatory = $false,
    HelpMessage = "Enter the syslog server for the ESXi server(s). Example tcp://log.domain.local:514")]
  [string]$syslogServer,
  [Parameter(Mandatory = $false,
    HelpMessage = "Enable this option if VMware vRealize Log Insight is used to manage syslog on the ESXi host(s).")]
  [switch]$logInsight,
  [Parameter(Mandatory = $true,
    HelpMessage = "Enter NTP servers.  For Example `"10.1.1.1`",`"10.1.1.2`" ")]
  [string[]]$ntpServers,
  [Parameter(Mandatory = $false,
    HelpMessage = "Specify the native VLAN Id configured on the ports going to the ESXi Hosts.  If none is specified the default of 1 will be used.")]
  [string]$nativeVLAN = "1"
)

Disabling Controls

The script includes varialbes to enable or disable controls by STIG ID. All controls are all enabled by default and can be turned off by changing these variables to $false for a specific control.

A snippet of these variables is shown below.

##### Enable or Disable specific STIG Remediations #####
$controlsenabled = [ordered]@{
  ESXI70000001 = $true  #Lockdown Mode
  ESXI70000002 = $true  #DCUI.Access List
  ESXI70000003 = $true  #Lockdown Mode Exceptions
  ESXI70000004 = $true  #Syslog

Run remediation script on target ESXi hosts

This example will remediate all hosts in the vSphere cluster named cluster0. If running on a single host is desired, specify the hostname parameter instead of cluster and provide the hostname as displayed in vCenter.

# Running the script.
> .\VMware_vSphere_7.0_STIG_ESXi_Remediation.ps1 -vcenter 10.182.131.166 -vccred $vccred -cluster "cluster0" -esxAdminGroup "MyESXiGroup" -allowedIPs "10.0.0.0/8" -ntpServers "time-a-g.nist.gov","time-b-g.nist.gov" -syslogServer "tcp://loginsight.vmware.com:514" -reportpath C:\Temp

# Snippet from the output of running the script.
Transcript started, output file is C:\Temp\VMware_vSphere_7.0_STIG_ESXi_Remediation_Transcript_5-25-2023_9-26-8.txt
9:26:09 AM ...Core detected...checking for VMware.PowerCLI
9:26:09 AM ...Trying to import module VMware.PowerCLI
9:27:13 AM ...Connecting to vCenter 10.182.131.166
9:27:16 AM ...Gathering info on target hosts in 10.182.131.166
9:27:19 AM ...Found host 10.182.131.186
9:27:19 AM ...Found host 10.182.132.6
9:27:19 AM ...Found host 10.182.138.1
9:27:19 AM ...Remediating STIG ID:ESXI-70-000002 with Title: The ESXi host must verify the DCUI.Access list.
9:27:20 AM ...Setting DCUI.Access is already configured correctly to root on 10.182.131.186
9:27:20 AM ...Setting DCUI.Access is already configured correctly to root on 10.182.132.6
9:27:20 AM ...Setting DCUI.Access is already configured correctly to root on 10.182.138.1
9:27:20 AM ...Remediating STIG ID:ESXI-70-000003 with Title: The ESXi host must verify the exception users list for lockdown mode.
9:27:20 AM ...No exception users found on 10.182.131.186
9:27:20 AM ...No exception users found on 10.182.132.6
9:27:21 AM ...No exception users found on 10.182.138.1
9:27:21 AM ...Remediating STIG ID:ESXI-70-000004 with Title: Remote logging for ESXi hosts must be configured.
9:27:21 AM ...Setting Syslog.global.logHost was incorrectly set to  on 10.182.131.186...setting to tcp://loginsight.vmware.com:514

Name                 Value                Type                 Description
----                 -----                ----                 -----------
Syslog.global.logHo tcp://loginsight.vm VMHost
9:27:25 AM ...Setting Syslog.global.logHost was incorrectly set to  on 10.182.132.6...setting to tcp://loginsight.vmware.com:514
Syslog.global.logHo tcp://loginsight.vm VMHost
9:27:28 AM ...Setting Syslog.global.logHost was incorrectly set to  on 10.182.138.1...setting to tcp://loginsight.vmware.com:514
Syslog.global.logHo tcp://loginsight.vm VMHost

# A results file and Powershell transcript is provided in the report path specified.
Directory: C:\Temp

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---           5/25/2023  9:30 AM           6224 VMware_vSphere_7.0_STIG_ESXi_Remediation_Results_5-25-2023_9-26-8.json
-a---           5/25/2023  9:30 AM          89142 VMware_vSphere_7.0_STIG_ESXi_Remediation_Transcript_5-25-2023_9-26-8.txt

Remediating virtual machines product controls

To remediate virtual machines we have provided a PowerCLI script that will target a single VM, all VMs in a cluster, or all VMs in vCenter based on parameters provided to the script.

Note: There are some controls that cannot be remediated with PowerCLI and are not addressed by this script. See the scripts description text for more details.

Disabling Controls

For processing efficiency it is not constructed to run each control individually so the STIG ID variables are not included to enabled/disable controls such as in the ESXi/vCenter scripts. If it is desired to skip some controls they could be commented out in the $vmconfig variable in the script.

Run remediation script on target virtual machines

This example will remediate all hosts in the vSphere cluster named cluster0. If running on a single host is desired, specify the hostname parameter instead of cluster and provide the hostname as displayed in vCenter.

# Running the script.
> .\VMware_vSphere_7.0_STIG_VM_Remediation.ps1 -vcenter 10.182.131.166 -vccred $vccred -cluster "cluster0" -reportpath C:\Temp

# Snippet from the output of running the script.
Transcript started, output file is C:\Temp\VMware_vSphere_7.0_STIG_VM_Remediation_Transcript_5-25-2023_10-19-28.txt
10:19:28 AM ...Core detected...checking for VMware.PowerCLI
10:19:28 AM ...Connecting to vCenter Server 10.182.131.166
10:19:31 AM ...Getting PowerCLI objects for all virtual machines in cluster: cluster0
10:19:31 AM ...Remediating advanced settings on stig space test on 10.182.131.166
10:19:31 AM ...Setting isolation.device.connectable.disable does not exist on stig space test creating setting...

Name                 Value                Type                 Description
----                 -----                ----                 -----------
isolation.device.co True                 VM
10:19:34 AM ...Setting isolation.tools.copy.disable does not exist on stig space test creating setting...
isolation.tools.cop True                 VM
10:19:36 AM ...Setting isolation.tools.diskShrink.disable does not exist on stig space test creating setting...
isolation.tools.dis True                 VM

# A results file and Powershell transcript is provided in the report path specified.
Directory: C:\Temp

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---           5/25/2023 10:20 AM           1055 VMware_vSphere_7.0_STIG_VM_Remediation_Results_5-25-2023_10-19-28.json
-a---           5/25/2023 10:22 AM          13150 VMware_vSphere_7.0_STIG_VM_Remediation_Transcript_5-25-2023_10-19-28.txt

Remediating vCenter product controls

To remediate vCenter we have provided a PowerCLI script that will target a single vCenter server.

Note: There are some controls that cannot be remediated with PowerCLI and are not addressed by this script. The output will indicate that these are manual controls.

Gather environment information

In order to run the script effectively it must be provided with the organizations environment specific information.

This script also uses the VMware.Vsphere.SsoAdmin PowerCLI Module to configure vCenter SSO controls. This module connects to vCenter separately using the Connect-SsoAdminServer command that requires using an account that has sufficient privileges in vCenter to modify SSO settings.

Review the below parameters and gather the information needed to run the script:

[CmdletBinding()]
param (
  [Parameter(Mandatory=$true)]
  [string]$vcenter,
  [Parameter(Mandatory=$true)]
  [pscredential]$vccred,
  [Parameter(Mandatory=$false,
  HelpMessage="Enter the path for the output report. Example /tmp")]
  [string]$reportpath,
  [Parameter(Mandatory=$false,
  HelpMessage="If Netflow is used enter the collector IP address")]
  [string]$vcNetflowCollectorIp = "",
  [Parameter(Mandatory=$false,
  HelpMessage="To disable Netflow on all port groups if enabled set to true")]
  [boolean]$vcNetflowDisableonallPortGroups = $false
)

Disabling Controls

The script includes varialbes to enable or disable controls by STIG ID. All controls are all enabled by default and can be turned off by changing these variables to $false for a specific control.

A snippet of these variables is shown below.

##### Enable or Disable specific STIG Remediations #####
$controlsenabled = [ordered]@{
  VCSA7000009 = $true  #TLS 1.2
  VCSA7000023 = $true  #SSO Login Attempts
  VCSA7000024 = $true  #SSO Banner - Manual
  VCSA7000034 = $true  #config.log.level
  VCSA7000057 = $true  #Plugins - Manual

Run remediation script on target vCenter server

This example will remediate all controls on a target vCenter server.

# Running the script.
> .\VMware_vSphere_7.0_STIG_vCenter_Remediation.ps1 -vcenter 10.182.131.166 -vccred $vccred -reportpath C:\Temp

# Snippet from the output of running the script.
Transcript started, output file is C:\Temp\VMware_vSphere_7.0_STIG_ESXi_Remediation_Transcript_5-25-2023_11-30-58.txt
11:30:58 AM ...Core detected...checking for VMware.PowerCLI
11:30:58 AM ...Module VMware.PowerCLI is already imported.
11:30:58 AM ...Core detected...checking for VMware.Vsphere.SsoAdmin
11:30:58 AM ...Module VMware.Vsphere.SsoAdmin is already imported.
11:30:58 AM ...Connecting to vCenter Server 10.182.131.166
11:30:59 AM ...Connecting to vCenter SSO Server 10.182.131.166
11:31:00 AM ...Verifying vCenter 10.182.131.166 is version 7.0.x
11:31:00 AM ...vCenter 10.182.131.166 is version 7.0.3 continuing...
11:31:00 AM ...Getting PowerCLI objects for all virtual distributed switches in vCenter: 10.182.131.166
11:31:01 AM ...Getting PowerCLI objects for all virtual distributed port groups in vCenter: 10.182.131.166
11:31:02 AM ...Remediating STIG ID: VCSA-70-000009 with Title: The vCenter Server must use TLS 1.2, at a minimum, to protect the confidentiality of sensitive data during electronic dissemination using remote access.
11:31:02 AM ...!!This control must be remediated manually!!
11:31:02 AM ...Remediating STIG ID: VCSA-70-000023 with Title: The vCenter Server must enforce the limit of three consecutive invalid logon attempts by a user.
11:31:02 AM ...SSO login attempts set incorrectly on 10.182.131.166
11:31:03 AM ...Remediating STIG ID: VCSA-70-000024 with Title: The vCenter Server must display the Standard Mandatory DoD Notice and Consent Banner before logon.
11:31:03 AM ...!!This control must be remediated manually!!
11:31:03 AM ...Remediating STIG ID: VCSA-70-000034 with Title: The vCenter Server must produce audit records containing information to establish what type of events occurred.
11:31:03 AM ...Setting config.log.level is already configured correctly to info on 10.182.131.166

# A results file and Powershell transcript is provided in the report path specified.
Directory: C:\Temp

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---           5/25/2023 11:33 AM           2543 VMware_vSphere_7.0_STIG_vCenter_Remediation_Results_5-25-2023_11-33-25.json
-a---           5/25/2023 11:33 AM          18763 VMware_vSphere_7.0_STIG_vCenter_Remediation_Transcript_5-25-2023_11-33-25.txt

Remediating vCenter server appliance controls

To remediate vCenter we have provided an Ansible playbook that will target a single vCenter server appliance over SSH and configure any non-compliant controls.

Since Ansible can only be ran from Linux based systems, the examples below are being ran on an Ubuntu 22.04 WSL2 instance on Windows 11 for reference.

Backups

Before running it is highly advised to have a backup of the VCSA and/or snapshot available if a rollback is required. Also the playbook will backup files configured before updates and place them under the /tmp directory in a folder directly on the VCSA.

Update the default shell for root

The default shell for root must be changed to /bin/bash before running. The appliance shell causes issues with some controls running.

# SSH to vCenter
Connected to service

    * List APIs: "help api list"
    * List Plugins: "help pi list"
    * Launch BASH: "shell"

Command> shell.set --enabled true
Command> shell
Shell access is granted to root
root@sc1-10-182-131-166 [ ~ ]# chsh -s /bin/bash root

Ansible dependencies

The playbook is written to use the separate Photon 3.0 playbook we have avaiable and must be installed as a role prior to running.

Also there are two ansible collections that must be installed if on a version of Ansible newer than 2.9.

# Installing playbook requirements from the requirements.yml file provided.
ansible-galaxy roles install -r requirements.yml

Running the playbook

To run all of the VCSA controls, follow the example below.

# The -k parameter will prompt for password and we are using extra-vars to specify a variable file for the playbook to use.
> ansible-playbook -i 10.182.131.166, -u root playbook.yml -k -v --extra-vars @vars-vcenter-7.0U3eplus.yml

# Output example
SSH password:

PLAY [all] ********************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] ********************************************************************************************************************************************************************************************************
ok: [10.182.131.166]

TASK [vmware-photon-3.0-stig-ansible-hardening : Include Photon] **************************************************************************************************************************************************************
included: /home/rlakey/.ansible/roles/vmware-photon-3.0-stig-ansible-hardening/tasks/photon.yml for 10.182.131.166

TASK [vmware-photon-3.0-stig-ansible-hardening : Create time stamp] ***********************************************************************************************************************************************************
ok: [10.182.131.166] => {"ansible_facts": {"backup_timestamp": "2023-05-25-12-25-58"}, "changed": false}

TASK [vmware-photon-3.0-stig-ansible-hardening : Backup files...if restoring be sure to restore permissions that original file had!!] *****************************************************************************************
ok: [10.182.131.166] => (item=/etc/rsyslog.conf) => {"ansible_loop_var": "item", "changed": false, "checksum": "7aa11dc58f144160e7e3dc2d40cb2f03a39a989c", "dest": "/tmp/ansible-backups-2023-05-25-12-25-58/rsyslog.conf", "gid": 0, "group": "root", "item": "/etc/rsyslog.conf", "md5sum": "d31d58ff2bbc5cff6b7f343c2580300c", "mode": "0644", "owner": "root", "size": 4000, "src": "/etc/rsyslog.conf", "state": "file", "uid": 0}
ok: [10.182.131.166] => (item=/etc/issue) => {"ansible_loop_var": "item", "changed": false, "checksum": "930cb25fc842aca6047cb9fc1bfbd6ea191e686f", "dest": "/tmp/ansible-backups-2023-05-25-12-25-58/issue", "gid": 0, "group": "root", "item": "/etc/issue", "md5sum": "f498b74a84aaa39e292d9b815899144d", "mode": "0644", "owner": "root", "size": 104, "src": "/etc/issue", "state": "file", "uid": 0}
ok: [10.182.131.166] => (item=/etc/audit/rules.d/audit.STIG.rules) => {"ansible_loop_var": "item", "changed": false, "checksum": "38f324fe67c6943e07ef1910b41dedeb0b256ca4", "dest": "/tmp/ansible-backups-2023-05-25-12-25-58/audit.STIG.rules", "gid": 0, "group": "root", "item": "/etc/audit/rules.d/audit.STIG.rules", "md5sum": "396d715044fc7a8d92a0332d3edb4112", "mode": "0640", "owner": "root", "size": 5080, "src": "/etc/audit/rules.d/audit.STIG.rules", "state": "file", "uid": 0}

TASK [vmware-photon-3.0-stig-ansible-hardening : PHTN-30-000001 - Update/Create audit.STIG.rules file] ************************************************************************************************************************
changed: [10.182.131.166] => {"changed": true, "checksum": "aaafa4e8c28743ce3cc22c818f28f4cb9a3f53b2", "dest": "/etc/audit/rules.d/audit.STIG.rules", "gid": 0, "group": "root", "md5sum": "91a31e7bbf9e3f0d7f390feb4360581b", "mode": "0640", "owner": "root", "size": 5180, "src": "/root/.ansible/tmp/ansible-tmp-1685039234.3606877-890-106251101523760/source", "state": "file", "uid": 0}

A more conservative and preferred approach is to target any non-compliant controls or run each component separately allowed you to perform any functional testing in between.

# Providing the tag "eam" will instruct the playbook to only run the eam role. This tag can be seen in each roles task/main.yml file.
> ansible-playbook -i 10.182.131.166, -u root playbook.yml -k -v --extra-vars @vars-vcenter-7.0U3eplus.yml --tags eam

# Providing the tag "VCEM-70-000001" will instruct the playbook to only run task tagged with the STIG ID of VCEM-70-000001.
> ansible-playbook -i 10.182.131.166, -u root playbook.yml -k -v --extra-vars @vars-vcenter-7.0U3eplus.yml --tags VCEM-70-000001

4.3 - Cloud Foundation

Performing compliance automation tasks for VMware Cloud Foundation.

4.3.1 - Audit Cloud Foundation 5.x

Auditing VCF 5.x for STIG Compliance

Overview

Auditing VCF for STIG compliance involves scanning the SDDC Manager appliance.

Scanning other components of a VCF deployment such as vSphere and NSX is documented in those sections on this site.

Prerequisites

Versions listed below were used for this documentation. Other versions of these tools may work as well but if issues are found it is recommended to try the versions listed here.

  • InSpec/CINC Auditor 6.6.0
  • SAF CLI 1.4.0
  • STIG Viewer 2.17
  • A VCF 5.x environment.
  • An account with access to VCF.

Assumptions

  • Commands are being ran from a Linux machine. Windows will also work but paths and commands may need to be adjusted from the examples.
  • The DOD Compliance and Automation repository downloaded and extracted to /usr/share/stigs.
  • CINC Auditor is used in lieu of InSpec. If InSpec is used replace cinc-auditor with inspec when running commands.

Auditing SDDC Manager

Generate bearer token for SDDC Manager

The SDDC Manager InSpec profile connects to the API via a bearer token to query some configurations when auditing.

This example uses curl to generate a token. This can also be done via other methods such as Postman or the UI as shown below.

curl -k 'https://sddc-manager.vrack.vsphere.local/v1/tokens' -i -X POST \
    -H 'Content-Type: application/json' \
    -H 'Accept: application/json' \
    -d '{
  "username" : "administrator@vsphere.local",
  "password" : "replaceme"
}'
curl -k 'https://sddc-manager.vrack.vsphere.local/v1/tokens' -i -X POST \
    -H 'Content-Type: application/json' \
    -H 'Accept: application/json' \
    -d '{
  "username" : "administrator@vsphere.local",
  "password" : "replaceme"
}'

A token can also be generated UI by going to the Developer Center » API Explorer » Tokens.
alt text

Retrieve token by copying the value in the accessToken field.
alt text

Update profile inputs

Included in the vmware-cloud-foundation-sddcmgr-5x-stig-baseline is an example inputs file with variables relevant to SDDC Manager. This is used to provide InSpec with values specific to the environment being audited.

Open the inputs file for editing.

# Navigate to the InSpec profile folder
cd /usr/share/stigs/vcf/5.x/v1r2-srg/inspec/vmware-cloud-foundation-sddcmgr-5x-stig-baseline/

# Edit the inputs file
vi inputs-vcf-sddcmgr-example.yml
# Navigate to the InSpec profile folder
cd /usr/share/stigs/vcf/5.x/v1r1-srg/inspec/vmware-cloud-foundation-sddcmgr-5x-stig-baseline/

# Edit the inputs file
vi inputs-vcf-sddcmgr-example.yml

Update the inputs as shown below with values relevant to your environment. Specifically syslogServer,sddcManager,bearerToken,sftpBackupsEnabled,sftpServer,ntpServers,currentVersion,and myVmwareAccount.

# Inputs for Photon OS.
authprivlog: /var/log/messages
sshdcommand: "sshd -T -C 'user=vcf'"
# Enter environment specific syslog server with port. replace.local:514
syslogServer: 'replace.local:514'
# Inputs for PostgreSQL. No updates needed.
postgres_user: postgres
pg_data_dir: /data/pgdata/
pg_log_dir: /var/log/postgres
pg_owner: postgres
pg_group: users
# SDDC Manager Application
# Enter SDDC Manager FQDN/IP
sddcManager: 'sddc-manager.vsphere.local'
# Enter bearer token for API based tests
bearerToken: 'Bearer eyJhbGciOiJIUzI1NiJ9.eyJqd...'
# Set to true if file based/sftp backups are used for SDDC Manager. Set to false if image based backups are used.
sftpBackupsEnabled: true
# Enter environment specific sftp server.
sftpServer: '10.1.2.3'
# Enter environment specific ntp servers. This is an array.
ntpServers: ['time-a-g.nist.gov','time-b-g.nist.gov']
# Enter latest version of SDDC manager with build.
currentVersion: '5.1.0.0-22688368'
# Enter myvmware account used to pull updates in SDDC Manager if used.
myVmwareAccount: 'myvmwarevcfaccount@test.local'
# Inputs for Photon OS.
authprivlog: /var/log/audit/auth.log
sshdcommand: "sshd -T -C 'user=vcf'"
# Enter environment specific syslog server with port. replace.local:514
syslogServer: 'replace.local:514'
# Inputs for PostgreSQL. No updates needed.
postgres_user: postgres
pg_data_dir: /data/pgdata/
pg_log_dir: /var/log/postgres
pg_owner: postgres
pg_group: users
# SDDC Manager Application
# Enter SDDC Manager FQDN/IP
sddcManager: 'sddc-manager.vsphere.local'
# Enter bearer token for API based tests
bearerToken: 'Bearer eyJhbGciOiJIUzI1NiJ9.eyJqd...'
# Set to true if file based/sftp backups are used for SDDC Manager. Set to false if image based backups are used.
sftpBackupsEnabled: true
# Enter environment specific sftp server.
sftpServer: '10.1.2.3'
# Enter environment specific ntp servers. This is an array.
ntpServers: ['time-a-g.nist.gov','time-b-g.nist.gov']
# Enter latest version of SDDC manager with build. 5.0.0.0-21822418
currentVersion: '5.0.0.0-21822418'
# Enter myvmware account used to pull updates in SDDC Manager if used.
myVmwareAccount: 'myvmwarevcfaccount@test.local'

Update the SSH config to allow scan

By default the SDDC Manager appliance does not allow root SSH and the vcf does not have the required privileges to complete the scan so root SSH must be temporarily enabled to complete the scan. These steps can be reversed once the audit is complete.

# Allow root SSH into SDDC manager
ssh vcf@sddc-manager.vsphere.local
su -
vi /etc/ssh/sshd_config
# Update PermitRootLogin from no to yes and save
systemctl restart sshd

Run the audit

In this example we will be scanning a target SDDC Manager, specifying an inputs file, and outputting a report to the CLI and to a JSON file ran from a linux machine.

# Navigate to the InSpec profile folder
cd /usr/share/stigs/vcf/5.x/v1r2-srg/inspec/vmware-cloud-foundation-sddcmgr-5x-stig-baseline/

# Run InSpec
cinc-auditor exec . -t ssh://root@sddc-manager.vsphere.local --password 'replaceme' --show-progress --enhanced-outcomes --input-file inputs-vcf-sddcmgr-example.yml --reporter cli json:/tmp/reports/VCF_5.1.0_SDDC_Manager_STIG_Report.json

# Shown below is the last part of the output at the CLI.
  ✔  CFUI-5X-000019: The SDDC Manager UI service log files must only be accessible by privileged users.
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/access.log is expected not to be writable by others
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/access.log owner is expected to cmp == "vcf_sddc_manager_ui_app"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/access.log group is expected to cmp == "vcf"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/sddc-manager-ui-activity.log is expected not to be writable by others
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/sddc-manager-ui-activity.log owner is expected to cmp == "vcf_sddc_manager_ui_app"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/sddc-manager-ui-activity.log group is expected to cmp == "vcf"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/cspViolationReport.log is expected not to be writable by others
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/cspViolationReport.log owner is expected to cmp == "vcf_sddc_manager_ui_app"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/cspViolationReport.log group is expected to cmp == "vcf"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/sddcManagerServer.log is expected not to be writable by others
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/sddcManagerServer.log owner is expected to cmp == "vcf_sddc_manager_ui_app"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/sddcManagerServer.log group is expected to cmp == "vcf"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/supervisor.log is expected not to be writable by others
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/supervisor.log owner is expected to cmp == "vcf_sddc_manager_ui_app"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/supervisor.log group is expected to cmp == "vcf"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/user-logs/administrator-vsphere.local/administrator.server.log is expected not to be writable by others
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/user-logs/administrator-vsphere.local/administrator.server.log owner is expected to cmp == "vcf_sddc_manager_ui_app"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/user-logs/administrator-vsphere.local/administrator.server.log group is expected to cmp == "vcf"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/user-logs/administrator-vsphere.local/administrator.client.log is expected not to be writable by others
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/user-logs/administrator-vsphere.local/administrator.client.log owner is expected to cmp == "vcf_sddc_manager_ui_app"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/user-logs/administrator-vsphere.local/administrator.client.log group is expected to cmp == "vcf"
  ✔  CFUI-5X-000022: The SDDC Manager UI service must offload logs to a centralized logging server.
     ✔  File /etc/rsyslog.d/stig-services-sddc-manager-ui-app.conf content is expected to eq "module(load=\"imfile\" mode=\"inotify\")\ninput(type=\"imfile\"\n      File=\"/var/log/vmware/vcf/sd...     Tag=\"vcf-sddc-manager-ui-app-user-logs\"\n      Severity=\"info\"\n      Facility=\"local0\")"
  ✔  CFUI-5X-000034: The SDDC Manager UI service must have Web Distributed Authoring (WebDAV) disabled.
     ✔  Command: `(cd /opt/vmware/vcf/sddc-manager-ui-app/server/node_modules/ && npm list 2>/dev/null | grep webdav)` stdout.strip is expected to eq ""
  ✔  CFUI-5X-000044: The SDDC Manager UI service directory tree must be secured.
     ✔  Command: `find /opt/vmware/vcf/sddc-manager-ui-app/ -xdev -type f -a '(' -perm -o+w -o -not -user vcf_sddc_manager_ui_app -o -not -group vcf ')' -exec ls -ld {} \;` stdout.strip is expected to eq ""

Profile Summary: 200 successful controls, 9 control failures, 0 controls skipped
Test Summary: 974 successful, 21 failures, 0 skipped
# Navigate to the InSpec profile folder
cd /usr/share/stigs/vcf/5.x/v1r1-srg/inspec/vmware-cloud-foundation-sddcmgr-5x-stig-baseline/

# Run InSpec
cinc-auditor exec . -t ssh://root@sddc-manager.vsphere.local --password 'replaceme' --show-progress --enhanced-outcomes --input-file inputs-vcf-sddcmgr-example.yml --reporter cli json:/tmp/reports/VCF_5.0.0_SDDC_Manager_STIG_Report.json

# Shown below is the last part of the output at the CLI.
  ✔  CFUI-5X-000019: The SDDC Manager UI service log files must only be accessible by privileged users.
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/access.log is expected not to be writable by others
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/access.log owner is expected to cmp == "vcf_sddc_manager_ui_app"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/access.log group is expected to cmp == "vcf"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/sddc-manager-ui-activity.log is expected not to be writable by others
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/sddc-manager-ui-activity.log owner is expected to cmp == "vcf_sddc_manager_ui_app"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/sddc-manager-ui-activity.log group is expected to cmp == "vcf"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/cspViolationReport.log is expected not to be writable by others
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/cspViolationReport.log owner is expected to cmp == "vcf_sddc_manager_ui_app"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/cspViolationReport.log group is expected to cmp == "vcf"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/sddcManagerServer.log is expected not to be writable by others
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/sddcManagerServer.log owner is expected to cmp == "vcf_sddc_manager_ui_app"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/sddcManagerServer.log group is expected to cmp == "vcf"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/supervisor.log is expected not to be writable by others
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/supervisor.log owner is expected to cmp == "vcf_sddc_manager_ui_app"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/supervisor.log group is expected to cmp == "vcf"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/user-logs/administrator-vsphere.local/administrator.server.log is expected not to be writable by others
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/user-logs/administrator-vsphere.local/administrator.server.log owner is expected to cmp == "vcf_sddc_manager_ui_app"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/user-logs/administrator-vsphere.local/administrator.server.log group is expected to cmp == "vcf"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/user-logs/administrator-vsphere.local/administrator.client.log is expected not to be writable by others
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/user-logs/administrator-vsphere.local/administrator.client.log owner is expected to cmp == "vcf_sddc_manager_ui_app"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/user-logs/administrator-vsphere.local/administrator.client.log group is expected to cmp == "vcf"
  ✔  CFUI-5X-000022: The SDDC Manager UI service must offload logs to a centralized logging server.
     ✔  File /etc/rsyslog.d/stig-services-sddc-manager-ui-app.conf content is expected to eq "module(load=\"imfile\" mode=\"inotify\")\ninput(type=\"imfile\"\n      File=\"/var/log/vmware/vcf/sd...     Tag=\"vcf-sddc-manager-ui-app-user-logs\"\n      Severity=\"info\"\n      Facility=\"local0\")"
  ✔  CFUI-5X-000034: The SDDC Manager UI service must have Web Distributed Authoring (WebDAV) disabled.
     ✔  Command: `(cd /opt/vmware/vcf/sddc-manager-ui-app/server/node_modules/ && npm list 2>/dev/null | grep webdav)` stdout.strip is expected to eq ""
  ✔  CFUI-5X-000044: The SDDC Manager UI service directory tree must be secured.
     ✔  Command: `find /opt/vmware/vcf/sddc-manager-ui-app/ -xdev -type f -a '(' -perm -o+w -o -not -user vcf_sddc_manager_ui_app -o -not -group vcf ')' -exec ls -ld {} \;` stdout.strip is expected to eq ""

Profile Summary: 200 successful controls, 9 control failures, 0 controls skipped
Test Summary: 974 successful, 21 failures, 0 skipped

Convert the results to CKL

If a STIG Viewer CKL file is needed then the results from the scans can be converted to CKL with the SAF CLI.

# Converting the VCSA scan results from the prior section to CKL
saf convert hdf2ckl -i /tmp/reports/VCF_5.1.0_SDDC_Manager_STIG_Report.json -o /tmp/reports/VCF_5.1.0_SDDC_Manager_STIG_Report.ckl --hostname sddc-manager.vsphere.local --fqdn sddc-manager.vsphere.local --ip 10.2.3.4 --mac 00:00:00:00:00:00

Opening the CKL file in STIG Viewer will look like the screenshot below. Note the InSpec results are included in the Finding Details pane. alt text

4.3.2 - Remediate Cloud Foundation 5.x

Remediating VCF 5.x for STIG Compliance

Overview

Remediating VCF for STIG compliance involves running an Ansible playbook against the target SDDC Manager appliance over SSH to configure any non-compliant controls.

Remediating other components of a VCF deployment such as vSphere and NSX is documented in those sections on this site.

Prerequisites

Versions listed below were used for this documentation. Other versions of these tools may work as well but if issues are found it is recommended to try the versions listed here.

  • Ansible 2.14.2
  • A VCF 5.x environment.
  • An account with access to VCF.

Assumptions

  • The DOD Compliance and Automation repository downloaded and extracted to /usr/share/stigs.
  • Ansible installed and all playbook dependencies resolved as provided in the requirements.yml file in each playbook. Install with ansible-galaxy roles install -r requirements.yml.
  • The dependent Photon OS Ansible roles(Photon 3.0 for VCF 5.0.x and Photon 4 for VCF 5.1.x) installed and available. Verify role installation with ansible-galaxy role list.

Remediating SDDC Manager

Generate bearer token for SDDC Manager

The SDDC Manager Ansible playbook connects to the API via a bearer token to update product controls while the appliance controls are configured via SSH.

This example uses curl to generate a token. This can also be done via other methods such as Postman or the UI as shown below.

curl -k 'https://sddc-manager.vrack.vsphere.local/v1/tokens' -i -X POST \
    -H 'Content-Type: application/json' \
    -H 'Accept: application/json' \
    -d '{
  "username" : "administrator@vsphere.local",
  "password" : "replaceme"
}'
curl -k 'https://sddc-manager.vrack.vsphere.local/v1/tokens' -i -X POST \
    -H 'Content-Type: application/json' \
    -H 'Accept: application/json' \
    -d '{
  "username" : "administrator@vsphere.local",
  "password" : "replaceme"
}'

A token can also be generated UI by going to the Developer Center » API Explorer » Tokens.
alt text

Retrieve token by copying the value in the accessToken field.
alt text

Update vars file

In order to run the playbook, environment specific values need to be provided. An example vars file vars-sddcmgr-example.yml is provided.

Open the inputs file for editing.

# Navigate to the Ansible playbook folder
cd /usr/share/stigs/vcf/5.x/v1r2-srg/ansible/vmware-cloud-foundation-sddcmgr-5x-stig-ansible-hardening

# Edit the vars file
vi vars-sddcmgr-example.yml
# Navigate to the Ansible playbook folder
cd /usr/share/stigs/vcf/5.x/v1r1-srg/ansible/vmware-cloud-foundation-sddcmgr-5x-stig-ansible-hardening

# Edit the vars file
vi vars-sddcmgr-example.yml

Update the variables as shown below with values relevant to your environment. Specifically var_sddc_manager, var_bearer_token, var_time_servers, var_password_rotate_days.

# General
run_create_backups: true

# Photon OS
create_backups: true
run_etc_issue_dod: true
var_rsyslog_server_name: 'syslog.test.local'
var_rsyslog_server_port: '514'
var_rsyslog_server_protocol: 'tcp'

# Application
# Enter SDDC Manager FQDN or IP for API Calls
var_sddc_manager: 'sddc-manager.vsphere.local'
# Enter generated bearer token here
var_bearer_token: ''
# Enter an array of 1 to 2 NTP servers
var_time_servers:
  - 'time-a-g.nist.gov'
  - 'time-b-g.nist.gov'
# Between 30 and 90
var_password_rotate_days: 90
# General
run_create_backups: true

# Photon OS
var_syslog_authpriv_log: '/var/log/audit/auth.log'
## Update login banner with DoD banner
run_sshd_banner_issue: true
# NTP is covered in the Application controls
run_set_ntp_server: false

# Application
# Enter SDDC Manager FQDN or IP for API Calls
var_sddc_manager: 'sddc-manager.vrack.vsphere.local'
# Enter generated bearer token here
var_bearer_token: 'UNDT1VOVF9XUklURSIsIk5FVFdPUktfUE9PTF9SRUFEIi'
# Enter an array of 1 to 2 NTP servers
var_time_servers:
  - 'time-a-g.nist.gov'
  - 'time-b-g.nist.gov'
# Between 30 and 90
var_password_rotate_days: 90

Update the SSH config to allow scan

By default the SDDC Manager appliance does not allow root SSH and the vcf does not have the required privileges to complete the scan so root SSH must be temporarily enabled to complete the scan. These steps can be reversed once remediation is complete.

# Allow root SSH into SDDC manager
ssh vcf@sddc-manager.vsphere.local
su -
vi /etc/ssh/sshd_config
# Update PermitRootLogin from no to yes and save
systemctl restart sshd

Running the playbook

To run all of the SDDC Manager controls, follow the example below.

# Navigate to the Ansible playbook folder
cd /usr/share/stigs/vcf/5.x/v1r2-srg/ansible/vmware-cloud-foundation-sddcmgr-5x-stig-ansible-hardening

# The -k parameter will prompt for password and we are using extra-vars to specify a variable file for the playbook to use. Command assume it is being ran from the playbook folder.
> ansible-playbook -i 10.0.0.4, -u 'root' playbook.yml -k -v --extra-vars @vars-sddcmgr-example.yml

# Output example
TASK [application : CFAP-5X-000127 - Set credential rotate policy] ************************************************************************************************************************************************************************
changed: [10.0.0.4] => {"cache_control": "no-cache, no-store, max-age=0, must-revalidate", "changed": true, "connection": "close", "content_type": "application/json", "cookies": {}, "cookies_string": "", "date": "Thu, 01 Jun 2023 18:19:36 GMT", "elapsed": 0, "expires": "0", "json": {"id": "f0f9e481-9555-46ea-bbc0-76d144323fe6", "status": "IN_PROGRESS"}, "location": "https://sddc-manager.vrack.vsphere.local/v1/tasks/f0f9e481-9555-46ea-bbc0-76d144323fe6", "msg": "OK (unknown bytes)", "pragma": "no-cache", "redirected": false, "server": "nginx", "status": 202, "transfer_encoding": "chunked", "url": "https://sddc-manager.vrack.vsphere.local/v1/credentials", "x_content_type_options": "nosniff", "x_frame_options": "DENY", "x_xss_protection": "1; mode=block"}

TASK [application : CFAP-5X-000127 - Wait for task to complete] ***************************************************************************************************************************************************************************
ok: [10.0.0.4] => {"attempts": 1, "cache_control": "no-cache, no-store, max-age=0, must-revalidate", "changed": false, "connection": "close", "content_type": "application/json;charset=UTF-8", "cookies": {}, "cookies_string": "", "date": "Thu, 01 Jun 2023 18:19:37 GMT", "elapsed": 0, "expires": "0", "json": {"creationTimestamp": "2023-06-01T18:19:36.784Z", "errors": [], "id": "f0f9e481-9555-46ea-bbc0-76d144323fe6", "isCancellable": false, "name": "Credentials update auto rotate policy operation", "resolutionStatus": "UNRESOLVED", "status": "SUCCESSFUL", "subTasks": [{"completionTimestamp": "2023-06-01T18:19:36.784Z", "creationTimestamp": "2023-06-01T18:19:36.784Z", "description": "Prevalidation of password update auto rotate policy request", "name": "Password update auto rotate policy prevalidation", "status": "SUCCESSFUL"}], "type": "PASSWORD_AUTO_ROTATE_POLICY_UPDATE"}, "msg": "OK (unknown bytes)", "pragma": "no-cache", "redirected": false, "referrer_policy": "no-referrer", "server": "nginx", "status": 200, "strict_transport_security": "max-age=15768000", "transfer_encoding": "chunked", "url": "https://sddc-manager.vrack.vsphere.local/v1/tasks/f0f9e481-9555-46ea-bbc0-76d144323fe6", "x_content_type_options": "nosniff, nosniff", "x_frame_options": "DENY, SAMEORIGIN", "x_xss_protection": "1; mode=block"}

TASK [application : CFAP-5X-000128 - The SDDC Manager must use an account dedicated for downloading updates and patches.] *****************************************************************************************************************
ok: [10.0.0.4] => {
    "msg": "CFAP-5X-000128 - This control must be manually remediated."
}

TASK [application : CFAP-5X-000129 - Get current basic auth status] ***********************************************************************************************************************************************************************
ok: [10.0.0.4] => {"cache_control": "no-cache, no-store, max-age=0, must-revalidate", "changed": false, "connection": "close", "content_type": "application/json;charset=UTF-8", "cookies": {}, "cookies_string": "", "date": "Thu, 01 Jun 2023 18:19:39 GMT", "elapsed": 0, "expires": "0", "json": {"basicAuthDetails": {"status": "ENABLED", "username": "admin"}, "domain": {"id": "529797b0-1b5c-4f90-a956-44b2398edba9"}, "fqdn": "sddc-manager.vrack.vsphere.local", "id": "dd56c751-49b5-4a69-957c-009a7ea79147", "ipAddress": "10.0.0.4", "version": "5.0.0.0-21822418"}, "msg": "OK (unknown bytes)", "pragma": "no-cache", "redirected": false, "referrer_policy": "no-referrer", "server": "nginx", "status": 200, "strict_transport_security": "max-age=15768000", "transfer_encoding": "chunked", "url": "https://sddc-manager.vrack.vsphere.local/v1/sddc-manager", "x_content_type_options": "nosniff, nosniff", "x_frame_options": "DENY, SAMEORIGIN", "x_xss_protection": "1; mode=block"}

TASK [application : CFAP-5X-000129 - Disable Basic Auth] **********************************************************************************************************************************************************************************
changed: [10.0.0.4] => {"cache_control": "no-cache, no-store, max-age=0, must-revalidate", "changed": true, "connection": "close", "content_length": "0", "cookies": {}, "cookies_string": "", "date": "Thu, 01 Jun 2023 18:19:40 GMT", "elapsed": 0, "expires": "0", "msg": "OK (0 bytes)", "pragma": "no-cache", "redirected": false, "referrer_policy": "no-referrer", "server": "nginx", "status": 200, "strict_transport_security": "max-age=15768000", "url": "https://sddc-manager.vrack.vsphere.local/v1/sddc-manager", "x_content_type_options": "nosniff, nosniff", "x_frame_options": "DENY, SAMEORIGIN", "x_xss_protection": "1; mode=block"}
# Navigate to the Ansible playbook folder
cd /usr/share/stigs/vcf/5.x/v1r1-srg/ansible/vmware-cloud-foundation-sddcmgr-5x-stig-ansible-hardening

# The -k parameter will prompt for password and we are using extra-vars to specify a variable file for the playbook to use. Command assume it is being ran from the playbook folder.
> ansible-playbook -i 10.0.0.4, -u 'root' playbook.yml -k -v --extra-vars @vars-sddcmgr-example.yml

# Output example
TASK [application : CFAP-5X-000127 - Set credential rotate policy] ************************************************************************************************************************************************************************
changed: [10.0.0.4] => {"cache_control": "no-cache, no-store, max-age=0, must-revalidate", "changed": true, "connection": "close", "content_type": "application/json", "cookies": {}, "cookies_string": "", "date": "Thu, 01 Jun 2023 18:19:36 GMT", "elapsed": 0, "expires": "0", "json": {"id": "f0f9e481-9555-46ea-bbc0-76d144323fe6", "status": "IN_PROGRESS"}, "location": "https://sddc-manager.vrack.vsphere.local/v1/tasks/f0f9e481-9555-46ea-bbc0-76d144323fe6", "msg": "OK (unknown bytes)", "pragma": "no-cache", "redirected": false, "server": "nginx", "status": 202, "transfer_encoding": "chunked", "url": "https://sddc-manager.vrack.vsphere.local/v1/credentials", "x_content_type_options": "nosniff", "x_frame_options": "DENY", "x_xss_protection": "1; mode=block"}

TASK [application : CFAP-5X-000127 - Wait for task to complete] ***************************************************************************************************************************************************************************
ok: [10.0.0.4] => {"attempts": 1, "cache_control": "no-cache, no-store, max-age=0, must-revalidate", "changed": false, "connection": "close", "content_type": "application/json;charset=UTF-8", "cookies": {}, "cookies_string": "", "date": "Thu, 01 Jun 2023 18:19:37 GMT", "elapsed": 0, "expires": "0", "json": {"creationTimestamp": "2023-06-01T18:19:36.784Z", "errors": [], "id": "f0f9e481-9555-46ea-bbc0-76d144323fe6", "isCancellable": false, "name": "Credentials update auto rotate policy operation", "resolutionStatus": "UNRESOLVED", "status": "SUCCESSFUL", "subTasks": [{"completionTimestamp": "2023-06-01T18:19:36.784Z", "creationTimestamp": "2023-06-01T18:19:36.784Z", "description": "Prevalidation of password update auto rotate policy request", "name": "Password update auto rotate policy prevalidation", "status": "SUCCESSFUL"}], "type": "PASSWORD_AUTO_ROTATE_POLICY_UPDATE"}, "msg": "OK (unknown bytes)", "pragma": "no-cache", "redirected": false, "referrer_policy": "no-referrer", "server": "nginx", "status": 200, "strict_transport_security": "max-age=15768000", "transfer_encoding": "chunked", "url": "https://sddc-manager.vrack.vsphere.local/v1/tasks/f0f9e481-9555-46ea-bbc0-76d144323fe6", "x_content_type_options": "nosniff, nosniff", "x_frame_options": "DENY, SAMEORIGIN", "x_xss_protection": "1; mode=block"}

TASK [application : CFAP-5X-000128 - The SDDC Manager must use an account dedicated for downloading updates and patches.] *****************************************************************************************************************
ok: [10.0.0.4] => {
    "msg": "CFAP-5X-000128 - This control must be manually remediated."
}

TASK [application : CFAP-5X-000129 - Get current basic auth status] ***********************************************************************************************************************************************************************
ok: [10.0.0.4] => {"cache_control": "no-cache, no-store, max-age=0, must-revalidate", "changed": false, "connection": "close", "content_type": "application/json;charset=UTF-8", "cookies": {}, "cookies_string": "", "date": "Thu, 01 Jun 2023 18:19:39 GMT", "elapsed": 0, "expires": "0", "json": {"basicAuthDetails": {"status": "ENABLED", "username": "admin"}, "domain": {"id": "529797b0-1b5c-4f90-a956-44b2398edba9"}, "fqdn": "sddc-manager.vrack.vsphere.local", "id": "dd56c751-49b5-4a69-957c-009a7ea79147", "ipAddress": "10.0.0.4", "version": "5.0.0.0-21822418"}, "msg": "OK (unknown bytes)", "pragma": "no-cache", "redirected": false, "referrer_policy": "no-referrer", "server": "nginx", "status": 200, "strict_transport_security": "max-age=15768000", "transfer_encoding": "chunked", "url": "https://sddc-manager.vrack.vsphere.local/v1/sddc-manager", "x_content_type_options": "nosniff, nosniff", "x_frame_options": "DENY, SAMEORIGIN", "x_xss_protection": "1; mode=block"}

TASK [application : CFAP-5X-000129 - Disable Basic Auth] **********************************************************************************************************************************************************************************
changed: [10.0.0.4] => {"cache_control": "no-cache, no-store, max-age=0, must-revalidate", "changed": true, "connection": "close", "content_length": "0", "cookies": {}, "cookies_string": "", "date": "Thu, 01 Jun 2023 18:19:40 GMT", "elapsed": 0, "expires": "0", "msg": "OK (0 bytes)", "pragma": "no-cache", "redirected": false, "referrer_policy": "no-referrer", "server": "nginx", "status": 200, "strict_transport_security": "max-age=15768000", "url": "https://sddc-manager.vrack.vsphere.local/v1/sddc-manager", "x_content_type_options": "nosniff, nosniff", "x_frame_options": "DENY, SAMEORIGIN", "x_xss_protection": "1; mode=block"}

A more conservative and preferred approach is to target any non-compliant controls or run each component separately allowed you to perform any functional testing in between.

# Navigate to the Ansible playbook folder
cd /usr/share/stigs/vcf/5.x/v1r2-srg/ansible/vmware-cloud-foundation-sddcmgr-5x-stig-ansible-hardening

# Providing the tag "application" will instruct the playbook to only run the application role. This tag can be seen in each roles task/main.yml file.
> ansible-playbook -i 10.0.0.4, -u 'root' playbook.yml -k -v --extra-vars @vars-sddcmgr-example.yml --tags application

# Providing the tag "CFAP-5X-000002" will instruct the playbook to only run task tagged with the STIG ID of CFAP-5X-000002.
> ansible-playbook -i 10.0.0.4, -u 'root' playbook.yml -k -v --extra-vars @vars-sddcmgr-example.yml --tags CFAP-5X-000002
# Navigate to the Ansible playbook folder
cd /usr/share/stigs/vcf/5.x/v1r1-srg/ansible/vmware-cloud-foundation-sddcmgr-5x-stig-ansible-hardening

# Providing the tag "application" will instruct the playbook to only run the application role. This tag can be seen in each roles task/main.yml file.
> ansible-playbook -i 10.0.0.4, -u 'root' playbook.yml -k -v --extra-vars @vars-sddcmgr-example.yml --tags application

# Providing the tag "CFAP-5X-000002" will instruct the playbook to only run task tagged with the STIG ID of CFAP-5X-000002.
> ansible-playbook -i 10.0.0.4, -u 'root' playbook.yml -k -v --extra-vars @vars-sddcmgr-example.yml --tags CFAP-5X-000002

4.3.3 - Audit Cloud Foundation 4.x

Auditing VCF 4.x for STIG Compliance

Overview

Auditing VCF for STIG compliance involves scanning the SDDC Manager appliance.

Scanning other components of a VCF deployment such as vSphere and NSX is documented in those sections on this site.

Prerequisites

Versions listed below were used for this documentation. Other versions of these tools may work as well but if issues are found it is recommended to try the versions listed here.

Auditing SDDC Manager

Generate bearer token for SDDC Manager

The SDDC Manager InSpec profile connects to the API via a bearer token to query the configurations to audit.

This is a curl example. This can also be done via other methods such as Postman.

# Ran from a Linux machine.
curl -k 'https://sddc-manager.vrack.vsphere.local/v1/tokens' -i -X POST \
    -H 'Content-Type: application/json' \
    -H 'Accept: application/json' \
    -d '{
  "username" : "administrator@vsphere.local",
  "password" : "replaceme"
}'

A token can also be generated UI by going to the Developer Center » API Explorer » Tokens.
alt text

Retrieve token by copying the value in the accessToken field.
alt text

Update profile inputs

Included in the vmware-vcf-sddcmgr-4x-stig-baseline is an example inputs-vcf-sddcmgr-4x-example file with the following inputs relevant to SDDC Manager.

Update the inputs as shown below with values relevant to your environment. Specifically syslogServer,sddcManager,bearerToken,sftpBackupsEnabled,sftpServer,ntpServers,currentVersion,and myVmwareAccount.

# Inputs for NGINX
nginx_conf_path: /etc/nginx/nginx.conf
limit_conn_ip_limit: '100'
limit_conn_server_limit: '1000'
nginx_ssl_ciphers: 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256'
# Inputs for Photon OS.
authprivlog: /var/log/audit/auth.log
sshdcommand: "sshd -T -C 'user=vcf'"
# Enter environment specific syslog server with port. replace.local:514
syslogServer: 'replace.local:514'
# SDDC Manager Application
# Enter SDDC Manager FQDN/IP
sddcManager: 'sddc-manager.vsphere.local'
# Enter bearer token for API based tests
bearerToken: 'Bearer eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJhOGVjYTViMS04OTMwLTRiOGYtOGJmMy0xM2U4NTg2MzE3MmYiLCJpYXQiOjE2ODU1NDUyMzQsInN1YiI6ImFkbWluaXN0cmF0b3JAdnNwaGVyZS5sb2NhbCIsImlzcyI6InZjZi1hdXRoIiwiYXVkIjoic2RkYy1zZXJ2aWNlcyIsIm5iZiI6MTY4NTU0NTIzNCwiZXhwIjoxNjg1NTQ4ODM0LCJ1c2VyIjoiYWRtaW5pc3RyYXRvckB2c3BoZXJlLmxvY2FsIiwibmFtZSI6ImFkbWluaXN0cmF0b3JAdnNwaGVyZS5sb2NhbCIsInNjb3BlIjpbIlJFU09VUkNFX0ZVTkNUSU9OQUxJVFlfV1JJVEUiLCJMSUNFTlNJTkdfSU5GT19SRUFEIiwiU0REQ19GRURFUkFUSU9OX1dSSVRFIiwiQVZOX1dSSVRFIiwiU0REQ19NQU5BR0VSX1JFQUQiLCJDRVJUX1dSSVRFIiwiQ09NUE9TQUJJTElUWV9XUklURSIsIkxJQ0VOU0VfS0VZX1JFQUQiLCJDT01QT1NBQklMSVRZX1JFQUQiLCJFREdFX0NMVVNURVJfV1JJVEUiLCJVU0VSX1JFQUQiLCJDUkVERU5USUFMX1dSSVRFIiwiQkFDS1VQX0NPTkZJR19SRUFEIiwiQ0xVU1RFUl9XUklURSIsIkFWTl9SRUFEIiwiVkFTQV9QUk9WSURFUl9SRUFEIiwiRE9NQUlOX1dSSVRFIiwiQ0VJUF9SRUFEIiwiU09TX1dSSVRFIiwiU0REQ19NQU5BR0VSX1dSSVRFIiwiTlRQX1dSSVRFIiwiVEFHX1dSSVRFIiwiREVQT1RfQ09ORklHX1dSSVRFIiwiU1lTVEVNX1JFQUQiLCJERVBPVF9DT05GSUdfUkVBRCIsIkhPU1RfV1JJVEUiLCJSRVNPVVJDRV9MT0NLX1dSSVRFIiwiQkFDS1VQX1JFU1RPUkVfUkVBRCIsIkNFUlRfUkVBRCIsIlVTRVJfV1JJVEUiLCJVUEdSQURFX1JFQUQiLCJPVEhFUl9SRUFEIiwiTElDRU5TSU5HX1dSSVRFIiwiU09TX1JFQUQiLCJFVkVOVF9XUklURSIsIlNFQ1VSSVRZX0NPTkZJR19SRUFEIiwiQ1JFREVOVElBTF9SRUFEIiwiSE9TVF9SRUFEIiwiQ0VJUF9XUklURSIsIlJFU09VUkNFX0xPQ0tfUkVBRCIsIk9USEVSX1dSSVRFIiwiTElDRU5TRV9LRVlfV1JJVEUiLCJSRVNPVVJDRV9GVU5DVElPTkFMSVRZX1JFQUQiLCJDQV9SRUFEIiwiVEFHX1JFQUQiLCJMSUNFTlNJTkdfUkVBRCIsIk5FVFdPUktfUE9PTF9XUklURSIsIldDUF9SRUFEIiwiTElDRU5TSU5HX0lORk9fV1JJVEUiLCJCQUNLVVBfUkVTVE9SRV9XUklURSIsIk5UUF9SRUFEIiwiRURHRV9DTFVTVEVSX1JFQUQiLCJFVkVOVF9SRUFEIiwiQkFDS1VQX0NPTkZJR19XUklURSIsIldDUF9XUklURSIsIlNFUlZJQ0VfQUNDT1VOVF9XUklURSIsIk5FVFdPUktfUE9PTF9SRUFEIiwiQ0FfV1JJVEUiLCJDTFVTVEVSX1JFQUQiLCJWQVNBX1BST1ZJREVSX1dSSVRFIiwiRE5TX1dSSVRFIiwiU1lTVEVNX1dSSVRFIiwiVlJTTENNX1dSSVRFIiwiRE5TX1JFQUQiLCJTRVJWSUNFX0FDQ09VTlRfUkVBRCIsIlNERENfRkVERVJBVElPTl9SRUFEIiwiRE9NQUlOX1JFQUQiLCJWUlNMQ01fUkVBRCIsIlVQR1JBREVfV1JJVEUiXSwicm9sZSI6WyJBRE1JTiJdfQ.Wqxti-ZId624KeH5vF'
# Set to true if file based/sftp backups are used for SDDC Manager. Set to false if image based backups are used.
sftpBackupsEnabled: true
# Enter environment specific sftp server.
sftpServer: '10.1.2.3'
# Enter environment specific ntp servers. This is an array.
ntpServers: ['time-a-g.nist.gov','time-b-g.nist.gov']
# Enter latest version of SDDC manager with build. 4.5.1.0-21682411
currentVersion: '4.5.1.0-21682411'
# Enter myvmware account used to pull updates in SDDC Manager if used.
myVmwareAccount: 'myvmwarevcfaccount@test.local'

Update the SSH config to allow scan

By default the SDDC Manager appliance does not allow root SSH and the vcf does not have the required privileges to complete the scan so root SSH must be temporarily enabled to complate the scan. These steps can be reversed once the audit is complete.

# Allow root SSH into SDDC manager
ssh vcf@sddc-manager.vsphere.local
su -
vi /etc/ssh/sshd_config
# Update PermitRootLogin from no to yes and save
systemctl restart sshd

Run the audit

In this example we will be scanning a target SDDC Manager, specifying an inputs file, and outputting a report to the CLI and to a JSON file ran from a linux machine.

# Note this command is being ran from the root of the profile folder. Update paths as needed if running from a different location.
> inspec exec . -t ssh://root@sddc-manager.vsphere.local --password 'replaceme' --show-progress --input-file inputs-vcf-sddcmgr-4x-example.yml --reporter cli json:/tmp/reports/VCF_4.5.1_SDDC_Manager_STIG_Report.json

# Shown below is the last part of the output at the CLI.
Profile:   VMware Cloud Foundation SDDC Manager UI Profile (VMware Cloud Foundation SDDC Manager UI Profile)
Version:   1.0.4
Target:    ssh://root@10.0.0.4:22
Target ID: 3cb5cfd9-709c-564d-b529-36fb03269263

  ✔  CFUI-4X-000001: The SDDC Manager UI service log files must only be accessible by privileged users.
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/access.log is expected not to be writable by others
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/access.log group is expected to cmp == "vcf"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/access.log owner is expected to cmp == "vcf_sddc_manager_ui_app"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/supervisor.log is expected not to be writable by others
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/supervisor.log group is expected to cmp == "vcf"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/supervisor.log owner is expected to cmp == "vcf_sddc_manager_ui_app"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/sddcManagerServer.log is expected not to be writable by others
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/sddcManagerServer.log group is expected to cmp == "vcf"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/sddcManagerServer.log owner is expected to cmp == "vcf_sddc_manager_ui_app"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/cspViolationReport.log is expected not to be writable by others
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/cspViolationReport.log group is expected to cmp == "vcf"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/cspViolationReport.log owner is expected to cmp == "vcf_sddc_manager_ui_app"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/sddc-manager-ui-activity.log is expected not to be writable by others
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/sddc-manager-ui-activity.log group is expected to cmp == "vcf"
     ✔  File /var/log/vmware/vcf/sddc-manager-ui-app/sddc-manager-ui-activity.log owner is expected to cmp == "vcf_sddc_manager_ui_app"
  ✔  CFUI-4X-000002: The SDDC Manager UI service files must be verified for their integrity.
     ✔  Command: `rpm -V sddc-manager-ui-app | grep \"^..5......\"|grep -v -E "|\.properties"` stdout.strip is expected to eq ""
  ✔  CFUI-4X-000003: The SDDC Manager UI service must have WebDAV disabled.
     ✔  Command: `(cd /opt/vmware/vcf/sddc-manager-ui-app/server/node_modules/ && npm list 2>/dev/null | grep webdav)` stdout.strip is expected to eq ""
  ✔  CFUI-4X-000004: The SDDC Manager UI service directory tree must have permissions in an "out of the box" state.
     ✔  Command: `find /opt/vmware/vcf/sddc-manager-ui-app/ -xdev -type f -a '(' -perm -o+w -o -not -user vcf_sddc_manager_ui_app -o -not -group vcf ')' -exec ls -ld {} \;` stdout.strip is expected to eq ""
  ✔  CFUI-4X-000005: The SDDC Manager UI service log files must be moved to a permanent repository in accordance with site policy.
     ✔  File /etc/rsyslog.d/stig-services-sddc-manager-ui-app.conf content is expected to eq "module(load=\"imfile\" mode=\"inotify\")\ninput(type=\"imfile\"\n      File=\"/var/log/vmware/vcf/sd...\"\n      Tag=\"vcf-sddc-manager-ui-app-misc\"\n      Severity=\"info\"\n      Facility=\"local0\")"
  ×  CFUI-4X-000006: The SDDC Manager UI service systemd service definition permissions must be configured appropriately. (2 failed)
     ×  File /etc/systemd/system/sddc-manager-ui-app.service is expected not to be more permissive than "0640"
     expected `File /etc/systemd/system/sddc-manager-ui-app.service.more_permissive_than?("0640")` to be falsey, got true
     ✔  File /etc/systemd/system/sddc-manager-ui-app.service group is expected to cmp == "root"
     ✔  File /etc/systemd/system/sddc-manager-ui-app.service owner is expected to cmp == "root"
     ×  File /etc/systemd/system/sddc-manager-ui-db.service is expected not to be more permissive than "0640"
     expected `File /etc/systemd/system/sddc-manager-ui-db.service.more_permissive_than?("0640")` to be falsey, got true
     ✔  File /etc/systemd/system/sddc-manager-ui-db.service group is expected to cmp == "root"
     ✔  File /etc/systemd/system/sddc-manager-ui-db.service owner is expected to cmp == "root"


Profile Summary: 199 successful controls, 19 control failures, 2 controls skipped
Test Summary: 691 successful, 36 failures, 4 skipped

Convert the results to CKL

If a STIG Viewer CKL file is needed then the results from the scans can be converted to CKL with the SAF CLI.

# Converting the VCSA scan results from the prior section to CKL
saf convert hdf2ckl -i /tmp/reports/VCF_4.5.1_SDDC_Manager_STIG_Report.json -o /tmp/reports/VCF_4.5.1_SDDC_Manager_STIG_Report.ckl --hostname sddc-manager.vsphere.local --fqdn sddc-manager.vsphere.local --ip 10.2.3.4 --mac 00:00:00:00:00:00

Opening the CKL file in STIG Viewer will look like the screenshot below. Note the InSpec results are included in the Finding Details pane.

alt text

4.4 - Aria/vRealize

Performing compliance automation tasks for Aria/vRealize Suite products.

4.4.1 - Audit VMware Aria Automation 8

Auditing VMware Aria Automation 8 for STIG Compliance

Overview

Auditing VMware Aria Automation for STIG compliance involves scanning the application, the Kubernetes and Docker services running on the appliance, and the underlying Photon OS.

Prerequisites

Versions listed below were used for this documentation. Other versions of these tools may work as well but if issues are found it is recommended to utilize the versions listed here.

Auditing VMware Aria Automation

Update profile inputs

Included in each of the vmware-vra-8x-stig-baseline sub-folders (vra, docker, and kubernetes) is an inspec input file named ‘inspec.yml’. Additionally, at the top level, there is and example yml file that “rolls up” all of the variables into one file, and can be utilized at the command line.

Update each of the input files (vra/inspec.yml, docker\inspec.yml, kubernetes\inspec.yml) with inputs as shown below containing values relevant to your environment. Alternatively, update the single top level file, inputs-example.yml, with values specific to your environment.

VMware Aria Automation - Application

syslogHost: "log.test.local"
syslogPort: "514"
syslogProtocol: "tcp"
syslogSslVerify: "true"
syslogUseSsl: "false"
ntpServers: "['time.server.org']"
maxAuthTries: "2"
verbose: True
allowedCipherSuites: ["TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384","TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256","TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384","TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"]

VMware Aria Automation - Kubernetes

manifests_path: '/etc/kubernetes/manifests'
pki_path: '/etc/kubernetes/pki'
kubeadm_conf_path: '/etc/systemd/system/kubelet.service.d/10-kubeadm.conf'
kubectl_path: '/usr/local/bin/kubectl'
kubectl_minversion: 'v1.12.9'
kubernetes_conf_files: ["/etc/kubernetes/admin.conf","/etc/kubernetes/scheduler.conf","/etc/kubernetes/controller-manager.conf"]
kubectl_conf_path: '/etc/kubernetes/admin.conf'
kubelet_conf_path: '/var/lib/kubelet/config.yaml'
kubelet_kubeconf_path: ''
k8s_min_supported_version: 'v1.20.13'

Update the SSH config to allow scan

If the VMware Aria Automation appliance has SSH access disabled, the check and fix scans will not be able to run. SSH must be temporarily enabled to complete the scan, then can be disabled again once the audit is complete.

# Connect to the console through vCenter
vi /etc/ssh/sshd_config
# Update PermitRootLogin from no to yes and save
systemctl restart sshd

Run the audit

In this example we will be scanning a target VMware Aria Automation appliance, specifying an inputs file, and outputting a report to the CLI and to a JSON file run from a linux machine.

# Note this command is being run from the root of the profile folder. Update paths as needed if running from a different location.
> inspec exec . -t ssh://root@aria-automation.domain.path --password 'replaceme' --show-progress --input-file inputs-example.yml --reporter cli json:/tmp/reports/Aria_Automation_8x_STIG_Report.json

# Shown below is the last part of the output at the CLI.
  ✔  CNTR-K8-003270: The Kubernetes admin.conf must have file permissions set to 644 or more restrictive.
     ✔  File /etc/kubernetes/admin.conf is expected not to be more permissive than "0644"
     ✔  File /etc/kubernetes/scheduler.conf is expected not to be more permissive than "0644"
     ✔  File /etc/kubernetes/controller-manager.conf is expected not to be more permissive than "0644"
  ✔  CNTR-K8-003330: The Kubernetes PKI CRT must have file permissions set to 644 or more restrictive.
     ✔  File /etc/kubernetes/pki/apiserver-etcd-client.crt is expected not to be more permissive than "0644"
     ✔  File /etc/kubernetes/pki/front-proxy-client.crt is expected not to be more permissive than "0644"
     ✔  File /etc/kubernetes/pki/ca.crt is expected not to be more permissive than "0644"
     ✔  File /etc/kubernetes/pki/front-proxy-ca.crt is expected not to be more permissive than "0644"

Profile Summary: zz successful controls, zz control failures, zz controls skipped
Test Summary: zz successful, zz failures, zz skipped

Convert the results to CKL

If a STIG Viewer CKL file is needed then the results from the scans can be converted to CKL with the SAF CLI.

# Converting the scan results from the prior section to CKL
saf convert hdf2ckl -i /tmp/reports/Aria_Automation_8x_STIG_Report.json -o /tmp/reports/Aria_Automation_8x_STIG_Report.ckl --hostname aria-automation.domain.path --fqdn aria-automation.domain.path --ip 10.2.3.4 --mac 00:00:00:00:00:00

Opening the CKL file in STIG Viewer will look similar to the screenshot below. Note the InSpec results are included in the Finding Details pane.

alt text

4.4.2 - Remediate VMware Aria Automation 8

Remediating VMware Aria Automation 8 for STIG Compliance

Overview

Remediating VMware Aria Automation for STIG compliance includes the application, the Kubernetes and Docker services running on the appliance, and the underlying Photon OS.

Remediating the application controls is currently a manual process. Please refer to the Kubernetes and Docker documentation for details on remediating those controls with the provided Ansible content.

5 - Support

Support for Official STIGs, STIG Readiness Guides, and automation is provided through a variety of channels depending on the situation. It is important to adhere to the supported scenarios detailed here to avoid issues in unsupported situations.

For the most up to date information on support please visit our STIG Support KB: https://kb.vmware.com/s/article/94398

Table of contents

Types of Support

Automation Support: Issues related to running scripts, playbooks, etc found in this repository.

Content Support: Problems with the guidance text found in a STIG.
Examples:

  • Clarification on guidance text
  • A command does not work as expected
  • Typos in the text
  • Check/Fix update suggestions

Product Support: Break/fix bug type issues encountered when using features and functionality found inside a STIGs content.
Examples:

  • Enabling Secureboot causes a host not to boot.
  • Hardening a service causes it to not start.

Unsupported Scenarios

  • Content and product version mismatched. For example applying the vSphere 7 STIG to vSphere 8.
  • Attempting to apply guidance from one STIG to a product it was not intended for.
  • A product that is no longer generally supported by VMware. See the VMware Product Lifecycle Matrix for product end of general support dates.

Automation Support

Support for automation found in this repo is community based and provided on a best effort basis.

If an issue is encountered please check the open and closed issues in the issue tracker for the details of your issue. If you can’t find it, or if you’re not sure, open a new issue.

A known issues document may also be available for a product and version in that products docs folder in this repository.

Official STIG Support

Content Support

Support for issues related to content in an Official STIG should be addressed by emailing DISA at: disa.stig_spt@mail.mil

A ticket for the issue must be open in order to update the guidance in a future STIG release. DISA will work with VMware to address any tickets needing content updates as necessary.

Product Support

A support request may be opened in these cases if a valid support agreement is in place.

STIG Readiness Guide Support

Content Support

Support for issues related to content in a STIG Readiness Guide should be addressed by emailing: stigs@vmware.com

Requests recieved will be processed on a best effort basis and any needed content updates published in the next content release. In between releases, issues will be documented in a known issues document available in a products folder in this repository.

Product Support

A support request may be opened in these cases if a valid support agreement is in place.

Support Tips

Before contacting support consider the following:

  • Is this a known issue?
  • Does reverting the change restore functionality?
  • Provide the source of the guidance with version and target product version in the request.
  • Is this a supported scenario as laid out in this document?
  • Support cannot assist with implementation of any hardening guidance or provide security advice.

Disclaimer

VMware accepts no liability for the consequences of applying specific configuration settings made on the basis of the SRGs/STIGs. It must be noted that the configuration settings specified should be evaluated in a local, representative test environment before implementation in a production environment, especially within large user populations. The extensive variety of environments makes it impossible to test these configuration settings for all potential software configurations.

For some production environments, failure to test before implementation may lead to a loss of required functionality. Evaluating the risks and benefits to a system’s particular circumstances and requirements is the system owner’s responsibility. The evaluated risks resulting from not applying specified configuration settings must be approved by the responsible Authorizing Official.

Furthermore, VMware implies no warranty that the application of all specified configurations will make a system 100 percent secure. Security guidance is provided for the Department of Defense. While other agencies and organizations are free to use it, care must be given to ensure that all applicable security guidance is applied both at the device hardening level as well as the architectural level. Some of the controls may not be configurable in environments outside the DoDIN.