Overview
Telemetry resources (logs, traces, metrics, meter metrics) control who can query telemetry data in SigNoz. They support a single relation, read, scoped by a telemetry selector. The three assignable managed roles (signoz-admin, signoz-editor, signoz-viewer) have unrestricted (*) read access on every telemetry resource; signoz-anonymous has none. Restrictions apply only through custom roles.
This page covers how telemetry transactions are written and evaluated. For the per-resource transaction tables and the selector format, see the Transactions Reference.
Selector Keys
Telemetry transactions can be scoped by one of three keys:
| Key | Value | Scopes access to |
|---|---|---|
signoz.workspace.key.id | Ingestion key ID, shown on the Ingestion Settings page | Telemetry sent with that ingestion key |
resource.service.name | Service name | Telemetry of that service |
resource.deployment.environment.name | Deployment environment name | Telemetry of that environment |
- The service and environment keys must be written with the
resource.prefix, both in the selector and in the query filter. Unprefixedservice.nameanddeployment.environment.nameare not recognized. - The ingestion key may be written unprefixed or as
resource.signoz.workspace.key.id; both are treated the same. - Key scoping is supported only for
builder_queryselectors. Key-scopedpromqlorclickhouse_sqlselectors are rejected. - Values starting with
$(dashboard variables) are rejected in selectors. Use the resolved value instead. - A bare query type is canonicalized on save:
builder_queryis stored asbuilder_query/*.
Transaction Evaluation
Broader transactions implicitly cover narrower requests within the same query type. Each selector in the list below covers every selector above it:
builder_query/<key>/<value>(one specific value of a key, for examplebuilder_query/resource.service.name/checkout)builder_query/<key>/*(any value of that key)builder_query/*(all builder queries on the signal)*(everything on the signal)
The same order applies to each of the three keys. A transaction on one key does not cover another key: builder_query/resource.service.name/* does not cover builder_query/resource.deployment.environment.name/prod.
Transactions never widen across query types: a builder_query transaction does not satisfy a PromQL query, and vice versa.
How Queries Are Authorized
Every query in SigNoz, whether it runs in an explorer, a dashboard panel, an alert evaluation preview, or through the API, is checked against the caller's telemetry transactions. The transactions a query requires depend on its query type:
| Query | Transactions Required |
|---|---|
| Builder query on a signal | read on that signal's telemetry resource, with a selector derived from the query's filter |
| PromQL query | metrics:read with selector promql/* |
| ClickHouse SQL query | read with selector clickhouse_sql/* on all of logs, traces, metrics, and meter-metrics |
| Formulas, joins, and trace operators | No transaction of their own; the queries they reference are checked |
For builder queries, the required selector is derived from the query's filter expression:
- Only top-level
=andINconditions on a selector key count. Conditions combined withOR, negated withNOT, or written with!=are ignored, and so are conditions on any other field. - One granted condition is enough. When the filter has conditions on more than one selector key, the query is allowed if the caller holds a transaction for any one of them. The remaining conditions only narrow the rows returned.
- A single
INlist needs every value granted.resource.service.name IN ('checkout', 'frontend')is allowed only when both values are granted, whenbuilder_query/resource.service.name/*is granted, or when another condition in the filter is granted. - Two or more multi-value
INlists need a wildcard. A filter with multi-value lists on two keys is allowed only bybuilder_query/<key>/*on one of those keys, or by a broader selector.
Query Behavior with Scoped Transactions
Scoped by ingestion key
For a role granted builder_query/signoz.workspace.key.id/key-a on a signal:
| Query filter | Result |
|---|---|
signoz.workspace.key.id = 'key-a' | Allowed |
signoz.workspace.key.id IN ('key-a') | Allowed |
signoz.workspace.key.id = 'key-a' AND severity_text = 'ERROR' | Allowed |
| No filter on the key | Denied |
signoz.workspace.key.id = 'key-b' | Denied |
signoz.workspace.key.id IN ('key-a', 'key-b') | Denied (needs the key-b transaction too) |
signoz.workspace.key.id = 'key-a' OR severity_text = 'ERROR' | Denied (the key is not pinned at the top level) |
NOT signoz.workspace.key.id = 'key-a' or signoz.workspace.key.id != 'key-b' | Denied |
Scoped by service
For a role granted builder_query/resource.service.name/checkout on a signal:
| Query filter | Result |
|---|---|
resource.service.name = 'checkout' | Allowed |
resource.service.name = 'checkout' AND resource.deployment.environment.name = 'prod' | Allowed (the service condition is granted) |
resource.service.name IN ('checkout') AND signoz.workspace.key.id IN ('key-a', 'key-b') | Allowed (the service condition is granted) |
service.name = 'checkout' | Denied (the key has no resource. prefix) |
resource.service.name = 'frontend' | Denied |
resource.deployment.environment.name = 'prod' | Denied (no transaction on the environment key) |
resource.service.name IN ('checkout', 'frontend') AND resource.deployment.environment.name = 'prod' | Denied (needs the frontend transaction too) |
resource.service.name IN ('checkout', 'frontend') AND signoz.workspace.key.id IN ('key-a', 'key-b') | Denied (two multi-value lists need a builder_query/<key>/* transaction) |
A role scoped by resource.deployment.environment.name behaves the same way with the environment key.
A denied query returns a 403 "not authorized" error. The error names the conditions that were checked, for example builder_query/resource.service.name = 'frontend', or builder_query/* when the filter has no usable condition.
Enforcement Behavior
- The transaction is a gate, not a row filter. SigNoz admits or rejects the query as written; it does not inject filters. The query's own filter is what narrows the rows returned.
- Dashboard variables are substituted before the check. A panel filtering
resource.service.name = $serviceis checked against the resolved value. - A scoped role cannot run PromQL or ClickHouse SQL queries. Allowing them requires
promql/*(on metrics) orclickhouse_sql/*(on logs, traces, metrics, and meter metrics) selectors, which grant access to all data for that query type. - Roles are additive. A principal receives the union of transactions from all assigned roles. To restrict a user, a scoped custom role must replace their managed role, not sit alongside it.
Next Steps
- Transactions Reference — Per-resource transaction tables and selector formats
- Scope Telemetry Access by Ingestion Key — Step-by-step walkthrough for ingestion keys
- Scope Telemetry Access by Service and Environment — Step-by-step walkthrough for services and environments
- Authorization Overview — How role-based access control works in SigNoz