Skip to content

Commit f9d3060

Browse files
authored
Merge pull request #1047 from major/LCORE-1019-split-auth-docs
LCORE-1019: Split auth.md into modular documentation structure
2 parents a743270 + 67dcaeb commit f9d3060

9 files changed

Lines changed: 1198 additions & 369 deletions

File tree

docs/auth.md

Lines changed: 10 additions & 362 deletions
Original file line numberDiff line numberDiff line change
@@ -1,367 +1,15 @@
11
# Authentication and Authorization
22

3-
Lightspeed Core Stack implements a modular authentication and authorization
4-
system with multiple authentication methods. Authorization is configurable
5-
through role-based access control.
3+
This documentation has been reorganized into separate files for better navigation.
64

7-
## Authentication configuration
5+
**See [auth/index.md](auth/index.md) for the complete authentication and authorization documentation.**
86

9-
The authentication system is configured via the `authentication` section in
10-
the configuration file.
7+
## Quick Links
118

12-
## Authentication Modules
13-
14-
Authentication is handled through selectable modules configured via the
15-
`module` field in the authentication configuration.
16-
17-
### No-op (`noop`)
18-
19-
Development-only authentication that bypasses security checks.
20-
21-
**Configuration:**
22-
```yaml
23-
authentication:
24-
module: noop
25-
```
26-
27-
**Behavior:**
28-
- Accepts any request without token validation
29-
- Extracts `user_id` from query parameters (defaults to `00000000-0000-0000-0000-000`)
30-
- Uses fixed username `lightspeed-user`
31-
32-
### No-op with Token (`noop-with-token`)
33-
34-
Development authentication that requires tokens but doesn't validate them.
35-
36-
**Configuration:**
37-
```yaml
38-
authentication:
39-
module: noop-with-token
40-
```
41-
42-
**Behavior:**
43-
- Extracts bearer token from the `Authorization` header
44-
- Same user ID and username handling as `noop`
45-
- Token is passed through unvalidated for downstream use
46-
47-
### Kubernetes (`k8s`)
48-
49-
K8s based authentication is suitable for running the Lightspeed Stack in
50-
Kubernetes environments. The user accessing the service must have a valid
51-
Kubernetes token and the appropriate RBAC permissions to access the service.
52-
The user must have the `get` permission on the Kubernetes RBAC non-resource URL
53-
`/ls-access`. Here is an example of granting `get` on `/ls-access` via a
54-
ClusterRole’s nonResourceURLs rule:
55-
56-
```yaml
57-
# Allow GET on non-resource URL /ls-access
58-
apiVersion: rbac.authorization.k8s.io/v1
59-
kind: ClusterRole
60-
metadata:
61-
name: lightspeed-access
62-
rules:
63-
- nonResourceURLs: ["/ls-access"]
64-
verbs: ["get"]
65-
---
66-
# Bind to a user, group, or service account
67-
apiVersion: rbac.authorization.k8s.io/v1
68-
kind: ClusterRoleBinding
69-
metadata:
70-
name: lightspeed-access-binding
71-
roleRef:
72-
apiGroup: rbac.authorization.k8s.io
73-
kind: ClusterRole
74-
name: lightspeed-access
75-
subjects:
76-
- kind: User # or ServiceAccount, Group
77-
name: SOME_USER_OR_SA
78-
apiGroup: rbac.authorization.k8s.io
79-
```
80-
81-
**Configuration:**
82-
83-
When deploying Lightspeed Stack in a Kubernetes cluster, it is not required to
84-
specify cluster connection details, it automatically picks up the in-cluster
85-
configuration or through a kubeconfig file.
86-
87-
When running outside a kubernetes cluster or connecting to external Kubernetes
88-
clusters, Lightspeed Stack requires the cluster connection details in the
89-
configuration file:
90-
91-
- `k8s_cluster_api` Kubernetes Cluster API URL. The URL of the k8s/OCP API server where tokens are validated.
92-
- `k8s_ca_cert_path` Path to the CA certificate file for clusters with self-signed certificates.
93-
- `skip_tls_verification` Whether to skip TLS verification.
94-
95-
For example:
96-
97-
```yaml
98-
authentication:
99-
module: k8s
100-
k8s_cluster_api: https://kubernetes.default.svc # optional, will be auto-detected
101-
k8s_ca_cert_path: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt # optional, will be auto-detected
102-
skip_tls_verification: false # optional, insecure
103-
```
104-
105-
**Behavior:**
106-
- Validates bearer tokens via the Kubernetes TokenReview API
107-
- Performs authorization checks using SubjectAccessReview (SAR)
108-
- Checks access to configured virtual path (default: `/ls-access`) with `get` verb
109-
- Extracts user ID and username from token claims
110-
- Special handling for the `kube:admin` user (uses cluster ID as user ID)
111-
112-
**Requirements:**
113-
- Valid Kubernetes service account token in the `Authorization` header
114-
- RBAC rules granting access to the virtual path
115-
- Cluster access or kubeconfig file
116-
117-
### JWK Token (`jwk-token`)
118-
119-
JWK (JSON Web Keyset) based authentication is suitable for scenarios where you
120-
need to authenticate users based on tokens. This method is commonly used in web
121-
applications and APIs.
122-
123-
Users provide a JWT (JSON Web Token) in the `Authorization` header of their
124-
requests. This JWT is validated against the JWK set fetched from the configured
125-
URL.
126-
127-
**Configuration:**
128-
```yaml
129-
authentication:
130-
module: jwk-token
131-
jwk_config:
132-
url: https://auth.example.com/.well-known/jwks.json
133-
jwt_configuration:
134-
user_id_claim: sub # optional, defaults to 'sub'
135-
username_claim: name # optional, defaults to 'preferred_username'
136-
role_rules: [] # optional role extraction rules. See Authorization section for details.
137-
```
138-
139-
**Behavior:**
140-
- Fetches JWK set from configured URL (cached for 1 hour)
141-
- Validates JWT signature against JWK set
142-
- Extracts user ID and username from configurable JWT claims
143-
- Returns default credentials (guest-like) if no `Authorization` header present (guest access)
144-
145-
### API Key Token (`api-key-token`)
146-
147-
Authentication that checks a given API Key token is present as a Bearer token
148-
149-
**Configuration:**
150-
```yaml
151-
module: "api-key-token"
152-
api_key_config:
153-
api_key: "some-api-key"
154-
```
155-
156-
**Behavior:**
157-
- Extracts bearer token from the `Authorization` header
158-
- Same user ID and username handling as `noop`
159-
- Token is passed through and validated against the API Key given from configuration, for downstream use
160-
161-
### Red Hat Identity (`rh-identity`)
162-
163-
Red Hat Identity header authentication is suitable for deployments behind Red Hat
164-
Hybrid Cloud Console infrastructure (e.g., console.redhat.com, Insights). This
165-
method validates the `x-rh-identity` header provided by Red Hat's authentication
166-
proxy, supporting both User (console users) and System (RHEL systems) identity types.
167-
168-
**Configuration:**
169-
```yaml
170-
authentication:
171-
module: rh-identity
172-
rh_identity_config:
173-
required_entitlements: ["rhel"] # optional, validates service entitlements
174-
```
175-
176-
The `required_entitlements` field accepts a list of service names. When configured,
177-
ALL listed entitlements must be present in the identity header. Omit this field
178-
to disable entitlement validation entirely.
179-
180-
**Identity Types:**
181-
182-
- **User**: Console users authenticated via SSO. Identified by `user_id` and `username`
183-
from the `identity.user` object.
184-
- **System**: Certificate-authenticated RHEL systems. Identified by `cn` (Common Name)
185-
from the `identity.system` object, with `account_number` used as username.
186-
187-
**Header Format:**
188-
189-
The `x-rh-identity` header contains a base64-encoded JSON payload. Below are
190-
examples of the decoded JSON structure for each identity type.
191-
192-
User identity:
193-
```json
194-
{
195-
"identity": {
196-
"account_number": "123456",
197-
"org_id": "654321",
198-
"type": "User",
199-
"user": {
200-
"user_id": "abc123",
201-
"username": "user@example.com",
202-
"is_org_admin": false
203-
}
204-
},
205-
"entitlements": {
206-
"rhel": {"is_entitled": true, "is_trial": false}
207-
}
208-
}
209-
```
210-
211-
System identity:
212-
```json
213-
{
214-
"identity": {
215-
"account_number": "123456",
216-
"org_id": "654321",
217-
"type": "System",
218-
"system": {
219-
"cn": "c87dcb4c-8af1-40dd-878e-60c744edddd0"
220-
}
221-
},
222-
"entitlements": {
223-
"rhel": {"is_entitled": true, "is_trial": false}
224-
}
225-
}
226-
```
227-
228-
**Behavior:**
229-
- Extracts `x-rh-identity` header from request
230-
- Base64 decodes and parses as JSON
231-
- Validates structure based on identity type (User or System)
232-
- Validates service entitlements if `required_entitlements` is configured
233-
- Extracts user_id (or cn for System) and username (or account_number for System)
234-
235-
**Requirements:**
236-
- Valid `x-rh-identity` header with base64-encoded JSON
237-
- Proper JSON structure for the identity type
238-
- Required service entitlements (if configured)
239-
240-
**Error Responses:**
241-
242-
| Status | Condition |
243-
|--------|-----------|
244-
| 401 | Missing `x-rh-identity` header |
245-
| 400 | Invalid base64 encoding, invalid JSON, or missing required fields |
246-
| 403 | Missing required service entitlements |
247-
248-
## Authorization System
249-
250-
Authorization is controlled through role-based access control using two resolver types.
251-
252-
### Role Resolution
253-
254-
Determines user roles based on authentication method:
255-
256-
**No-op/K8s Authentication:**
257-
- Uses a no-op role resolver
258-
- All users get the special `*` (everyone) role only
259-
- To be expanded in the future
260-
261-
**JWK Token Authentication:**
262-
- Uses JWT claims to determine user roles through JSONPath expressions
263-
- Falls back to a no-op resolver if no role rules are configured
264-
265-
#### JWT Role Rules
266-
267-
Extract roles from JWT claims using JSONPath expressions, for example:
268-
269-
```yaml
270-
authentication:
271-
module: jwk-token
272-
jwk_config:
273-
jwt_configuration:
274-
role_rules:
275-
- jsonpath: "$.realm_access.roles[*]"
276-
operator: contains
277-
value: "manager"
278-
roles: ["manager"]
279-
- jsonpath: "$.org_id"
280-
operator: "equals"
281-
value: [["dummy_corp"]]
282-
roles: ["dummy_employee"]
283-
- jsonpath: "$.groups[*]"
284-
operator: in
285-
value: ["developers", "qa"]
286-
roles: ["developer"]
287-
negate: false
288-
```
289-
290-
**Fields:**
291-
- `jsonpath`: JSONPath expression to extract values from JWT claims.
292-
- `operator`: Comparison operator (see below)
293-
- `value`: Value(s) to evaluate the extracted values and operator against
294-
- `roles`: List of roles to assign if the rule matches
295-
- `negate`: If true, inverts the rule match result (optional, defaults to false)
296-
297-
Note that the JSONPath expression always yields a list of values, even for
298-
single-value expressions, so comparisons should be done accordingly.
299-
300-
**Operators:**
301-
- `equals`: Exact match
302-
- `contains`: Value contains the specified string
303-
- `in`: Value is in the specified list
304-
- `match`: Regex pattern match (uses pre-compiled patterns)
305-
306-
### Access Resolution
307-
308-
Various operations inside lightspeed require authorization checks. Those
309-
operations are associated with actions (e.g. `query`, `info`, `admin`).
310-
311-
Once user roles are determined, checking whether a user is allowed to perform
312-
an action is done through access resolvers.
313-
314-
**No-op resolver:**
315-
316-
A resolver which uses a no-op access resolver that grants all users access to
317-
all actions, used when no access rules are configured no-op authentication is
318-
configured, or at-least currently when k8s authentication is configured.
319-
320-
**Rule-based Access:**
321-
322-
A resolver which does the obvious thing of checking whether any of the user's
323-
roles is allowed to perform the requested action based on the access rules in
324-
the authorization configuration. It also grants all users which have the `admin`
325-
action unrestricted access to all other actions.
326-
327-
#### Access Rules
328-
329-
Define which roles can perform which actions:
330-
331-
```yaml
332-
authorization:
333-
access_rules:
334-
# `*` is a special role that is given to all users
335-
- role: "*"
336-
actions: ["query", "info"]
337-
- role: "manager"
338-
# admin is a special *action* that grants unrestricted access to all actions.
339-
# Note that only the `admin` *action* is special, there is no special `admin` role.
340-
actions: ["admin"]
341-
- role: "dummy_employee"
342-
actions: ["list_conversations"]
343-
- role: "developer"
344-
actions: ["query", "get_config", "list_conversations"]
345-
```
346-
347-
**Available Actions:**
348-
- `admin` - If a user has this action, they automatically can perform all other actions
349-
- `query` - Access query endpoints
350-
- `query_other_conversations` - Query conversations not owned by the user
351-
- `streaming_query` - Access streaming query endpoints
352-
- `info` - Access the `/` endpoint, `/info` endpoint, `/readiness` endpoint, and `/liveness` endpoint
353-
- `get_config` - Access the `/config` endpoint
354-
- `get_models` - Access the `/models` endpoint
355-
- `get_tools` - Access the `/tools` and `/mcp-auth/client-options` endpoints
356-
- `get_shields` - Access the `/shields` endpoint
357-
- `list_providers` - Access the `/providers` endpoint
358-
- `get_provider` - Access the `/providers/{provider_id}` endpoint
359-
- `get_metrics` - Access the `/metrics` endpoint
360-
- `list_conversations` - Access the `/conversations` endpoint
361-
- `list_other_conversations` - Access conversations not owned by the user
362-
- `get_conversation` - `GET` conversations from `/conversations/{conversation_id}` endpoint
363-
- `read_other_conversations` - Read conversations not owned by the user
364-
- `delete_conversation` - `DELETE` conversations from `/conversations/{conversation_id}` endpoint
365-
- `delete_other_conversations` - Delete conversations not owned by the user
366-
- `feedback` - Access the `/feedback` endpoint
367-
- `model_override` - Allow user to choose the model when querying
9+
- [Overview & Configuration](auth/index.md)
10+
- [No-op Modules](auth/noop.md) - Development authentication
11+
- [Kubernetes](auth/kubernetes.md) - K8s/OCP authentication
12+
- [JWK Token](auth/jwk-token.md) - JWT/OAuth2 authentication
13+
- [API Key Token](auth/api-key-token.md) - Static API key authentication
14+
- [Red Hat Identity](auth/rh-identity.md) - Red Hat Hybrid Cloud Console authentication
15+
- [Authorization](auth/authorization.md) - Role-based access control

0 commit comments

Comments
 (0)