Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions mkdocs/docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
11 changes: 9 additions & 2 deletions pyiceberg/catalog/rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

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

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:
Expand Down
25 changes: 24 additions & 1 deletion tests/catalog/test_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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",
Expand Down Expand Up @@ -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",
Expand Down