> Raw Markdown twin (generated at build time from the source Markdown). Rendered page: https://docs.gatellm.io/en/practices/access-control · Doc index: https://docs.gatellm.io/en/llms.txt


# Access control design

Access control answers "who can call what". The gateway combines three layers of control points: access keys (identity) → key groups (model/LB authorization) → Header ACL (request header rules).

## Three control points

| Layer | Governs | Configured at |
|----|--------|--------|
| Access key | Caller identity | Console → Access Keys |
| Key group | Model reachability + LB reachability | Console → Key Groups (`models` + `load_balancers`) |
| Header ACL | Match by request header to allow/deny | Console → Header ACL rules |

## Allowlist mode (default deny + single allow)

The regex engine does not support lookahead, so "allow only if the value **does not** contain X" cannot be written as a single regex. When you need default-deny and only allow specific requests, orchestrate the other way:

1. Set `default_action` to `deny` (default deny).
2. Use a "if contains X then `allow`" rule to allow matching items.
3. Or split into multiple rules covering each allow condition.

This "allowlist + explicit allow" is safer than a denylist — new unknown requests are denied by default. For a config example, see the allowlist mode in [Configure Header ACL](/en/howto/configure-header-acl.md).

## Scope and priority

Header ACL rules have three scopes: global → key group → access key. Matching is first-match-wins, with the more specific scope taking priority. See [Header ACL rule fields](/en/reference/header-acl-rules.md) for the fields.

## Expressiveness limits and rule orchestration

::: warning Regex does not support lookahead / backreferences
The regex engine is a linear-time, ReDoS-resistant implementation, so it does **not** support lookahead (`(?=...)` / `(?!...)`) or backreferences (`\1`). The trade-off is that negation conditions like "allow only if the value does not contain X" **cannot be expressed as a single regex** — use the allowlist mode above instead (default deny + explicit allow).
:::

Rules that fail to load (syntax errors, etc.) are skipped and logged as a warning, while the remaining rules still take effect — so test rules before deploying, and don't rely on a single possibly-failing-to-load rule for a critical allow.

## Key groups: two independent dimensions

A key group's `models` and `load_balancers` are two **independent** lists:

- `models: ["*"]` (all models) does **not** carry LB permission.
- `load_balancers: ["*"]` does not carry ordinary model permission either.
- The two dimensions must be checked separately.

And an LB is an authorization unit — once an LB is allowed, keys in that group can reach **every** entry of that LB, without being validated against `models` one by one. For strict isolation, don't use LBs; see [Multi-tenant isolation](/en/usecases/multi-tenant-isolation.md#lb-is-auth-unit).

## Behavior when rules fail

- Rule syntax error: ignored at load time, logged as a warning, other rules take effect.
- Regex no match: follows `default_action`.
- Multiple scopes: first-match-wins, more specific scope takes priority.

## FAQ

**Q: Can a key group's models use an alias?**
No. It only matches the canonical name (`name` field), aliases are not resolved. See "Model aliases and hidden names" in [Upstream and model fields](/en/reference/upstreams-models-fields.md).

**Q: How do I authorize a hide_name model?**
Write its **canonical name** (not the alias) in the key group's `models`. `hide_name=true` only affects whether clients can access it by canonical name; authorization still uses the canonical name. See [Upstream and model fields](/en/reference/upstreams-models-fields.md).

**Q: How do I rate-limit per tenant?**
Each tenant has its own access key, and rate limits are counted per key. In multi-instance, configure Redis so rate limits are shared across instances. See [Multi-tenant isolation](/en/usecases/multi-tenant-isolation.md).

**Next**: [Multi-tenant isolation](/en/usecases/multi-tenant-isolation.md) for isolation; [Header ACL rule fields](/en/reference/header-acl-rules.md) for fields; [Configure Header ACL](/en/howto/configure-header-acl.md) for examples.
