This is an automated email from the ASF dual-hosted git repository.
fokko pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-python.git
The following commit(s) were added to refs/heads/main by this push:
new 9797360 Rest Catalog Support for a Separate OAuth Server URI (#233)
9797360 is described below
commit 979736045f440c91020990106572ef9fc25c0f9f
Author: Sung Yun <[email protected]>
AuthorDate: Tue Jan 16 07:30:24 2024 -0500
Rest Catalog Support for a Separate OAuth Server URI (#233)
* support separate auth url
* Remove debug line
---------
Co-authored-by: Fokko Driesprong <[email protected]>
---
mkdocs/docs/configuration.md | 17 +++++++++--------
pyiceberg/catalog/rest.py | 11 +++++++++--
tests/catalog/test_rest.py | 25 ++++++++++++++++++++++++-
3 files changed, 42 insertions(+), 11 deletions(-)
diff --git a/mkdocs/docs/configuration.md b/mkdocs/docs/configuration.md
index 801bb8f..12bb351 100644
--- a/mkdocs/docs/configuration.md
+++ b/mkdocs/docs/configuration.md
@@ -130,14 +130,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 3dbb5b7..de192a9 100644
--- a/pyiceberg/catalog/rest.py
+++ b/pyiceberg/catalog/rest.py
@@ -109,6 +109,7 @@ SSL = "ssl"
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,21 @@ class RestCatalog(Catalog):
return url + endpoint.format(**kwargs)
+ @property
+ def auth_url(self) -> str:
+ 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 79cf25f..248cc14 100644
--- a/tests/catalog/test_rest.py
+++ b/tests/catalog/test_rest.py
@@ -24,7 +24,7 @@ from requests_mock import Mocker
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 @@ from pyiceberg.utils.config import Config
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",