Remote Scanning with Inventory Files
Scan remote systems, network devices, and cloud accounts by defining targets and credentials in a single inventory file.
Running queries and query packs against one asset at a time works well while you explore, but most fleets have many assets. cnspec can scan the machine it's installed on, but many targets such as network devices, cloud accounts, SaaS tenants, and servers where you can't install cnspec require remote access. An inventory file lets you list those remote targets in one place, along with the credentials cnspec needs to reach them, so you can scan your entire fleet with a single command.
This page covers the cnspec inventory file, a YAML file you author to tell cnspec what to scan. Looking for the assets Mondoo has already discovered and cataloged in your space instead? See Inventory Your Assets.
An inventory file is a YAML document that defines:
- What to scan: hosts, cloud accounts, Kubernetes clusters, SaaS tenants, and more
- How to connect: SSH, WinRM, cloud APIs, container runtimes, and other connection types
- How to authenticate: passwords, SSH keys, API tokens, or references to an external vault such as HashiCorp Vault or AWS Secrets Manager
Pass the file to cnspec with --inventory-file:
cnspec scan --inventory-file inventory.ymlYou can also pipe an inventory from stdin instead of a file, which is useful when a previous step in a pipeline generates it:
cat inventory.yml | cnspec scan --inventory-file -Structure
Every inventory file follows this structure:
apiVersion: v1
kind: Inventory
metadata:
name: my-inventory
labels:
environment: production
spec:
assets:
- name: display-name
connections:
- type: ssh
host: 10.0.0.1
port: 22
credentials:
- user: ubuntu
private_key_path: ./id_rsa
credentials:
# Optional: central credential store (referenced by secret_id)
vault:
# Optional: external vault configurationTop-level fields
| Field | Description |
|---|---|
apiVersion | Always v1. |
kind | Always Inventory. |
metadata.name | A human-readable name for the inventory. |
metadata.labels | Key-value pairs for organizing the inventory itself. |
spec.assets | List of assets to scan. |
spec.credentials | Optional map of named credentials (see Reference credentials with secret_id). |
spec.vault | Optional external vault configuration (see Vault integration). |
spec.credential_query | Optional MQL query for dynamic credential resolution. |
Asset fields
Each entry in spec.assets supports:
| Field | Description |
|---|---|
name | Display name for the asset. |
id | Optional unique identifier. |
connections | List of connection configurations. |
annotations | Key-value metadata that displays in Mondoo App. |
labels | Key-value pairs for filtering and grouping. |
Connection fields
| Field | Description |
|---|---|
type | Connection type, such as ssh, winrm, aws, azure, gcp, k8s, docker, vsphere, ms365, google-workspace, or local. cnspec also supports many other providers; see Supported Targets. |
host | Hostname or IP address. |
port | Port number (defaults depend on connection type). |
credentials | List of credentials for this connection. |
discover | Optional discovery configuration (see Discovery). |
sudo | Optional sudo configuration for privilege escalation (see Sudo). |
insecure | Set to true to skip TLS verification. |
options | Provider-specific key-value options. |
Credentials
The simplest approach is to specify credentials directly on each connection. For larger inventories, you can define credentials once and reference them across assets, or pull them from an external vault.
Inline credentials
Specify credentials directly on a connection:
spec:
assets:
- name: web-server
connections:
- type: ssh
host: 192.168.1.10
credentials:
- type: password
user: admin
password: s3cretspec:
assets:
- name: web-server
connections:
- type: ssh
host: 192.168.1.10
credentials:
- user: ubuntu
private_key_path: ~/.ssh/id_rsaspec:
assets:
- name: web-server
connections:
- type: ssh
host: 192.168.1.10
credentials:
- user: ubuntu
private_key: <base64-encoded private key>To encode your key, run:
base64 -i ~/.ssh/id_rsaThe credential type is inferred automatically when you use password, private_key, or private_key_path. You don't need to set type explicitly in most cases.
SSH agent
Use the system SSH agent instead of storing keys:
credentials:
- type: ssh_agent
user: ubuntuReference credentials with secret_id
When multiple assets share the same credentials, define them once in spec.credentials and reference them by secret_id:
spec:
assets:
- name: web-01
connections:
- type: ssh
host: 10.0.0.1
credentials:
- secret_id: my-ssh-key
- name: web-02
connections:
- type: ssh
host: 10.0.0.2
credentials:
- secret_id: my-ssh-key
credentials:
my-ssh-key:
user: ubuntu
private_key_path: ~/.ssh/id_rsaEnvironment variables
Load a credential value from an environment variable:
spec:
credentials:
my-env-secret:
type: env
env: MY_SECRET_VARDynamic credentials with credential_query
For large or heterogeneous inventories, you can resolve credentials dynamically instead of listing a secret_id on every connection. Set spec.credential_query to an MQL expression. cnspec evaluates it once per asset, with mrn, name, labels, and platform available as query properties, and expects it to return an object such as { user, type, secret_id }:
spec:
credential_query: "return { user: 'auditor', type: 'ssh_agent' }"cnspec only falls back to credential_query for a connection that doesn't already specify its own credentials. To learn how to write the expression itself, read Write Effective MQL.
Credential types
| Type | Description |
|---|---|
password | Username and password. |
private_key | SSH private key (PEM-encoded, inline or loaded from a file). |
ssh_agent | System SSH agent forwarding. |
bearer | Bearer token for API authentication. |
json | JSON-encoded secret (for example, a cloud service account key file). |
pkcs12 | Certificate-based authentication (.p12, .pfx, or PEM combo file). |
env | Load the secret from an environment variable. |
aws_ec2_instance_connect | AWS EC2 Instance Connect. |
aws_ec2_ssm_session | AWS Systems Manager Session Manager. |
When you use private_key_path with a relative path, it resolves relative to the inventory file location, not your current working directory. For example, if your inventory is at /etc/mondoo/inventory.yml and contains private_key_path: ./keys/id_rsa, cnspec looks for /etc/mondoo/keys/id_rsa. Paths starting with ~/ expand to the current user's home directory. Absolute paths are used as-is.
Vault integration
Instead of storing secrets in the inventory file, you can use an external vault. Define the vault in spec.vault and reference secrets by their vault key:
spec:
assets:
- name: vsphere-env
connections:
- type: vsphere
host: 192.168.5.24
insecure: true
credentials:
- secret_id: vcenter/mondoo-read
discover:
targets:
- auto
vault:
name: my-vault
type: hashicorp-vault
options:
url: http://127.0.0.1:8200
token: XXXXXXXXSupported vault types
| Type | Description |
|---|---|
keyring | System keyring (macOS Keychain, GNOME Keyring, Windows Credential Manager). |
linux-kernel-keyring | Linux kernel keyring (persistent). |
encrypted-file | Local encrypted file. Options: path, password. |
hashicorp-vault | HashiCorp Vault server. Options: url, token. |
aws-secrets-manager | AWS Secrets Manager. Uses AWS environment credentials. |
aws-parameter-store | AWS Systems Manager Parameter Store. Uses AWS environment credentials. |
gcp-secret-manager | Google Cloud Secret Manager. Options: project-id. |
gcp-berglas | GCP Berglas. Options: project-id, kms-key-id, bucket-name. |
Configure a vault from the CLI
You can add vault configuration directly to an existing inventory file:
cnspec vault configure my-vault \
--type hashicorp-vault \
--option url=http://127.0.0.1:8200 \
--option token=XXXXXXXX \
--inventory-file inventory.ymlTo store a secret in the configured vault:
cnspec vault add-secret my-secret-id "secret-value" \
--inventory-file inventory.ymlDiscovery
Some connection types can automatically find and scan related assets, such as every EC2 instance in an AWS account or every container running on a host. Use the discover block to enable this:
spec:
assets:
- name: aws-account
connections:
- type: aws
discover:
targets:
- auto
options:
profile: productionspec:
assets:
- connections:
- type: local
discover:
targets:
- containerDiscovery targets are defined per provider; there's no universal list. auto (discover what the provider recommends by default) and all (discover everything the provider supports) are common conventions, but not every provider implements both, and many define additional targets specific to what they connect to, such as databases for postgresdb or host-machines for vsphere. Check the connection type's page under Supported Targets for the exact targets it accepts before relying on a target name.
Annotations
Add metadata to assets that appears in Mondoo App:
spec:
assets:
- name: prod-web
connections:
- type: ssh
host: 10.0.0.1
credentials:
- type: ssh_agent
user: ubuntu
annotations:
Owner: ops-team
Environment: productionYou can also pass annotations from the CLI. They apply to all assets in the inventory and are merged with any annotations defined in the file:
cnspec scan --inventory-file inventory.yml --annotation Environment=stagingPass --annotation multiple times to set more than one key:
cnspec scan --inventory-file inventory.yml \
--annotation Environment=staging \
--annotation Owner=ops-teamSudo
To run scans with elevated privileges over SSH, enable sudo on the connection:
connections:
- type: ssh
host: 10.0.0.1
credentials:
- type: ssh_agent
user: deploy
sudo:
active: true
user: rootInventory templates
Instead of hardcoding connection details, you can use templates to substitute environment variables at scan time. Use the getenv function to reference them:
spec:
assets:
- name: { { getenv "ASSET_NAME" } }
connections:
- type: ssh
host: { { getenv "TARGET_HOST" } }
credentials:
- user: { { getenv "SSH_USER" } }
private_key_path: { { getenv "SSH_KEY_PATH" } }Run the template with --inventory-template:
ASSET_NAME="web-01" TARGET_HOST="10.0.0.1" SSH_USER="ubuntu" SSH_KEY_PATH="~/.ssh/id_rsa" \
cnspec scan --inventory-template template.ymlTemplates are useful in CI/CD pipelines where connection details vary between environments.
Alternative inventory formats
Ansible inventory
cnspec can read Ansible inventory files in JSON format. Generate one with:
ansible-inventory --list > ansible-inventory.jsonThen scan using:
cnspec scan --inventory-file ansible-inventory.json --inventory-format-ansibleDomain list
A plain text file with one hostname per line:
# Production web servers
web-01.example.com
web-02.example.com
192.168.1.50:2222Scan with:
cnspec scan --inventory-file hosts.txt --inventory-format-domainlistExamples
Multi-cloud inventory
apiVersion: v1
kind: Inventory
metadata:
name: multi-cloud
spec:
assets:
- name: aws-production
connections:
- type: aws
options:
profile: prod-account
discover:
targets:
- auto
- name: gcp-project
connections:
- type: gcp
options:
project: my-gcp-project
discover:
targets:
- auto
- name: azure-tenant
connections:
- type: azure
credentials:
- type: pkcs12
private_key_path: ./azure-cert.pem
options:
client-id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
tenant-id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
discover:
targets:
- autoSSH fleet with shared credentials
apiVersion: v1
kind: Inventory
metadata:
name: ssh-fleet
spec:
assets:
- name: web-01
connections:
- type: ssh
host: 10.0.0.1
credentials:
- secret_id: fleet-key
- name: web-02
connections:
- type: ssh
host: 10.0.0.2
credentials:
- secret_id: fleet-key
- name: db-01
connections:
- type: ssh
host: 10.0.1.1
credentials:
- secret_id: fleet-key
credentials:
fleet-key:
user: ubuntu
private_key_path: ~/.ssh/fleet_id_rsaMicrosoft 365
apiVersion: v1
kind: Inventory
metadata:
name: m365-inventory
spec:
assets:
- connections:
- type: ms365
credentials:
- type: pkcs12
private_key_path: ./certificate.pem
options:
client-id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
tenant-id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
discover:
targets:
- autoKubernetes
apiVersion: v1
kind: Inventory
metadata:
name: k8s-inventory
spec:
assets:
- name: production-cluster
connections:
- type: k8s
options:
kubeconfig: ~/.kube/config
context: production
discover:
targets:
- autovSphere with HashiCorp Vault
apiVersion: v1
kind: Inventory
metadata:
name: vsphere-inventory
spec:
assets:
- name: vsphere
connections:
- type: vsphere
host: vcenter.example.com
insecure: true
credentials:
- secret_id: vcenter/admin
discover:
targets:
- host-machines
annotations:
Owner: infra-team
vault:
name: hcv
type: hashicorp-vault
options:
url: http://vault.internal:8200
token: s.xxxxxxxxxxxxxxxxxxxxxxxxNetwork device fleet
Network devices often need connector-specific values, such as a privileged exec (enable) password, that aren't credentials cnspec resolves through the credential store. Set those under the connection's options instead:
apiVersion: v1
kind: Inventory
metadata:
name: network-fleet
spec:
assets:
- name: core-switch-01
connections:
- type: nd-ssh
host: 10.10.0.1
credentials:
- user: admin
password: s3cret
options:
enable-password: en4blepw
- name: edge-router-01
connections:
- type: junos
host: 10.10.0.2
port: 830
credentials:
- secret_id: network-fleet-key
credentials:
network-fleet-key:
user: admin
private_key_path: ~/.ssh/network_id_rsaSome connectors accept authentication-related values, such as the network device connector's enable-password for privileged exec mode, as provider options rather than credentials. Options aren't resolved through secret_id or vault references, so treat any sensitive option value with the same care you'd give a plaintext secret. Check each device page under network device scanning for which fields are options versus credentials.
Combine a host scan with its local database
A self-managed database usually runs on a host cnspec already scans at the OS level, often as a registered service with its own mondoo.yml. You don't need to re-register the host or touch mondoo.yml to add the database. Drop an inventory file beside it that lists both the host and the database, and restart cnspec so it picks up the change.
1. Find the configuration file
A host running cnspec as a service almost always uses the system-wide mondoo.yml path:
| OS | Path |
|---|---|
| Linux | /etc/opt/mondoo/mondoo.yml |
| Windows | C:\ProgramData\Mondoo\mondoo.yml |
For the full list, including per-user paths, read Where cnspec looks for the file. If you're not sure which one a given host actually loaded, run cnspec status; it names the file.
2. Create inventory.yml beside it
Name the file inventory.yml and place it in the same directory as mondoo.yml:
/etc/opt/mondoo/
├── mondoo.yml
└── inventory.ymlList two assets: a local connection for the host cnspec is already scanning, and a database connection pointed at localhost for the service running on it.
List both assets. If the file defines only the database, cnspec drops the existing host scan entirely rather than adding to it, because an inventory file with any assets in it replaces the default local target instead of extending it.
apiVersion: v1
kind: Inventory
metadata:
name: host-with-local-database
spec:
assets:
- name: db-host-os
connections:
- type: local
- name: db-host-postgres
connections:
- type: postgresdb
host: localhost
credentials:
- user: auditor
password: s3cretThe same pattern works for any self-managed database type. For a Windows host running SQL Server, swap the second asset's connection type and credentials:
apiVersion: v1
kind: Inventory
metadata:
name: host-with-local-database
spec:
assets:
- name: db-host-os
connections:
- type: local
- name: db-host-sqlserver
connections:
- type: mssql
host: localhost
credentials:
- user: auditor
password: s3cret3. Restart cnspec
cnspec reads mondoo.yml and the inventory file once, when the service starts, and keeps that in memory for as long as it runs. It does not watch the file for changes, so a service that's already running won't notice a new or edited inventory.yml on its own. Restart it to pick up the change:
sudo systemctl restart cnspecRestart-Service -Name mondooThe next scan cycle reports on both assets: the host, as it already did, and the database.
To check the file before restarting the service, test it directly. This scans exactly what the file defines without touching the running service, so you can confirm both assets connect and fix credentials before the change goes live:
cnspec scan --inventory-file /etc/opt/mondoo/inventory.ymlcnspec also auto-discovers this file when you run cnspec scan ad hoc, but only to enrich the target you give it, for example by copying id_detector settings, not to add its other assets. If you run cnspec scan local (with no --inventory-file flag) on a host that has this inventory.yml on disk, cnspec scans only local and drops the database asset. Pass --inventory-file explicitly, as in the test above, to scan everything the file defines outside of the service.
Database fleet
Beyond a single host, an inventory file also lets you list many separate database servers. Set discover.targets to have cnspec find every database on an instance, and share one credential across a fleet with secret_id:
apiVersion: v1
kind: Inventory
metadata:
name: database-fleet
spec:
assets:
- name: pg-primary
connections:
- type: postgresdb
host: 10.20.0.1
credentials:
- secret_id: db-fleet-key
discover:
targets:
- all
- name: mysql-primary
connections:
- type: mysqldb
host: 10.20.0.2
credentials:
- secret_id: db-fleet-key
credentials:
db-fleet-key:
user: auditor
password: s3cretLearn more
- To explore a single asset interactively before scanning your fleet, read Query Your Infrastructure.
- To understand the policies cnspec runs during a scan, read About Policies.
- To control the format of scan results, read Report Results.
- To scan network devices such as Cisco, Juniper, and Palo Alto individually or as a fleet, read the network device scanning overview.
- To scan databases such as PostgreSQL, MySQL, and SQL Server individually or as a fleet, read the database scanning overview.