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