Skip to content

Commit a49881d

Browse files
committed
squashme: minor fixes
1 parent a857078 commit a49881d

File tree

3 files changed

+39
-12
lines changed

3 files changed

+39
-12
lines changed

renku/ui/service/entrypoint.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@
4040
)
4141
from renku.ui.service.logger import service_log
4242
from renku.ui.service.serializers.headers import JWT_TOKEN_SECRET
43-
from renku.ui.service.utils.json_encoder import SvcJSONProvider
4443
from renku.ui.service.utils import jwk_client
44+
from renku.ui.service.utils.json_encoder import SvcJSONProvider
4545
from renku.ui.service.views import error_response
4646
from renku.ui.service.views.apispec import apispec_blueprint
4747
from renku.ui.service.views.cache import cache_blueprint

renku/ui/service/serializers/headers.py

+22-4
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
from typing import cast
2121

2222
import jwt
23-
from flask import app
24-
from marshmallow import Schema, ValidationError, fields, post_load
23+
from flask import current_app
24+
from marshmallow import Schema, ValidationError, fields, post_load, pre_load
2525
from werkzeug.utils import secure_filename
2626

2727
JWT_TOKEN_SECRET = os.getenv("RENKU_JWT_TOKEN_SECRET", "bW9menZ3cnh6cWpkcHVuZ3F5aWJycmJn")
@@ -96,9 +96,9 @@ def decode_token(token):
9696
def decode_user(data):
9797
"""Extract renku user from the Keycloak ID token which is a JWT."""
9898
try:
99-
jwk = cast(jwt.PyJWKClient, app.config["KEYCLOAK_JWK_CLIENT"])
99+
jwk = cast(jwt.PyJWKClient, current_app.config["KEYCLOAK_JWK_CLIENT"])
100100
key = jwk.get_signing_key_from_jwt(data)
101-
decoded = jwt.decode(data, key=key, algorithms=["RS256"], audience="renku")
101+
decoded = jwt.decode(data, key=key.key, algorithms=["RS256"], audience="renku")
102102
except jwt.PyJWTError:
103103
# NOTE: older tokens used to be signed with HS256 so use this as a backup if the validation with RS256
104104
# above fails. We used to need HS256 because a step that is now removed was generating an ID token and
@@ -110,6 +110,24 @@ def decode_user(data):
110110
class IdentityHeaders(Schema):
111111
"""User identity schema."""
112112

113+
@pre_load
114+
def lowercase_required_headers(self, data, **kwargs):
115+
# NOTE: App flask headers are immutable and raise an error when modified so we copy them here
116+
output = {}
117+
if "Authorization" in data:
118+
output["authorization"] = data["Authorization"]
119+
elif "authorization" in data:
120+
output["authorization"] = data["authorization"]
121+
122+
if "Renku-User" in data:
123+
output["renku-user"] = data["Renku-User"]
124+
elif "Renku-user" in data:
125+
output["renku-user"] = data["Renku-user"]
126+
elif "renku-user":
127+
output["renku-user"] = data["renku-user"]
128+
129+
return output
130+
113131
@post_load
114132
def set_user(self, data, **kwargs):
115133
"""Extract user object from a JWT."""

renku/ui/service/utils/__init__.py

+16-7
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,18 @@
1414
# See the License for the specific language governing permissions and
1515
# limitations under the License.
1616
"""Renku service utility functions."""
17+
import os
18+
import urllib
1719
from time import sleep
1820
from typing import Any, Dict, Optional, overload
1921

2022
import requests
21-
import urllib
2223
from jwt import PyJWKClient
2324

25+
from renku.core.util.requests import get
2426
from renku.ui.service.config import CACHE_PROJECTS_PATH, CACHE_UPLOADS_PATH, OIDC_URL
2527
from renku.ui.service.errors import ProgramInternalError
2628
from renku.ui.service.logger import service_log
27-
from renku.core.util.requests import get
2829

2930

3031
def make_project_path(user, project):
@@ -101,28 +102,36 @@ def oidc_discovery() -> Dict[str, Any]:
101102
retries = 0
102103
max_retries = 30
103104
sleep_seconds = 2
105+
renku_domain = os.environ.get("RENKU_DOMAIN")
106+
if not renku_domain:
107+
raise ProgramInternalError(
108+
error_message="Cannot perform OIDC discovery without the renku domain expected "
109+
"to be found in the RENKU_DOMAIN environment variable."
110+
)
111+
full_oidc_url = f"http://{renku_domain}{OIDC_URL}"
104112
while True:
105113
retries += 1
106114
try:
107-
res: requests.Response = get(OIDC_URL)
115+
res: requests.Response = get(full_oidc_url)
108116
except (requests.exceptions.HTTPError, urllib.error.HTTPError) as e:
109117
if not retries < max_retries:
110118
service_log.error("Failed to get OIDC discovery data after all retries - the server cannot start.")
111119
raise e
112120
service_log.info(
113-
f"Failed to get OIDC discovery data from {OIDC_URL}, sleeping for {sleep_seconds} seconds and retrying"
121+
f"Failed to get OIDC discovery data from {full_oidc_url}, "
122+
f"sleeping for {sleep_seconds} seconds and retrying"
114123
)
115124
sleep(sleep_seconds)
116125
else:
117-
service_log.info(f"Successfully fetched OIDC discovery data from {OIDC_URL}")
126+
service_log.info(f"Successfully fetched OIDC discovery data from {full_oidc_url}")
118127
return res.json()
119128

120129

121130
def jwk_client() -> PyJWKClient:
122-
"""Return a JWK client for Keycloak that can be used to provide JWT keys for JWT signature validation"""
131+
"""Return a JWK client for Keycloak that can be used to provide JWT keys for JWT signature validation."""
123132
oidc_data = oidc_discovery()
124133
jwks_uri = oidc_data.get("jwks_uri")
125134
if not jwks_uri:
126-
raise ProgramInternalError(error_message="Could not find JWK URI in the OIDC discovery data")
135+
raise ProgramInternalError(error_message="Could not find jwks_uri in the OIDC discovery data")
127136
jwk = PyJWKClient(jwks_uri)
128137
return jwk

0 commit comments

Comments
 (0)