Skip to main content

Developing Custom Policies

This page provides an overview of developing Mondoo policies, as well as some example tutorials to get you started. It is also recommended you check out our getting started section on MQL & Mondoo Shell.

Developing Mondoo policies is designed to be intuitive for infrastructure developers and security engineers embracing automation to secure their environments. Don't worry if you are new automation, Mondoo policy development is easy to learn!

Prerequisites​

Before beginning, you should have the following installed on your local development workstation:

  • Mondoo Client - Mondoo Client should be installed and configured
  • Test Infrastructure - Depending on the type of policy you are authoring, you should have access to test the policy against assets during the development process. Examples include Linux, Windows, and macOS hosts, Kubernetes clusters, or cloud environments
  • Code Editor - As Mondoo policies are written in YAML, it is very helpful to have a developer code editor such as Visual Studio Code to help with syntax highlighting, linting, and more.

Policy as code - YAML​

Mondoo policies are written in YAML, which stands for "yet another markup language" or "YAML ain't markup language" depending on who you ask. If you are new to YAML it is highly recommended you checkout one of the many tutorials online or on YouTube.

If you are new to YAML, but would rather jump in, it is important to keep a few things in mind:

  • YAML is case sensitive
  • The files should have .yaml or .yml as the extension
  • YAML does not allow the use of tabs, and spaces should be used instead

Modern code editors such as Visual Studio Code offer YAML plugins to help with proper syntax and stylistic guidelines. If you do not have a modern code editor, installing one is highly recommended.

Getting started developing Mondoo policies​

Mondoo policies are a collection of 'scoring' and 'data' queries, along with optional metadata that includes documentation, audit and remediation steps, references, and more. This next section breaks down the components of a Mondoo policy.

Initialize a new Mondoo policy​

Mondoo Client provides the mondoo policy subcommand for interacting with Mondoo policies. At any point you can always run the mondoo policy --help command to view all of the subcommands for mondoo policy.

You can generate a starting template for a new Mondoo policy by running the mondoo policy init command. If no filename is provided, it will generate a file called example-policy.yml in the current working directory.

Generate my-policy.yml
mondoo policy init my-policy.yml

Structure of a Mondoo policy​

Next let's take a look at the structure of example Mondoo policy generated from the mondoo policy init command to understand each component.

Example Policy (part 1)
policies:
- uid: sshd
name: SSH Server Policy
version: "1.0.0"
authors:
- name: Jane Doe
email: jane@example.com
tags:
key: value
another-key: another-value
props:
sshdCiphers:
  • policies - This top-level key defines a collection of multiple policies. Each policy defines its own metadata and the referenced.
  • uid - The "uid" key is the unique identifier for the policy.
  • name - The "name" key defines a human-readable name for the policy.
  • version - The "version" key defines a semantic version for a policy.
  • authors - A section to provide information about the author of the policy.
  • name - The name of the author of the policy.
  • email - The email for the author of the policy
  • tags - The "tags" key defines key-value pairs in a map that can be used to categorize policies
Example Policy (part 2)
specs:
asset_filter:
query: platform.family.contains(_ == 'unix')
scoring_queries:
sshd-score-01:
data_queries:
sshd-data-01:
  • specs - The "specs" key contains one or many specs. Specs are a group of queries. Each spec has its own asset filter, which allows running a group of queries only to apply if a certain condition is met. For example, one spec could implement generic checks for Linux, and another only applies if Nginx is installed.
  • asset_filter - The key "assetfilter" defines a single query that decides if the policy is applicable or not. For example, a policy designed for Linux might use an asset_filter of `platform.family.contains( == 'linux')`
  • scoring_queries - The key "scoring_queries" defines a collection of queries that are executed to determine the policy score. Each scoring queries is expected to return a true/false result. All entries reference a query available under the "query" key. Multiple specs, even in different policies can re-use the same query id.
  • data_queries - The key "data_queries" defines a collection of queries that collect information about a system. Those queries do not influence the policy score.
"Example
queries:
- uid: sshd-score-01
title: Ensure SSH MaxAuthTries is set to 4 or less
query: sshd.config.params["MaxAuthTries"] <= 4
  • queries - The "queries" tag defines a list of queries
  • uid - The "uid" key is the unique identifier for the query. The uid is used to reference the query from a policy spec.
  • title - The "title" key defines a human-readable name for the query
  • query - The "query" key contains the MQL query that is run on the asset. A scoring query should return a true/false result.
"Example
docs:
desc: |
The MaxAuthTries parameter specifies the maximum number of authentication attempts permitted per connection. When the login failure count reaches half the number, error messages will be written to the syslog file detailing the login failure.
audit: |
Run the `sshd -T | grep maxauthtries` command and verify that output MaxAuthTries is 4 or less
remediation: |
Open your `/etc/ssh/sshd_config` and set `MaxAuthTries` to `4`.
refs:
- title: CIS Distribution Independent Linux
url: https://www.cisecurity.org/benchmark/distribution_independent_linux/
  • docs - The "docs" key is optional and defines helpful metadata "desc", "audit" and "remediation". This metadata is used
  • desc - The "desc" key provides a description for the query. It should provide enough context to explain the rationale for the control.
  • audit - The "audit" key provides context to allow users to manually verify the result of the information.
  • remediation - The "remediation" key provides information to fix the detected issue.
  • refs - The "refs" key defines optional web resources to learn more about the context.

Policy tutorial - Create a policy to verify Linux OpenSSH service and configuration​

This tutorial walks you through creating a Mondoo policy from scratch to validate configuration on a Linux host. To complete this tutorial you should have access to Linux host, and have the latest version of Mondoo Client installed.

