-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Redshift Iam Idc token authentication method with an eye towards …
…future supported Idps (#970) * Fix tests and add token authentication method to auth flow * Add changelog. * Add token method (>^.^)> We expect users of this method to provide a YAML-structured set of params including a uri, an authentication string, and whatever paramters might be needed to construct the correct payload equivalent to data in a curl request. There is an all-important under the hood POST which needs a set of params unique to each identity provider to generate access tokens for use with TokenAuthIdpPlugin. * Add unit tests for current codepaths. * Make test a bit more specific. * Add skeleton of test case I've been using for hand testing. Can't commit it due to it being based on a refresh token. * Code review comments and adapt for Entra + future providers. * Improve comment. * Better error handling for missing access_token since it could happen on some Idp
- Loading branch information
1 parent
f10d316
commit de078b8
Showing
7 changed files
with
273 additions
and
11 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
kind: Features | ||
body: Add IdpTokenAuthPlugin authentication method. | ||
time: 2024-12-17T18:13:40.281494-08:00 | ||
custom: | ||
Author: versusfacit | ||
Issue: "898" |
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,87 @@ | ||
import requests | ||
from abc import ABC, abstractmethod | ||
from enum import Enum | ||
from typing import Dict, Any | ||
|
||
from dbt.adapters.exceptions import FailedToConnectError | ||
from dbt_common.exceptions import DbtRuntimeError | ||
|
||
|
||
# Define an Enum for the supported token endpoint types | ||
class TokenServiceBase(ABC): | ||
def __init__(self, token_endpoint: Dict[str, Any]): | ||
expected_keys = {"type", "request_url", "request_data"} | ||
for key in expected_keys: | ||
if key not in token_endpoint: | ||
raise FailedToConnectError(f"Missing required key in token_endpoint: '{key}'") | ||
|
||
self.type: str = token_endpoint["type"] | ||
self.url: str = token_endpoint["request_url"] | ||
self.data: str = token_endpoint["request_data"] | ||
|
||
self.other_params = {k: v for k, v in token_endpoint.items() if k not in expected_keys} | ||
|
||
@abstractmethod | ||
def build_header_payload(self) -> Dict[str, Any]: | ||
pass | ||
|
||
def handle_request(self) -> requests.Response: | ||
""" | ||
Handles the request with rate limiting and error handling. | ||
""" | ||
response = requests.post(self.url, headers=self.build_header_payload(), data=self.data) | ||
|
||
if response.status_code == 429: | ||
raise DbtRuntimeError( | ||
"Rate limit on identity provider's token dispatch has been reached. " | ||
"Consider increasing your identity provider's refresh token rate or " | ||
"lower dbt's maximum concurrent thread count." | ||
) | ||
|
||
response.raise_for_status() | ||
return response | ||
|
||
|
||
class OktaIdpTokenService(TokenServiceBase): | ||
def build_header_payload(self) -> Dict[str, Any]: | ||
if encoded_idp_client_creds := self.other_params.get("idp_auth_credentials"): | ||
return { | ||
"accept": "application/json", | ||
"authorization": f"Basic {encoded_idp_client_creds}", | ||
"content-type": "application/x-www-form-urlencoded", | ||
} | ||
else: | ||
raise FailedToConnectError( | ||
"Missing 'idp_auth_credentials' from token_endpoint. Please provide client_id:client_secret in base64 encoded format as a profile entry under token_endpoint." | ||
) | ||
|
||
|
||
class EntraIdpTokenService(TokenServiceBase): | ||
""" | ||
formatted based on docs: https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow#refresh-the-access-token | ||
""" | ||
|
||
def build_header_payload(self) -> Dict[str, Any]: | ||
return { | ||
"accept": "application/json", | ||
"content-type": "application/x-www-form-urlencoded", | ||
} | ||
|
||
|
||
class TokenServiceType(Enum): | ||
OKTA = "okta" | ||
ENTRA = "entra" | ||
|
||
|
||
def create_token_service_client(token_endpoint: Dict[str, Any]) -> TokenServiceBase: | ||
if (service_type := token_endpoint.get("type")) is None: | ||
raise FailedToConnectError("Missing required key in token_endpoint: 'type'") | ||
|
||
if service_type == TokenServiceType.OKTA.value: | ||
return OktaIdpTokenService(token_endpoint) | ||
elif service_type == TokenServiceType.ENTRA.value: | ||
return EntraIdpTokenService(token_endpoint) | ||
else: | ||
raise ValueError( | ||
f"Unsupported identity provider type: {service_type}. Select 'okta' or 'entra.'" | ||
) |
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
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