Security
Security Model
Prometheus Proxy is designed to be firewall-friendly:
- The agent initiates an outbound gRPC connection to the proxy
- No inbound ports need to be opened on the firewall
- Agent connections can be authenticated with an optional pre-shared token — optionally scoped to per-agent identities — and/or mutual TLS
- Stale agent connections are automatically cleaned up
The agent gRPC port is unauthenticated by default
With neither a pre-shared agent token nor mutual TLS configured, any process that can reach the
agent port (default 50051) can register as an agent. Set a token (below), require mutual TLS,
and/or restrict the port to trusted networks. The proxy logs a startup warning when the agent
port is left unauthenticated.
TLS Encryption
Agents connect to the proxy using gRPC, which supports TLS with or without mutual authentication.
| Mode | Proxy Needs | Agent Needs |
|---|---|---|
| No TLS | Nothing | Nothing |
| TLS (server only) | Server cert + key | CA cert (trust store) |
| Mutual TLS | Server cert + key + CA cert | Client cert + key + CA cert |
See TLS Setup for detailed configuration instructions.
Agent Authentication (Pre-Shared Token)
By default the proxy accepts agent gRPC connections with no application-level authentication. Set a shared pre-shared token so the proxy rejects agents that do not present it:
| Side | CLI | Env Var | Config |
|---|---|---|---|
| Proxy | --agent_token |
AGENT_TOKEN |
proxy.agentToken |
| Agent | --agent_token |
AGENT_TOKEN |
agent.agentToken |
Both sides must use the same value. When set, the agent attaches the token as a gRPC metadata
header on every call and the proxy rejects any call with a missing or mismatched token
(UNAUTHENTICATED). When the token is empty (the default), the open behavior is preserved and the
proxy logs a startup warning — unless mutual TLS is configured, which already authenticates agents.
The token is never logged.
# Proxy requiring a token
java -jar prometheus-proxy.jar --agent_token "$AGENT_TOKEN"
# Agent presenting the token
java -jar prometheus-agent.jar --config myconfig.conf --agent_token "$AGENT_TOKEN"
Token vs. mutual TLS
A pre-shared token is a lightweight, app-level control that authenticates that a peer may connect. Mutual TLS additionally encrypts the channel and verifies a certificate identity. They can be combined; for production, prefer mutual TLS and/or restrict the agent port to trusted networks.
Per-Agent Identities and Path Authorization
A single shared agentToken authenticates agents but cannot tell them apart: any agent holding the
token can register any path, including one already served by another agent. Define named
identities under proxy.auth, each with its own token and a list of allowed path glob patterns, to
scope what each agent may register:
proxy {
auth = [
{ name = team-a, token = "team-a-token", paths = ["team_a_*"] }
{ name = team-b, token = "team-b-token", paths = ["team_b_*"] }
{ name = infra, token = "infra-token", paths = [] } // empty paths = may register any path
]
}
Each agent presents its identity's token the usual way (--agent_token, AGENT_TOKEN, or
agent.agentToken) — no agent-side change is needed. The proxy resolves the token to an identity and
enforces, on every path registration, that the requested path matches one of the identity's patterns.
| Condition | Result |
|---|---|
| Unknown token | Connection rejected with UNAUTHENTICATED |
| Path matches a pattern | Registration succeeds |
| Path matches no pattern | Registration fails with a "not authorized" reason |
Empty paths list |
Identity may register any path (allow-all) |
Patterns are single-segment globs: * matches any run of characters and ? matches exactly one
(e.g. team_a_*). Because authorization is per-identity-per-path,
consolidated mode still works as long as each participating
agent's identity permits the shared path.
Config-file only
proxy.auth is a list of objects, so it can only be set in a config file — there is no
equivalent CLI flag or environment variable, and the -D property override (parsed as Java
properties) cannot express a list. Identity names must be unique and tokens non-empty; the proxy
fails fast at startup otherwise.
Migrating from a shared token
Setting proxy.auth does not disable a legacy proxy.agentToken. When both are present, the
shared token is honored as an additional allow-all identity (the proxy logs a warning that it is
active), so you can adopt per-agent identities incrementally:
- Add a
proxy.authentry per agent while leavingproxy.agentTokenin place — existing agents keep connecting with the shared token. - Move each agent onto its own identity token, one at a time.
- Once every agent presents an identity token, remove
proxy.agentTokento close the shared allow-all path.
Auth Header Forwarding
When Prometheus scrape configurations include basic_auth or bearer_token, the proxy forwards
the Authorization header to the agent over the gRPC channel. The agent then includes this
header when fetching metrics from the target endpoint.
scrape_configs:
# Bearer token authentication
- job_name: 'app1'
metrics_path: '/app1_metrics'
bearer_token: 'eyJhbGciOiJIUzI1NiIs...'
static_configs:
- targets: ['proxy-host.example.com:8080']
# Basic auth
- job_name: 'app2'
metrics_path: '/app2_metrics'
basic_auth:
username: 'user'
password: 's3cr3t'
static_configs:
- targets: ['proxy-host.example.com:8080']
# No auth
- job_name: 'app3'
metrics_path: '/app3_metrics'
static_configs:
- targets: ['proxy-host.example.com:8080']
Credentials transmitted in plaintext without TLS
Without TLS, the Authorization header is transmitted in plaintext between the proxy
and agent. The proxy logs a warning on the first request that includes an
Authorization header when TLS is not enabled.
Always enable TLS when forwarding authentication headers.
When Prometheus scrape configs include basic_auth or bearer_token,
the proxy forwards the Authorization header to the agent over gRPC.
Without TLS, credentials are transmitted in plaintext!
Protect forwarded credentials with TLS:
java -jar prometheus-proxy.jar \
--cert /path/to/server.crt \
--key /path/to/server.key
java -jar prometheus-agent.jar \
--config myconfig.conf \
--trust /path/to/ca.crt
Scraping HTTPS Endpoints
For HTTPS scrape targets signed by a custom or private CA (e.g. an internal corporate CA), point the agent at a trust store containing that CA so certificates are still validated:
Trust a custom or private CA for HTTPS scrape targets (validation stays enabled):
Via CLI:
java -jar prometheus-agent.jar \
--https_truststore /etc/agent/truststore.jks \
--https_truststore_password changeit \
--config myconfig.conf
Via environment variables:
HTTPS_TRUST_STORE_PATH=/etc/agent/truststore.jks
HTTPS_TRUST_STORE_PASSWORD=changeit
Via config file:
agent.http.trustStorePath = "/etc/agent/truststore.jks"
agent.http.trustStorePassword = "changeit"
An empty path uses the JDK default trust store. The trust store is process-wide — it applies
to every HTTPS target the agent scrapes, and it is ignored when trust_all_x509 is enabled.
As a last resort, you can disable SSL verification entirely:
Disable SSL verification for HTTPS endpoints (development only!):
Via CLI:
java -jar prometheus-agent.jar --trust_all_x509 --config myconfig.conf
Via environment variable:
TRUST_ALL_X509_CERTIFICATES=true
Via config file:
agent.http.enableTrustAllX509Certificates = true
Development only
Only use trust_all_x509 in development or testing environments: it disables certificate
validation for every HTTPS target and takes precedence over the trust store. In
production, configure a trust store (or properly trusted certificates) for your metrics
endpoints instead.