forked from feast-dev/feast
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implementation of oidc client authentication. (feast-dev#40)
* Adding initial draft code to manage the oidc client authentication. Signed-off-by: Lokesh Rangineni <lokeshforjava@gmail.com> * Adding initial draft code to manage the oidc client authentication. Signed-off-by: Lokesh Rangineni <lokeshforjava@gmail.com> * Incorporating code review comments. Signed-off-by: Lokesh Rangineni <lokeshforjava@gmail.com> --------- Signed-off-by: Lokesh Rangineni <lokeshforjava@gmail.com> Signed-off-by: Abdul Hameed <ahameed@redhat.com>
- Loading branch information
1 parent
c7984e0
commit 9f47283
Showing
8 changed files
with
137 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from abc import ABC, abstractmethod | ||
|
||
|
||
class AuthenticationClientManager(ABC): | ||
@abstractmethod | ||
def get_token(self) -> str: | ||
"""Retrieves the token based on the authentication type configuration""" | ||
pass |
43 changes: 43 additions & 0 deletions
43
sdk/python/feast/permissions/client/http_auth_requests_wrapper.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import requests | ||
from requests import Session | ||
|
||
from feast.permissions.auth_model import ( | ||
AuthConfig, | ||
KubernetesAuthConfig, | ||
OidcAuthConfig, | ||
) | ||
from feast.permissions.client.kubernetes_auth_client_manager import ( | ||
KubernetesAuthClientManager, | ||
) | ||
from feast.permissions.client.oidc_authentication_client_manager import ( | ||
OidcAuthClientManager, | ||
) | ||
|
||
|
||
class AuthenticatedRequestsSession(Session): | ||
def __init__(self, auth_token: str): | ||
super().__init__() | ||
self.auth_token = auth_token | ||
self.headers.update({"Authorization": f"Bearer {self.auth_token}"}) | ||
|
||
|
||
def get_auth_client_manager(auth_config: AuthConfig): | ||
if auth_config.type == "oidc": | ||
assert isinstance(auth_config, OidcAuthConfig) | ||
return OidcAuthClientManager(auth_config) | ||
elif auth_config.type == "kubernetes": | ||
assert isinstance(auth_config, KubernetesAuthConfig) | ||
return KubernetesAuthClientManager(auth_config) | ||
else: | ||
raise RuntimeError( | ||
f"No Auth client manager implemented for the auth type:${auth_config.type}" | ||
) | ||
|
||
|
||
def get_http_auth_requests_session(auth_config: AuthConfig) -> Session: | ||
if auth_config.type == "no_auth": | ||
request_session = requests.session() | ||
else: | ||
auth_client_manager = get_auth_client_manager(auth_config) | ||
request_session = AuthenticatedRequestsSession(auth_client_manager.get_token()) | ||
return request_session |
11 changes: 11 additions & 0 deletions
11
sdk/python/feast/permissions/client/kubernetes_auth_client_manager.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
from feast.permissions.auth_model import KubernetesAuthConfig | ||
from feast.permissions.client.auth_client_manager import AuthenticationClientManager | ||
|
||
|
||
class KubernetesAuthClientManager(AuthenticationClientManager): | ||
def __init__(self, auth_config: KubernetesAuthConfig): | ||
self.auth_config = auth_config | ||
|
||
# TODO: needs to implement this for k8 auth. | ||
def get_token(self): | ||
return "" |
52 changes: 52 additions & 0 deletions
52
sdk/python/feast/permissions/client/oidc_authentication_client_manager.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import logging | ||
|
||
import requests | ||
|
||
from feast.permissions.auth_model import OidcAuthConfig | ||
from feast.permissions.client.auth_client_manager import AuthenticationClientManager | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class OidcAuthClientManager(AuthenticationClientManager): | ||
def __init__(self, auth_config: OidcAuthConfig): | ||
self.auth_config = auth_config | ||
|
||
def _get_token_endpoint(self): | ||
response = requests.get(self.auth_config.auth_discovery_url) | ||
if response.status_code == 200: | ||
oidc_config = response.json() | ||
if not oidc_config["token_endpoint"]: | ||
raise RuntimeError( | ||
" OIDC token_endpoint is not available from discovery url response." | ||
) | ||
return oidc_config["token_endpoint"] | ||
else: | ||
raise RuntimeError( | ||
f"Error fetching OIDC token endpoint configuration: {response.status_code} - {response.text}" | ||
) | ||
|
||
def get_token(self): | ||
# Fetch the token endpoint from the discovery URL | ||
token_endpoint = self._get_token_endpoint() | ||
|
||
token_request_body = { | ||
"grant_type": "password", | ||
"client_id": self.auth_config.client_id, | ||
"username": self.auth_config.username, | ||
"password": self.auth_config.password, | ||
} | ||
|
||
token_response = requests.post(token_endpoint, data=token_request_body) | ||
if token_response.status_code == 200: | ||
access_token = token_response.json()["access_token"] | ||
if not access_token: | ||
logger.debug( | ||
f"access_token is empty for the client_id=${self.auth_config.client_id}" | ||
) | ||
raise RuntimeError("access token is empty") | ||
return access_token | ||
else: | ||
raise RuntimeError( | ||
"Failed to obtain access token: {token_response.status_code} - {token_response.text}" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters