1
- from typing import Literal
1
+ # --------------------------------------------------------------------
2
+ # Extends OIDC client auth model with an optional `token` field.
3
+ # Works on Pydantic v1 and v2.
4
+ #
5
+ # Accepted credential sets (exactly **one** of):
6
+ # 1 pre-issued `token`
7
+ # 2 `client_secret` (client-credentials flow)
8
+ # 3 `username` + `password` + `client_secret` (ROPG)
9
+ # --------------------------------------------------------------------
10
+ from __future__ import annotations
11
+ from typing import Literal , Optional
2
12
3
13
from feast .repo_config import FeastConfigBaseModel
4
14
15
+ # pick the correct validator decorator for current Pydantic version
16
+ try : # Pydantic ≥ 2.0
17
+ from pydantic import model_validator as _v2 # type: ignore
18
+
19
+ def _cred_validator (fn ):
20
+ return _v2 (mode = "after" )(fn ) # run after field validation
21
+ except ImportError : # Pydantic 1.x
22
+ from pydantic import root_validator as _v1 # type: ignore
23
+
24
+ def _cred_validator (fn ):
25
+ return _v1 (skip_on_failure = True )(fn )
26
+
5
27
6
28
class AuthConfig (FeastConfigBaseModel ):
7
29
type : Literal ["oidc" , "kubernetes" , "no_auth" ] = "no_auth"
@@ -13,9 +35,40 @@ class OidcAuthConfig(AuthConfig):
13
35
14
36
15
37
class OidcClientAuthConfig (OidcAuthConfig ):
16
- username : str
17
- password : str
18
- client_secret : str
38
+ # any **one** of the four fields below is sufficient
39
+ username : Optional [str ] = None
40
+ password : Optional [str ] = None
41
+ client_secret : Optional [str ] = None
42
+ token : Optional [str ] = None # pre-issued `token`
43
+
44
+ @_cred_validator
45
+ def _validate_credentials (cls , values ):
46
+ """Enforce exactly one valid credential set."""
47
+ d = values .__dict__ if hasattr (values , "__dict__" ) else values
48
+
49
+ has_user_pass = bool (d .get ("username" )) and bool (d .get ("password" ))
50
+ has_secret = bool (d .get ("client_secret" ))
51
+ has_token = bool (d .get ("token" ))
52
+
53
+ # 1 static token
54
+ if has_token and not (has_user_pass or has_secret ):
55
+ return values
56
+
57
+ # 2 client_credentials
58
+ if has_secret and not has_user_pass and not has_token :
59
+ return values
60
+
61
+ # 3 ROPG
62
+ if has_user_pass and has_secret and not has_token :
63
+ return values
64
+
65
+ raise ValueError (
66
+ "Invalid OIDC client auth combination: "
67
+ "provide either\n "
68
+ " • token\n "
69
+ " • client_secret (without username/password)\n "
70
+ " • username + password + client_secret"
71
+ )
19
72
20
73
21
74
class NoAuthConfig (AuthConfig ):
0 commit comments