Security events
Send security events to your SIEM with OpenTelemetry, and what the Data API offers.
Security teams, BI and management get the gateway's data through interfaces, never through its database. The plan and the reasons are in data-access.md. What exists today:
- Security events for your SIEM. The gateway and admin API log security events under the category
Ume.LlmGateway.Securitywith stable event names:gateway.auth.failed,gateway.pii.action,gateway.content.flagged(the content guard; categories only, never text),gateway.request.refused,admin.change,admin.signin,admin.signout,admin.session.extended,admin.access.deniedandadmin.data.read(the table is in data-access.md). SetOTEL_EXPORTER_OTLP_ENDPOINTon both services and route that category to your SIEM with an OpenTelemetry Collector.deploy/otel/collector-siem.example.yamlsends it to syslog (RFC 5424), with Splunk, Elastic and Sentinel alternatives. - Refused keys are recorded. Missing, unknown, revoked, expired and disabled keys are counted in the new
AuthFailurestable. A row covers one reason, endpoint, key and client network for up to 10 seconds, so callers without a valid key cannot flood the database. The presented key is never stored. Refused keys onGET /v1/modelsare recorded with the endpointModels. - Floods of unknown keys are throttled. After
Gateway:AuthFailuresPerMinute(60) missing or unknown keys in a minute from one client address (IPv6 per /64), the gateway answers that address429 rate_limitedwithout looking keys up until the minute ends; keys it has cached keep working, so other clients behind the same proxy are not cut off. Set trusted proxies (see client addresses) so the limit applies per client, not per proxy. - Logs are JSON outside development. The services write console logs with the JSON formatter unless
Logging:Console:FormatterNamesays otherwise, so a line break or terminal escape sequence in a client-supplied value (a model name, a Data API path) cannot start a forged log line. Those values are also logged and stored with control characters replaced by?. SetLogging__Console__FormatterName=simplefor the old plain-text format. - Admin activity is attributable. Every audit entry records the user's name, roles and departments at the time, the
client address (behind the trusted proxies), a session id given at sign-in, the request's trace id and the browser.
Exports of the configuration or of usage are audit entries (
export). Sign-in, sign-out, Stay signed in, refused requests and reads of the audit log, request list, PII incidents and Data API keys are security events. Alerts worth setting up in the SIEM:- several
admin.access.deniedfrom one user (probing for rights), or any from avieweron write paths; admin.changewith actionexport, oradmin.data.readof/api/audit, outside office hours;admin.signinfrom an address outside the municipal networks, or the sameActorfrom two addresses at once;admin.session.extendedmany times for oneSessionId(a session kept alive unattended);- an audit entry (Data API
security/auditfeed) whosesessionIdnever had anadmin.signin.
- several
- Unknown keys are cached. A key the gateway does not know is remembered for
Gateway:KeyCacheSeconds(30 s), so a client retrying with a deleted or mistyped key costs no database query (0.12 ms per refused request in theauditbenchmark). Creating a key in the admin API clears the cache at once.
Settings (Gateway:Security:*):
| Setting | Default | |
|---|---|---|
SourceAddress | Truncated | Client address kept for refused keys: Truncated (IPv4 /24, IPv6 /48), Full or None. Behind a reverse proxy, list the proxy under Settings > Trusted proxies in the admin UI, or every address is the proxy's. |
AuthFailureFlushSeconds | 10 | How often refused keys are written and logged. |
MaxAuthFailureBuckets | 1000 | Distinct rows per interval; anything beyond is folded into one row per reason and endpoint. |
Data API for BI, management and security
An optional, read-only HTTPS service (Ume.LlmGateway.DataApi) for integrations: a data warehouse ETL job, a
management dashboard, a SIEM connector. It never gives anyone database access.
- Each integration is an OAuth client (client credentials) at your identity provider and gets only the
permissions it needs:
usage.aggregate(totals per day or month and department, model, provider),usage.detail(one row per request),security.read(refused keys, PII actions, audit log, key inventory) orcatalog.read(departments, teams, keys, models, prices, budgets). Works with Keycloak, AD FS and Entra ID. - Or a Data API key: a gateway admin creates one under Access → Data API access in the admin UI, ticks the
permissions and gets the key (
ume-dk-…) once, with an example request. Send it asAuthorization: BearerorX-Api-Key. Revoking takes effect within 30 seconds (DataApi:KeyCacheSeconds). - Incremental feeds: pass the
nextCursorof one page asafteron the next call. JSON, orformat=csv/format=ndjsonfor bulk loads. - Privacy by default: departments with fewer than 5 active keys in a period are reported together without a
department, and per-request PII categories are left out of
usage.detail. - Read-only by database role: it connects as
ume_data, which cannot read gateway key hashes, encrypted secrets or provider credentials at all (it reads only the hashes of Data API keys and writes only their last use). Every read is logged as adata.readsecurity event.
Locally it starts with the rest of the stack (resource dataapi, https://localhost:7311/scalar). Get a token from the
bundled Keycloak with the ume-data-dev client (all four permissions); its secret is the AppHost parameter
data-client-secret:
$token = (Invoke-RestMethod -Method Post "<keycloak-url>/realms/ume/protocol/openid-connect/token" -Body @{
grant_type = 'client_credentials'; client_id = 'ume-data-dev'; client_secret = '<data-client-secret>' }).access_token
Invoke-RestMethod "https://localhost:7311/v1/usage/records?limit=10" -Headers @{ Authorization = "Bearer $token" }In production it is the Compose profile data (COMPOSE_PROFILES=data); see the runbook, Data API (optional),
and for existing installations the upgrade guide. Endpoints and design: data-access.md.