|
1 | 1 | # Authentication and Authorization |
2 | 2 |
|
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. |
6 | 4 |
|
7 | | -## Authentication configuration |
| 5 | +**See [auth/index.md](auth/index.md) for the complete authentication and authorization documentation.** |
8 | 6 |
|
9 | | -The authentication system is configured via the `authentication` section in |
10 | | -the configuration file. |
| 7 | +## Quick Links |
11 | 8 |
|
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