Skip to content

Commit

Permalink
Issue #7/EP-4046 Add warnings about OIDC mapping changes and lookup f…
Browse files Browse the repository at this point in the history
…ailures
  • Loading branch information
soxofaan committed Oct 8, 2021
1 parent bfaecdc commit 8c91d9a
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/openeo_aggregator/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ def _set_auth(self, auth: OpenEoApiAuthBase):
auth = property(_get_auth, _set_auth)

def set_oidc_provider_map(self, pid_map: Dict[str, str]):
if len(self._oidc_provider_map) > 0 and self._oidc_provider_map != pid_map:
_log.warning(f"Changing OIDC provider mapping in connection {self.id} from {self._oidc_provider_map} to {pid_map}")
_log.info(f"Setting OIDC provider mapping for connection {self.id}: {pid_map}")
self._oidc_provider_map = pid_map

def _get_bearer(self, request: flask.Request) -> str:
Expand All @@ -68,6 +71,8 @@ def _get_bearer(self, request: flask.Request) -> str:
return auth.partition("Bearer ")[2]
elif auth.startswith("Bearer oidc/"):
_, pid, token = auth.split("/")
if pid not in self._oidc_provider_map:
_log.warning(f"OIDC provider mapping failure: {pid} not in {self._oidc_provider_map}.")
backend_pid = self._oidc_provider_map.get(pid, pid)
return f"oidc/{backend_pid}/{token}"
else:
Expand Down Expand Up @@ -193,6 +198,7 @@ def build_oidc_handling(self, configured_providers: List[OidcProvider]) -> List[

# Take configured providers for common issuers.
agg_providers = [p for p in configured_providers if p.issuer.rstrip("/").lower() in intersection]
_log.info(f"Actual aggregator providers: {agg_providers}")

# Set up provider id mapping (aggregator pid to original backend pid) for the connections
for con in self._connections:
Expand Down
55 changes: 55 additions & 0 deletions tests/test_connection.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import logging
import types

import flask
Expand Down Expand Up @@ -295,3 +296,57 @@ def get_me(request: requests.Request, context):
con3 = multi_backend_connection.get_connection("b3")
with con3.authenticated_from_request(request=request):
assert con3.get("/me").json() == {"user_id": "Bearer oidc/x3/yadayadayada"}

def test_oidc_provider_mapping_changes(self, requests_mock, caplog):
domain1 = "https://b1.test/v1"
requests_mock.get(domain1 + "/", json={"api_version": "1.0.0"})
requests_mock.get(domain1 + "/credentials/oidc", json={"providers": [
{"id": "x1", "issuer": "https://x.test/", "title": "X1"},
]})

def get_me(request: requests.Request, context):
auth = request.headers.get("Authorization")
return {"user_id": auth}

requests_mock.get("https://b1.test/v1/me", json=get_me)

multi_backend_connection = MultiBackendConnection({"b1": domain1})
con1 = multi_backend_connection.get_connection("b1")

configured_providers = [
OidcProvider("ax", "https://x.test", "A-X"),
OidcProvider("ay", "https://y.test", "A-Y"),
]

agg_providers = multi_backend_connection.build_oidc_handling(configured_providers)
assert agg_providers == [OidcProvider(id="ax", issuer="https://x.test", title="A-X", scopes=["openid"])]
warnings = "\n".join(r.getMessage() for r in caplog.records if r.levelno == logging.WARNING)
assert warnings == ""

# Fake aggregator request containing bearer token for aggregator providers
request = flask.Request(environ={"HTTP_AUTHORIZATION": "Bearer oidc/ax/yadayadayada"})
with con1.authenticated_from_request(request=request):
assert con1.get("/me").json() == {"user_id": "Bearer oidc/x1/yadayadayada"}

# Change backend's oidc config, clear its cache and rebuild OIDC handling
requests_mock.get(domain1 + "/credentials/oidc", json={"providers": [
{"id": "y1", "issuer": "https://y.test/", "title": "Y1"},
]})
multi_backend_connection._cache.flush_all()
agg_providers = multi_backend_connection.build_oidc_handling(configured_providers)
assert agg_providers == [OidcProvider(id="ay", issuer="https://y.test", title="A-Y", scopes=["openid"])]
warnings = "\n".join(r.getMessage() for r in caplog.records if r.levelno == logging.WARNING)
assert "Changing OIDC provider mapping" in warnings

# Try old auth headers
request = flask.Request(environ={"HTTP_AUTHORIZATION": "Bearer oidc/ax/yadayadayada"})
with con1.authenticated_from_request(request=request):
assert con1.get("/me").json() == {"user_id": "Bearer oidc/ax/yadayadayada"}

warnings = "\n".join(r.getMessage() for r in caplog.records if r.levelno == logging.WARNING)
assert "OIDC provider mapping failure" in warnings

# New headers
request = flask.Request(environ={"HTTP_AUTHORIZATION": "Bearer oidc/ay/yadayadayada"})
with con1.authenticated_from_request(request=request):
assert con1.get("/me").json() == {"user_id": "Bearer oidc/y1/yadayadayada"}

0 comments on commit 8c91d9a

Please sign in to comment.