From 992681df0980ef587bc2fa394fa6a4f5438c7ba1 Mon Sep 17 00:00:00 2001 From: Matyas Selmeci Date: Mon, 30 Oct 2023 17:54:55 -0500 Subject: [PATCH] Ensure the title of the 'Issuer' block is no more than 50 characters - chop off the `https://` to give us a little more room - use a sha1 hash if the title is still too big --- src/tests/test_stashcache.py | 11 +++++++---- src/webapp/data_federation.py | 15 ++++++++++++++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/tests/test_stashcache.py b/src/tests/test_stashcache.py index 8b0175668..05d4d3d62 100644 --- a/src/tests/test_stashcache.py +++ b/src/tests/test_stashcache.py @@ -1,6 +1,7 @@ from configparser import ConfigParser import copy import flask +import hashlib import pytest import re from pytest_mock import MockerFixture @@ -112,15 +113,17 @@ def test_scitokens_issuer_character_limit(self, client: flask.Flask): cp = ConfigParser() cp.read_string(origin_scitokens_conf, "origin_scitokens.conf") + hasher = hashlib.sha1() + hasher.update(b"test.wisc.edu/long-name-that-is-over-50-characters-even-if-you-strip-off-https") + hashed_title = hasher.hexdigest() try: assert "Global" in cp, "Missing Global section" - assert "Issuer https://test.wisc.edu" in cp, \ + assert "Issuer test.wisc.edu" in cp, \ "Issuer with reasonable length missing" assert "Issuer issuer-thats-50-characters-long-if-you.chop" in cp, \ "Issuer that just barely fits if you chop off the scheme missing" - assert (cp["Issuer issuer-thats-50-characters-long-if-you.chop"]["issuer"] == - "https://issuer-thats-50-characters-long-if-you.chop"), \ - "Unexpected issuer in a section we modified" + assert f"Issuer {hashed_title}" in cp, \ + "Issuer that's needed to be hashed missing" assert not re.search(r"^\[[^]]{51}", origin_scitokens_conf, re.MULTILINE), \ "Section over 50 chars long found" # ^^ easier to regexp this diff --git a/src/webapp/data_federation.py b/src/webapp/data_federation.py index 06a700fe3..4e17ce5e5 100644 --- a/src/webapp/data_federation.py +++ b/src/webapp/data_federation.py @@ -1,3 +1,4 @@ +import hashlib import urllib import urllib.parse from collections import OrderedDict @@ -76,6 +77,8 @@ def get_authfile_id(self): class SciTokenAuth(AuthMethod): used_in_scitokens_conf = True + ISSUER_TITLE_MAX_LENGTH = 43 # 50 - the length of 'Issuer ' + # xrootd/xrootd#2074 def __init__(self, issuer: str, base_path: str, restricted_path: Optional[str], map_subject: bool): self.issuer = issuer @@ -90,7 +93,17 @@ def __str__(self): def get_scitokens_conf_block(self, service_name: str): if service_name not in [XROOTD_CACHE_SERVER, XROOTD_ORIGIN_SERVER]: raise ValueError(f"service_name must be '{XROOTD_CACHE_SERVER}' or '{XROOTD_ORIGIN_SERVER}'") - block = (f"[Issuer {self.issuer}]\n" + + issuer_title = self.issuer + if issuer_title.startswith("https://"): + issuer_title = issuer_title[8:] + # title is too long; replace it with a hash + if len(issuer_title) > self.ISSUER_TITLE_MAX_LENGTH: + hasher = hashlib.sha1() # sha1 hex digest is 40 chars + hasher.update(issuer_title.encode("utf-8", errors="ignore")) + issuer_title = hasher.hexdigest() + + block = (f"[Issuer {issuer_title}]\n" f"issuer = {self.issuer}\n" f"base_path = {self.base_path}\n") if self.restricted_path: