checkfleet

Permissions

checkfleet permissions

What each check needs on the system it watches, and what it does not. Derived from the queries and endpoints the modules actually issue.

checkfleet perms --config checkfleet.yml prints the subset below for the modules you actually run, in text, markdown or JSON — send that to whoever owns the system instead of this whole page.

Every module is read-only: no check writes to the system it inspects. Credentials always come from the environment (*_env, ${VAR}), never from the config file.

Needs no credential (17)

These reach the target over the network and read what it already exposes.

cassandra

Speaks the CQL native handshake (OPTIONS/STARTUP) and stops at READY or AUTHENTICATE.

Not needed: No credential and no keyspace access: reaching the AUTHENTICATE frame already proves the node accepts CQL.

certs

Opens a TLS connection to the port and reads the presented certificate. No credential.

Not needed: No account, no API access. The chain is not validated (the expiry is read even from an untrusted chain), so no trust store changes either.

dns

Sends DNS queries to the configured resolvers. No credential.

Not needed: No zone transfer (AXFR) and no write: only ordinary lookups.

grpc

Calls the standard gRPC Health Checking service over HTTP/2.

Not needed: No access to any application RPC.

haproxy

GETs the stats page in CSV form (/stats;csv), which must be enabled in haproxy.cfg.

Not needed: No admin access to the stats socket: the check reads, it never enables or disables a server.

The exact policy depends on how the target is deployed, so treat the above as guidance rather than a recipe.

http

Issues the configured request (GET by default) to the URL.

Not needed: Whatever the endpoint itself requires is the operator’s choice; checkfleet asks for no privilege of its own.

ingest

RTMP or SRT handshake only — it stops before publishing a stream.

Not needed: No stream key and no publish permission: the check answers ‘can a streamer connect’, not ‘can it publish’.

keycloak

Reads the health endpoint and the public OIDC discovery document of each realm (/realms/<realm>/.well-known/openid-configuration).

Not needed: No admin API access, no client secret, no service account: both endpoints are public by design.

memcached

Sends the text-protocol stats command.

Not needed: No key is read or written. If SASL is enabled the check needs an account that may run stats.

nats

Reads the HTTP monitoring endpoints /varz and /jsz?meta=1 on the monitoring port (8222 by default).

Not needed: No NATS client credential: the monitoring port is separate from the client port, and no subject is subscribed or published.

ntp

One SNTP request per server. No credential.

Not needed: The local clock is never set — checkfleet reports the offset, it does not correct it.

patroni

GETs the Patroni REST API /cluster endpoint.

Not needed: No database credential, and none of Patroni’s write endpoints (switchover, restart, reinitialise) is ever called.

The exact policy depends on how the target is deployed, so treat the above as guidance rather than a recipe.

smtp

Connects, reads the greeting, sends EHLO and optionally negotiates STARTTLS.

Not needed: It never authenticates and never sends mail — no mailbox, no relay permission.

stream

HTTP GET of the HLS/DASH manifest, and of the variant playlists it references.

Not needed: No publishing credential: the check reads the delivery side, never the ingest side.

tcp

Opens a TCP connection (optionally TLS) and optionally reads the banner. No credential.

Not needed: Nothing is sent to the service beyond the connection itself.

tls

TLS handshake against the target. No credential.

Not needed: No account and no server-side configuration.

vault

Reads /v1/sys/seal-status and /v1/sys/health, which Vault serves unauthenticated.

Not needed: No token is required. One may be configured, and if set it is sent, but the two endpoints used need no policy — no secret engine, no read of any path.

The exact policy depends on how the target is deployed, so treat the above as guidance rather than a recipe.

Needs an account (12)

clickhouse

Calls /ping, runs SELECT version() and reads system.replicas.

CREATE USER checkfleet IDENTIFIED BY '<from your secret store>';
GRANT SELECT ON system.replicas TO checkfleet;

Not needed: No access to any user database or table, and no SYSTEM privileges (no restart, no replica manipulation).

consul

Reads /v1/status/leader, /v1/status/peers, /v1/health/state/<state> and any configured /v1/kv/<key>. With ACLs on, a token whose policy grants read on those.

# consul acl policy create -name checkfleet -rules -
agent_prefix "" { policy = "read" }
node_prefix  "" { policy = "read" }
service_prefix "" { policy = "read" }
key_prefix "<only the keys in kv_keys>" { policy = "read" }

