Skip to content

Commit 9797360

Browse files
sungwyFokko
andauthored
Rest Catalog Support for a Separate OAuth Server URI (#233)
* support separate auth url * Remove debug line --------- Co-authored-by: Fokko Driesprong <fokko@apache.org>
1 parent 4593208 commit 9797360

3 files changed

Lines changed: 42 additions & 11 deletions

File tree

mkdocs/docs/configuration.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,15 @@ catalog:
130130
cabundle: /absolute/path/to/cabundle.pem
131131
```
132132
133-
| Key | Example | Description |
134-
| ------------------- | ----------------------- | -------------------------------------------------------------------------- |
135-
| uri | https://rest-catalog/ws | URI identifying the REST Server |
136-
| credential | t-1234:secret | Credential to use for OAuth2 credential flow when initializing the catalog |
137-
| token | FEW23.DFSDF.FSDF | Bearer token value to use for `Authorization` header |
138-
| rest.sigv4-enabled | true | Sign requests to the REST Server using AWS SigV4 protocol |
139-
| rest.signing-region | us-east-1 | The region to use when SigV4 signing a request |
140-
| rest.signing-name | execute-api | The service signing name to use when SigV4 signing a request |
133+
| Key | Example | Description |
134+
| ---------------------- | ----------------------- | -------------------------------------------------------------------------------------------------- |
135+
| uri | https://rest-catalog/ws | URI identifying the REST Server |
136+
| credential | t-1234:secret | Credential to use for OAuth2 credential flow when initializing the catalog |
137+
| token | FEW23.DFSDF.FSDF | Bearer token value to use for `Authorization` header |
138+
| rest.sigv4-enabled | true | Sign requests to the REST Server using AWS SigV4 protocol |
139+
| rest.signing-region | us-east-1 | The region to use when SigV4 signing a request |
140+
| rest.signing-name | execute-api | The service signing name to use when SigV4 signing a request |
141+
| rest.authorization-url | https://auth-service/cc | Authentication URL to use for client credentials authentication (default: uri + 'v1/oauth/tokens') |
141142

142143
## SQL Catalog
143144

pyiceberg/catalog/rest.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ class Endpoints:
109109
SIGV4 = "rest.sigv4-enabled"
110110
SIGV4_REGION = "rest.signing-region"
111111
SIGV4_SERVICE = "rest.signing-name"
112+
AUTH_URL = "rest.authorization-url"
112113

113114
NAMESPACE_SEPARATOR = b"\x1F".decode(UTF8)
114115

@@ -265,15 +266,21 @@ def url(self, endpoint: str, prefixed: bool = True, **kwargs: Any) -> str:
265266

266267
return url + endpoint.format(**kwargs)
267268

269+
@property
270+
def auth_url(self) -> str:
271+
if url := self.properties.get(AUTH_URL):
272+
return url
273+
else:
274+
return self.url(Endpoints.get_token, prefixed=False)
275+
268276
def _fetch_access_token(self, session: Session, credential: str) -> str:
269277
if SEMICOLON in credential:
270278
client_id, client_secret = credential.split(SEMICOLON)
271279
else:
272280
client_id, client_secret = None, credential
273281
data = {GRANT_TYPE: CLIENT_CREDENTIALS, CLIENT_ID: client_id, CLIENT_SECRET: client_secret, SCOPE: CATALOG_SCOPE}
274-
url = self.url(Endpoints.get_token, prefixed=False)
275282
# Uses application/x-www-form-urlencoded by default
276-
response = session.post(url=url, data=data)
283+
response = session.post(url=self.auth_url, data=data)
277284
try:
278285
response.raise_for_status()
279286
except HTTPError as exc:

tests/catalog/test_rest.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
import pyiceberg
2626
from pyiceberg.catalog import PropertiesUpdateSummary, Table, load_catalog
27-
from pyiceberg.catalog.rest import RestCatalog
27+
from pyiceberg.catalog.rest import AUTH_URL, RestCatalog
2828
from pyiceberg.exceptions import (
2929
NamespaceAlreadyExistsError,
3030
NoSuchNamespaceError,
@@ -43,6 +43,7 @@
4343

4444
TEST_URI = "https://iceberg-test-catalog/"
4545
TEST_CREDENTIALS = "client:secret"
46+
TEST_AUTH_URL = "https://auth-endpoint/"
4647
TEST_TOKEN = "some_jwt_token"
4748
TEST_HEADERS = {
4849
"Content-type": "application/json",
@@ -116,6 +117,28 @@ def test_token_200(rest_mock: Mocker) -> None:
116117
)
117118

118119

120+
def test_token_200_w_auth_url(rest_mock: Mocker) -> None:
121+
rest_mock.post(
122+
TEST_AUTH_URL,
123+
json={
124+
"access_token": TEST_TOKEN,
125+
"token_type": "Bearer",
126+
"expires_in": 86400,
127+
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
128+
},
129+
status_code=200,
130+
request_headers=OAUTH_TEST_HEADERS,
131+
)
132+
# pylint: disable=W0212
133+
assert (
134+
RestCatalog("rest", uri=TEST_URI, credential=TEST_CREDENTIALS, **{AUTH_URL: TEST_AUTH_URL})._session.headers[
135+
"Authorization"
136+
]
137+
== f"Bearer {TEST_TOKEN}"
138+
)
139+
# pylint: enable=W0212
140+
141+
119142
def test_config_200(requests_mock: Mocker) -> None:
120143
requests_mock.get(
121144
f"{TEST_URI}v1/config",

0 commit comments

Comments
 (0)