From a24ccf4232e88b70307327560a81911e13b3c68a Mon Sep 17 00:00:00 2001 From: Sung Yun <107272191+syun64@users.noreply.github.com> Date: Thu, 21 Dec 2023 16:58:07 +0000 Subject: [PATCH 1/2] support separate auth url --- mkdocs/docs/configuration.md | 17 +++++++++-------- pyiceberg/catalog/rest.py | 12 ++++++++++-- tests/catalog/test_rest.py | 25 ++++++++++++++++++++++++- 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/mkdocs/docs/configuration.md b/mkdocs/docs/configuration.md index fa861908f9..9ea730ffbf 100644 --- a/mkdocs/docs/configuration.md +++ b/mkdocs/docs/configuration.md @@ -129,14 +129,15 @@ catalog: cabundle: /absolute/path/to/cabundle.pem ``` -| Key | Example | Description | -| ------------------- | ----------------------- | -------------------------------------------------------------------------- | -| uri | https://rest-catalog/ws | URI identifying the REST Server | -| credential | t-1234:secret | Credential to use for OAuth2 credential flow when initializing the catalog | -| token | FEW23.DFSDF.FSDF | Bearer token value to use for `Authorization` header | -| rest.sigv4-enabled | true | Sign requests to the REST Server using AWS SigV4 protocol | -| rest.signing-region | us-east-1 | The region to use when SigV4 signing a request | -| rest.signing-name | execute-api | The service signing name to use when SigV4 signing a request | +| Key | Example | Description | +| ---------------------- | ----------------------- | -------------------------------------------------------------------------------------------------- | +| uri | https://rest-catalog/ws | URI identifying the REST Server | +| credential | t-1234:secret | Credential to use for OAuth2 credential flow when initializing the catalog | +| token | FEW23.DFSDF.FSDF | Bearer token value to use for `Authorization` header | +| rest.sigv4-enabled | true | Sign requests to the REST Server using AWS SigV4 protocol | +| rest.signing-region | us-east-1 | The region to use when SigV4 signing a request | +| rest.signing-name | execute-api | The service signing name to use when SigV4 signing a request | +| rest.authorization-url | https://auth-service/cc | Authentication URL to use for client credentials authentication (default: uri + 'v1/oauth/tokens') | ## SQL Catalog diff --git a/pyiceberg/catalog/rest.py b/pyiceberg/catalog/rest.py index 3dbb5b72a9..c384ebbf32 100644 --- a/pyiceberg/catalog/rest.py +++ b/pyiceberg/catalog/rest.py @@ -109,6 +109,7 @@ class Endpoints: SIGV4 = "rest.sigv4-enabled" SIGV4_REGION = "rest.signing-region" SIGV4_SERVICE = "rest.signing-name" +AUTH_URL = "rest.authorization-url" NAMESPACE_SEPARATOR = b"\x1F".decode(UTF8) @@ -265,15 +266,22 @@ def url(self, endpoint: str, prefixed: bool = True, **kwargs: Any) -> str: return url + endpoint.format(**kwargs) + @property + def auth_url(self) -> str: + print(f"DEBUG: {self.properties}") + if url := self.properties.get(AUTH_URL): + return url + else: + return self.url(Endpoints.get_token, prefixed=False) + def _fetch_access_token(self, session: Session, credential: str) -> str: if SEMICOLON in credential: client_id, client_secret = credential.split(SEMICOLON) else: client_id, client_secret = None, credential data = {GRANT_TYPE: CLIENT_CREDENTIALS, CLIENT_ID: client_id, CLIENT_SECRET: client_secret, SCOPE: CATALOG_SCOPE} - url = self.url(Endpoints.get_token, prefixed=False) # Uses application/x-www-form-urlencoded by default - response = session.post(url=url, data=data) + response = session.post(url=self.auth_url, data=data) try: response.raise_for_status() except HTTPError as exc: diff --git a/tests/catalog/test_rest.py b/tests/catalog/test_rest.py index 79cf25f87a..248cc14d88 100644 --- a/tests/catalog/test_rest.py +++ b/tests/catalog/test_rest.py @@ -24,7 +24,7 @@ import pyiceberg from pyiceberg.catalog import PropertiesUpdateSummary, Table, load_catalog -from pyiceberg.catalog.rest import RestCatalog +from pyiceberg.catalog.rest import AUTH_URL, RestCatalog from pyiceberg.exceptions import ( NamespaceAlreadyExistsError, NoSuchNamespaceError, @@ -43,6 +43,7 @@ TEST_URI = "https://iceberg-test-catalog/" TEST_CREDENTIALS = "client:secret" +TEST_AUTH_URL = "https://auth-endpoint/" TEST_TOKEN = "some_jwt_token" TEST_HEADERS = { "Content-type": "application/json", @@ -116,6 +117,28 @@ def test_token_200(rest_mock: Mocker) -> None: ) +def test_token_200_w_auth_url(rest_mock: Mocker) -> None: + rest_mock.post( + TEST_AUTH_URL, + json={ + "access_token": TEST_TOKEN, + "token_type": "Bearer", + "expires_in": 86400, + "issued_token_type": "urn:ietf:params:oauth:token-type:access_token", + }, + status_code=200, + request_headers=OAUTH_TEST_HEADERS, + ) + # pylint: disable=W0212 + assert ( + RestCatalog("rest", uri=TEST_URI, credential=TEST_CREDENTIALS, **{AUTH_URL: TEST_AUTH_URL})._session.headers[ + "Authorization" + ] + == f"Bearer {TEST_TOKEN}" + ) + # pylint: enable=W0212 + + def test_config_200(requests_mock: Mocker) -> None: requests_mock.get( f"{TEST_URI}v1/config", From b5d3e483d3a29e4c5b2d51a778e83c8cce3db78a Mon Sep 17 00:00:00 2001 From: Fokko Driesprong Date: Tue, 16 Jan 2024 13:23:44 +0100 Subject: [PATCH 2/2] Remove debug line --- pyiceberg/catalog/rest.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyiceberg/catalog/rest.py b/pyiceberg/catalog/rest.py index c384ebbf32..de192a9e0b 100644 --- a/pyiceberg/catalog/rest.py +++ b/pyiceberg/catalog/rest.py @@ -268,7 +268,6 @@ def url(self, endpoint: str, prefixed: bool = True, **kwargs: Any) -> str: @property def auth_url(self) -> str: - print(f"DEBUG: {self.properties}") if url := self.properties.get(AUTH_URL): return url else: