Databases

Secure ClickHouse Cloud with cnspec

Scan ClickHouse Cloud organizations and services against security and compliance best practices with cnspec.

Scan your ClickHouse Cloud organization to find security risks before they become incidents. cnspec evaluates which sources can reach each service, encryption at rest, private endpoint coverage, API key expiration and roles, organization membership, and other ClickHouse Cloud controls.

cnspec audits the ClickHouse Cloud control plane: services, network access, API keys, and organization members. To audit the database inside a service, its users, roles, and grants, point the clickhousedb provider at the service endpoint instead.

If you're new to cnspec, start with the Quickstart. For an overview of every database cnspec can scan, see the database scanning overview.

Prerequisites

To scan ClickHouse Cloud with cnspec, you must have:

Authenticate

cnspec connects to ClickHouse Cloud using an organization API key, which is a key ID paired with a secret. To create one:

  1. Log in to the ClickHouse Cloud console.
  2. Go to your organization's API keys page.
  3. Create a key, give it read access, and copy both the key ID and the secret. ClickHouse shows the secret only once.
  4. Copy your organization ID from the console URL or the organization's settings.

A key with read access is enough. cnspec never writes to the control plane.

Pass the organization ID, key ID, and secret on the command line. Use --ask-secret to be prompted rather than putting the secret in your shell history:

cnspec shell clickhousecloud --organization-id ORG_ID --api-key KEY_ID --ask-secret

The ClickHouse Cloud API never returns a key's secret, so cnspec can't expose one in scan results. API keys report only their ID, name, state, roles, and expiration.

Connection options

OptionDescription
--organization-idClickHouse Cloud organization ID
--api-keyClickHouse Cloud API key ID
--api-secretClickHouse Cloud API key secret
--ask-secretPrompt for the API key secret instead of passing it as a flag
--api-urlOverride the API base URL (default https://api.clickhouse.cloud/v1)

Verify with a quick ClickHouse Cloud check

Confirm that cnspec can reach your organization by running a single query:

cnspec shell clickhousecloud --organization-id ORG_ID --api-key KEY_ID --ask-secret \
  -c "clickhousecloud.organization { name }"
clickhousecloud.organization: {
  name: "Acme Inc"
}

If clickhousecloud.organization.services comes back empty, the API key lacks read access to services. Grant it, or use a more privileged key, and try again.

Scan ClickHouse Cloud

cnspec scan clickhousecloud --organization-id ORG_ID --api-key KEY_ID --ask-secret

When a scan completes, cnspec prints a summary of all the checks it ran, grouped by policy, along with a risk score from 0 (no risk) to 100 (highest risk). Failed checks include remediation guidance to help you fix issues. To learn more about reading scan results, read Understand cnspec Results.

Mondoo doesn't yet ship an out-of-the-box ClickHouse Cloud policy, so use the checks below as a starting point and create your own policies to meet your specific requirements.

Explore and test checks interactively

Open a cnspec shell to discover resources and try out checks:

cnspec shell clickhousecloud --organization-id ORG_ID --api-key KEY_ID --ask-secret

List all services

cnspec> clickhousecloud.organization.services { name region cloudProvider state tier }
clickhousecloud.organization.services: [
  0: {
    name: "analytics-prod"
    region: "eu-central-1"
    cloudProvider: "aws"
    state: "running"
    tier: "production"
  }
]

Inspect a service's IP allow list

cnspec> clickhousecloud.organization.services { name openToAllIps ipAccessList { source description } }

List a service's connection endpoints

cnspec> clickhousecloud.organization.services { name endpoints { protocol host port } }

List API keys

cnspec> clickhousecloud.organization.apiKeys { name state roles neverExpires expiresAt usedAt }
clickhousecloud.organization.apiKeys: [
  0: {
    name: "cnspec"
    state: "enabled"
    roles: ["Admin"]
    neverExpires: false
  }
]

List organization members

cnspec> clickhousecloud.organization.members { email name role }

Example security checks

Ensure no service is reachable from any IP address

cnspec> clickhousecloud.organization.services.none(openToAllIps == true)
[ok] value: true

Ensure no allow-list entry opens a service to the whole internet

openToAllIps covers the common case. Testing the entries themselves also catches the IPv6 wildcard:

cnspec> clickhousecloud.organization.services.all(ipAccessList.none(source == "0.0.0.0/0" || source == "::/0"))
[ok] value: true

Ensure services encrypt data at rest with a customer-managed key

cnspec> clickhousecloud.organization.services.all(hasTransparentDataEncryption == true)
[ok] value: true

Scoping this to production with .where(tier == "production") looks tempting, but tier is empty on scale-tier organizations. On one of those the filter matches nothing and the check passes without evaluating a single service. Test every service, or filter on something the organization actually populates.

Ensure services are reachable over a private endpoint

A service with private endpoints attached doesn't have to accept connections across the public internet:

cnspec> clickhousecloud.organization.services.all(hasPrivateEndpoints == true)
[ok] value: true

Ensure no API key lives forever

cnspec> clickhousecloud.organization.apiKeys.none(neverExpires == true)
[ok] value: true

Ensure no API key has gone unused

A key with a null usedAt was never used and keeps working until someone revokes it:

cnspec> clickhousecloud.organization.apiKeys.where(state == "enabled").all(usedAt != null)
[ok] value: true

Ensure an expired key is also disabled

A key that never expires has a null expiresAt, so exclude those before comparing:

cnspec> clickhousecloud.organization.apiKeys.where(state == "enabled" && neverExpires == false).none(expiresAt < time.now)
[ok] value: true

Review which API keys hold the Admin role

An Admin key can change the organization, not just read it:

cnspec> clickhousecloud.organization.apiKeys.where(roles.contains("Admin")) { name state usedAt }

Review who administers the organization

cnspec> clickhousecloud.organization.members.where(role == "admin") { email name }

Review the protocols each service accepts

Every endpoint is a way in. A service that publishes a MySQL-protocol endpoint alongside its native one has a second surface to account for:

cnspec> clickhousecloud.organization.services { name endpoints { protocol host port } }

Learn more

On this page