From bcf3bdf8414a13ec1e00d13710a236323e87e503 Mon Sep 17 00:00:00 2001 From: Weston Carvalho Date: Fri, 10 Feb 2023 13:33:33 -0600 Subject: [PATCH] gerrit.py: Support `.googlesource.com` credentials The scripts currently check that the requested domain exactly matches one of the domains in the user's `.gitcookies` file, which causes a "Cannot find the domain" error if the user's credentials are for all of `googlesource.com`. Change-Id: Ifed117e7d76c8678558720db1d518d59d986521d --- tools/repo_pull/gerrit.py | 42 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/tools/repo_pull/gerrit.py b/tools/repo_pull/gerrit.py index e74b90779..a1211e1d8 100755 --- a/tools/repo_pull/gerrit.py +++ b/tools/repo_pull/gerrit.py @@ -117,13 +117,53 @@ def load_auth_credentials(cookie_file_path): return load_auth_credentials_from_file(cookie_file) +def _domain_matches(domain_name, domain_pattern): + """Returns whether `domain_name` matches `domain_pattern` under the + definition of RFC 6265 (Section 4.1.2.3 and 5.1.3). + + Pattern matching rule defined by Section 5.1.3: + + >>> _domain_matches('example.com', 'example.com') + True + >>> _domain_matches('a.example.com', 'example.com') + True + >>> _domain_matches('aaaexample.com', 'example.com') + False + + If the domain pattern starts with '.', '.' is ignored (Section 4.1.2.3): + + >>> _domain_matches('a.example.com', '.example.com') + True + >>> _domain_matches('example.com', '.example.com') + True + + See also: + https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.2.3 + https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.3 + """ + domain_pattern = domain_pattern.removeprefix('.') + return (domain_name == domain_pattern or + (domain_name.endswith(domain_pattern) and + domain_name[-len(domain_pattern) - 1] == '.')) + + +def _find_auth_credentials(credentials, domain): + """Find the first set of login credentials (username, password) + that `domain` matches. + """ + for domain_pattern, login in credentials.items(): + if _domain_matches(domain, domain_pattern): + return login + raise KeyError('Domain {} not found'.format(domain)) + + def create_url_opener(cookie_file_path, domain): """Load username and password from .gitcookies and return a URL opener with an authentication handler.""" # Load authentication credentials credentials = load_auth_credentials(cookie_file_path) - username, password = credentials[domain] + username, password = _find_auth_credentials(credentials, domain) # Create URL opener with authentication handler auth_handler = HTTPBasicAuthHandler()