Unlike other policy engines, Mondoo policies are built on the power and flexibility of MQL so that you can easily filter and make assertions about your critical business assets. This tutorial focuses on writing a policy for a Linux host, but the same pattern applies to public and private cloud environments, Kubernetes clusters, containers, and more.

Objective​

For this tutorial, you will implement the following controls using MQL:

  • Validates sshd service is running
  • Checks that the sshd configuration 'X11 forwarding' is disabled

Create a development environment​

This tutorial uses the terminal. Open a new shell session and get started by creating a new working directory:

Command Line
mkdir ~/sshd-policy

cd ~/sshd-policy

Initialize a new policy​

Initialize a new policy template that we will use for further customization:

Command Line
mondoo policy init sshd.yaml

This command will produce a new sshd.yaml in the current working directory.

Implement a Center for Internet Security (CIS) control​

For this step, we are implementing control 5.2.6 Ensure SSH X11 forwarding is disabled from the CIS Distribution Independent Linux Benchmark. Downloading the Benchmark PDF will require submitting your email to CIS's marketing database.

The benchmark states the following about this control:

5.2.6 Ensure SSH X11 forwarding is disabled

Description: The X11Forwarding parameter enables remote graphic connections by providing the ability to tunnel X11 traffic through the connection.

Remediation: Edit the /etc/ssh/sshd_config file to set the parameter as follows: X11Forwarding == no

Open sshd.yaml in a developer's text editor and add the new query to the queries array:

sshd.yaml
queries:
- uid: ensure-x11-forwarding-disabled
title: Ensure SSH X11 forwarding is disabled
query: sshd.config.params['X11Forwarding'] == 'no'

Mondoo will only execute queries that are assigned to policies. If you run the policy now in the terminal via mondoo scan --policy-bundle sshd.yaml you will see that the policy was accepted, but the query was not run. Therefore we need to assign the new 'X11Forwarding' query to the existing sshd policy.

Modify the existing policy specification by adding the uid ensure-x11-forwarding-disabled: to the scoring-queries array.

sshd.yaml
scoring_queries:
sshd-score-01:
ensure-x11-forwarding-disabled:

The required colon at the end allows each query to define additional properties, like scoring weight. Mondoo uses the default properties if nothing additional is specified.

Run the policy again via:

Command Line
mondoo scan --policy-bundle sshd.yaml

Example output

Command Line
β–  Title:  Ensure SSH X11 forwarding is disabled (failed)
Query: sshd.config.params['X11Forwarding'] == 'no'
Assessment:
[failed] sshd.config.params[X11Forwarding] == "no"
expected: == "no"

The example above shows query was executed, but failed. Open the /etc/ssh/sshd_config file and add or edit the parameter X11Forwarding no. Then re-run the policy.

Linux SSH Results

Policy tutorial - Create a new policy to verify Windows configuration​

This tutorial walks you through creating a Mondoo policy from scratch to validate configuration on a Windows host. To complete this tutorial you should have access to Windows host, and have the latest version of Mondoo Client installed.

Mondoo makes policy development with Windows fast and easy. MQL ships with many native Windows resources for querying the configuration of Windows hosts.

Objective​

For this tutorial, you will develop a Mondoo policy for Windows that achieves the following:

  • Validates that the time service is running
  • Ensures that the Windows feature 'telnet' is not installed
  • Verifies that the package 'x' is installed
  • Validates the NTP configuration for specific configuration

Create a development environment​

This tutorial uses Windows Console or Windows Terminal. Open a new PowerShell terminal and create a new working directory for this tutorial:

Command Line
New-intro-item -ItemType directory -Path win-policy
cd .\win-policy\

Initialize a new policy​

Initialize a new policy template that we will use for further customization:

Command Line
mondoo policy init windows-sample.yaml

This command will produce a new windows-sample.yaml in the current working directory.

Implement a policy for Windows​

In this section we are creating a new policy that verifies various values on Windows. To get started, open the windows-sample.yaml in a developer's text editor such as VSCode and copy/paste the following content:

\win-policy\windows-sample.yaml
policies:
- uid: windows-sample
name: Windows Sample Policy
version: "1.0.0"
authors:
- name: Jane Doe
email: jane@example.com
specs:
- asset_filter:
query: platform.family.contains(_ == 'windows')
scoring_queries:
turn-off-data-execution:
no-telnet-client:
time-service:
hotfix-KB4512578:

queries:
- uid: turn-off-data-execution
title: Ensure 'Turn off Data Execution Prevention for Explorer' is set to 'Disabled'
query: |
registrykey.property(path: 'HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\Explorer', name: 'NoDataExecutionPrevention') {
value == 0
}
docs:
desc: |
Disabling Data Execution Prevention can allow certain legacy plug-in applications to function without terminating
Explorer. The recommended state for this setting is: Disabled.

- uid: no-telnet-client
title: Test that the Telnet Client is not installed
query: windows.features.none(name == "Telnet-Client" && installed)

- uid: time-service
title: Ensure the time service is running
query: service("W32Time") { enabled running }

- uid: hotfix-KB4512578
title: Check that a specific Windows Hotfix is installed
query: windows.hotfixes.one ( hotfixId == "KB4512578" )

Make sure to Save the file.

This first query, turn-off-data-execution, ensures that the registry key is properly set. If you want to define optional documentation for a policy, the docs section can hold information for desc, audit and remediation.

Run the policy​

Run the policy using --incognito mode, which tells Mondoo Client not to send the scan results to Mondoo Platform. Return to PowerShell and run the following command:

Command Line
mondoo scan --policy-bundle .\windows-sample.yaml

Windows Results