Admin API¶
The operator uses the admin API to inspect a running server and to reload its policies. It is off by default and has its own port.
Example¶
Turn it on in the server config. Add admin.tls to serve HTTPS.
admin:
enabled: true
listen: ":9091"
# Demo value. Use your own token.
token: "demo-admin-token-change-me"
This call reloads the policy directory. It also works when policies.reload is false.
curl -s -X POST http://localhost:9091/admin/reload \
-H "Authorization: Bearer demo-admin-token-change-me"
Routes¶
Every route needs the header Authorization: Bearer <token> with the value of admin.token.
| Method | Path | What it does | Response |
|---|---|---|---|
GET | /admin/policies | Lists the loaded policies. | version, digest, warnings, and policies by policy kind with name, priority, enforcement |
GET | /admin/datasources | Shows the state of each data source. | datasources with name, type, healthy, last_check, schema_pulled_at. last_error, latency_ms and status only when set |
GET | /admin/subjects/explain | Shows which policies apply to a subject. | See Explain |
POST | /admin/reload | Loads the policy directory again. | ok, digest |
GET | /admin/audit/tail | Returns the newest audit records. | One JSON record per line |
POST | /admin/synthetic/{name}/build | Starts a build of a synthetic data source. | 202 with name, build_id, state, already_running. See Synthetic builds |
GET | /admin/synthetic/{name} | Shows the state, the builds and the report of a synthetic data source. | name, source, status, spec_hash, current, builds, report |
GET | /admin/approvals | Lists the pending approvals, without tokens. | pending, count. 501 when approvals are off |
GET | /admin/healthz | Reports the health of the server. | status, version, config_digest, config_version. 503 when a data source is unhealthy |
GET | /admin/version | Reports the build. | version, commit, build_time, go |
GET | /metrics | Serves the metrics. | Prometheus text |
Every response has an X-Admin-Request-Id header.
Explain¶
| Parameter | Meaning |
|---|---|
user | Subject id. Required. |
table | Table as catalog.schema.table. Required. Sluice does not add a missing catalog or schema. A policy that names them does not match a shorter name. |
issuer | Issuer of the subject. |
groups | Groups, separated by commas. |
claims | One key=value pair. Repeat the parameter for more. |
simulated_sql | A statement. Sluice explains its tables and table together. |
curl -s "http://localhost:9091/admin/subjects/explain?user=alice&groups=analysts&claims=tenantId=acme&table=shop.main.customers" \
-H "Authorization: Bearer demo-admin-token-change-me"
{
"subject": "alice",
"resource": "shop.main.customers",
"matched": [
{
"kind": "SqlAccessPolicy",
"name": "allow-analysts",
"priority": 100
},
{
"kind": "RowFilterPolicy",
"name": "filter-tenant",
"priority": 80
},
{
"kind": "ColumnMaskPolicy",
"name": "mask-email",
"priority": 50
}
],
"rejected": null,
"effective": {
"decision": "allow",
"row_filters": ["shop.main.customers"],
"column_masks": [
{
"column": "shop.main.customers.email",
"mask_type": "null",
"policy": "mask-email"
}
]
}
}
sluice policy explain --json prints the same shape. When no policy allows the table, decision is deny and rejected names the reason.
Audit tail¶
/admin/audit/tail?n=1 returns the newest record, here the record of the explain call:
curl -s "http://localhost:9091/admin/audit/tail?n=1" \
-H "Authorization: Bearer demo-admin-token-change-me"
{
"timestamp": "<time>",
"event_type": "admin-action",
"query_id": "<query-id>",
"subject": {
"id": "alice",
"groups": ["analysts"]
},
"origin": "admin",
"tables": ["shop.main.customers"],
"catalogs": ["shop"],
"decision": "allow",
"sluice_version": "<version>",
"message": "policy explain",
"prior_hash": "<hash>",
"hash": "<hash>"
}
n is 100 by default and at most 1000. The oldest record comes first. Sluice reads rotated files too.
Synthetic builds¶
POST /admin/synthetic/{name}/build answers at once. The build runs in the server and replaces the snapshot when it succeeds. See Synthetic data.
- A second call during a build returns the running build with
already_running: true. A retry is harmless. statusisnot_built,readyorstale.GET /admin/datasourcesshows it too.buildslists only the builds of this server process.currentandreportarenullwhen no snapshot exists.currentandreportshow the build that the server serves. Aftersluice synth build, the server serves the old snapshot until a restart or the next server build.GETshows that old build.- An unknown name, or a data source that is not synthetic, gives 404 with an empty body.
- Without a synthetic data source, both routes give 501.
- With
audit.failClosed, a build whose start record the audit log does not take gives 503ERR_AUDIT_UNAVAILABLE.
Limits¶
- Set
admin.tokenin the server config or withSLUICE_ADMIN__TOKEN. See Server config. - With an empty token, every route is open. Sluice logs a warning at start.
- A wrong token gives 401
ERR_UNAUTHORIZEDand aWWW-Authenticateheader. - A missing
userortable, ornbelow 1, gives 400ERR_SYNTAX. - A failed reload gives 400
ERR_POLICY_INVALIDorERR_CONFIG_INVALID. The old policies stay active.