Not needed: No write on anything, no operator policy, and key read scoped to the keys you actually configured rather than the whole KV tree.

The exact policy depends on how the target is deployed, so treat the above as guidance rather than a recipe.

elasticsearch

GETs /_cluster/health and /_cat/allocation. The built-in cluster privilege monitor covers both.

PUT /_security/role/checkfleet {"cluster":["monitor"]}

Not needed: No index privilege at all: no document is read, and no index is created, written or deleted.

etcd

Calls /health, /v3/maintenance/status and /v3/cluster/member/list over the JSON gateway. With auth enabled it first calls /v3/auth/authenticate.

etcdctl role add checkfleet
etcdctl user add checkfleet
etcdctl user grant-role checkfleet checkfleet

Not needed: No key read or write: the endpoints used report cluster state, not data. Grant no key range to the role.

The exact policy depends on how the target is deployed, so treat the above as guidance rather than a recipe.

kafka

Reads cluster metadata and, when consumer groups are configured, their committed offsets and lag.

kafka-acls --add --allow-principal User:checkfleet --operation Describe --cluster
kafka-acls --add --allow-principal User:checkfleet --operation Describe --topic '*'
kafka-acls --add --allow-principal User:checkfleet --operation Describe --group '*'

Not needed: No Read or Write on any topic: the check never consumes or produces a message, it reads metadata and offsets.

ldap

Binds (anonymously, or with the configured account) and optionally runs one search under base_dn.

Not needed: No write of any kind, and read scoped to the subtree you point it at. When no sanity search is configured, the bind alone is enough and the account needs no read at all.

The exact policy depends on how the target is deployed, so treat the above as guidance rather than a recipe.

mongodb

Runs the serverStatus and replSetGetStatus admin commands. The built-in clusterMonitor role covers both.

db.getSiblingDB("admin").createUser({user:"checkfleet", pwd:"<from your secret store>", roles:[{role:"clusterMonitor", db:"admin"}]})

Not needed: No read on any application database, no clusterManager, no write. clusterMonitor cannot see document data.

mysql

Runs SELECT VERSION(), SELECT @@global.read_only, SHOW GLOBAL STATUS, SHOW GLOBAL VARIABLES and, on a replica, SHOW REPLICA STATUS.

CREATE USER 'checkfleet'@'%' IDENTIFIED BY '<from your secret store>';
GRANT PROCESS, REPLICATION CLIENT ON *.* TO 'checkfleet'@'%';

Not needed: No SELECT on any schema, no SUPER, no RELOAD, no write. REPLICATION CLIENT grants the status view only — not the ability to change replication.

postgres

Connects to one database and reads server statistics: pg_is_in_recovery(), pg_database, pg_stat_activity, pg_replication_slots, pg_stat_replication and max_connections. The built-in pg_monitor role covers all of it. Without it the check still connects, but a non-superuser sees the replication views empty — so the replica-lag and inactive-slot findings would report nothing wrong on a primary that has a problem.

CREATE ROLE checkfleet LOGIN PASSWORD '<from your secret store>';
GRANT pg_monitor TO checkfleet;
GRANT CONNECT ON DATABASE postgres TO checkfleet;

Not needed: No SELECT on any user table, no schema access, no SUPERUSER, no write of any kind. pg_monitor is read-only by construction.

The exact policy depends on how the target is deployed, so treat the above as guidance rather than a recipe.

rabbitmq

GETs the management API /api/overview, /api/nodes and /api/queues. The monitoring tag is exactly this level.

rabbitmqctl add_user checkfleet '<from your secret store>'
rabbitmqctl set_user_tags checkfleet monitoring

Not needed: No administrator or management tag, and no configure/write/read permission on any vhost: queues are counted, never consumed from.

redis

Sends INFO. On Redis 6+ an ACL user restricted to that one command is enough.

ACL SETUSER checkfleet on >'<from your secret store>' ~ -@all +info

Not needed: No keyspace access (~ matches no key), no CONFIG, no KEYS, no administrative or write command.

s3

HEADs the bucket and, when a sentinel object is configured, reads its metadata.

{"Effect":"Allow","Action":["s3:ListBucket"],"Resource":"arn:aws:s3:::<bucket>"}
{"Effect":"Allow","Action":["s3:GetObject"],"Resource":"arn:aws:s3:::<bucket>/<sentinel object>"}

Not needed: No s3:PutObject, no s3:DeleteObject, and GetObject scoped to the single sentinel key rather than the bucket.