This is an automated email from the ASF dual-hosted git repository.

juergbi pushed a commit to branch juerg/downloadable-auth
in repository https://gitbox.apache.org/repos/asf/buildstream.git

commit 0294dae939d667c87a3a00ba2ebec08b628b3761
Author: Jürg Billeter <[email protected]>
AuthorDate: Fri Apr 12 18:36:02 2024 +0200

    DownloadableFileSource: Replace `auth-header-format` with `http-auth`
---
 src/buildstream/downloadablefilesource.py          | 60 +++++++---------------
 tests/sources/tar.py                               |  2 +-
 .../tar/fetch/sourcemirrors/bearermirror.py        |  2 +-
 3 files changed, 21 insertions(+), 43 deletions(-)

diff --git a/src/buildstream/downloadablefilesource.py 
b/src/buildstream/downloadablefilesource.py
index 77e2bfa1c..5d7db4bcf 100644
--- a/src/buildstream/downloadablefilesource.py
+++ b/src/buildstream/downloadablefilesource.py
@@ -25,10 +25,10 @@ Any derived classes must write their own stage() and 
get_unique_key()
 implementation.
 
 
-SourceMirror extra data "auth-header-format"
+SourceMirror extra data "http-auth"
 --------------------------------------------
 The DownloadableFileSource, and consequently any :class:`Source 
<buildstream.source.Source>`
-implementations which derive from DownloadableFileSource, support the 
"auth-header-format"
+implementations which derive from DownloadableFileSource, support the 
"http-auth"
 extra data returned by :class:`SourceMirror 
<buildstream.sourcemirror.SourceMirror>` plugins
 through :func:`Source.translate_url() 
<buildstream.source.Source.translate_url>`.
 
@@ -56,15 +56,14 @@ to add an authorization header to the ``GET`` requests.
         ) -> str:
 
             #
-            # Set the "auth-header-format" extra data
+            # Set the "http-auth" extra data
             #
             if extra_data is not None:
-                extra_data["auth-header-format"] = "Bearer {password}"
+                extra_data["http-auth"] = "bearer"
 
             return alias_substitute_url + source_url
 
-The "auth-header-format" value **must** contain the ``{password}`` expression, 
which
-will be substituted with the corresponding password found in the user's 
``~/.netrc``.
+Only the "http-auth" value ``bearer`` is supported.
 
 
 **Example:**
@@ -78,8 +77,7 @@ user's ``~/.netrc``:
    flying-ponies.com
        password 1234
 
-Assuming the ``"auth-header-format"`` value of ``Bearer {password}`` and the 
configured password ``1234``,
-the DownloadableFileSource will add the following header to the ``GET`` 
request to download the file:
+DownloadableFileSource will add the following header to the ``GET`` request to 
download the file:
 
 .. code::
 
@@ -148,28 +146,20 @@ class _NetrcPasswordManager:
             return login, password
 
 
-def _download_file(opener_creator, url, etag, directory):
-    opener = opener_creator.get_url_opener()
+def _download_file(opener_creator, url, etag, directory, bearer_auth):
+    opener = opener_creator.get_url_opener(bearer_auth)
     default_name = os.path.basename(url)
     request = urllib.request.Request(url)
     request.add_header("Accept", "*/*")
     request.add_header("User-Agent", "BuildStream/2")
 
-    if opener_creator.auth_header_format:
-        if not opener_creator.netrc_config:
-            raise SourceError("Authorization header format specified without 
supporting netrc")
-
+    if opener_creator.netrc_config and bearer_auth:
         parts = urllib.parse.urlsplit(url)
         entry = opener_creator.netrc_config.authenticators(parts.hostname)
-        if not entry:
-            raise SourceError(
-                "Authorization header format specified without provided 
password",
-                detail="No password specified in netrc for hostname: 
{}".format(parts.hostname),
-            )
-
-        _, _, password = entry
-        auth_header = 
opener_creator.auth_header_format.format(password=password)
-        request.add_header("Authorization", auth_header)
+        if entry:
+            _, _, password = entry
+            auth_header = "Bearer " + password
+            request.add_header("Authorization", auth_header)
 
     if etag is not None:
         request.add_header("If-None-Match", etag)
@@ -224,18 +214,7 @@ class DownloadableFileSource(Source):
 
         extra_data = {}
         self.url = self.translate_url(self.original_url, extra_data=extra_data)
-        self.auth_header_format = extra_data.get("auth-header-format")
-
-        #
-        # Validate the auth header format for a `{password}` formatting 
identifier
-        #
-        if self.auth_header_format:
-            try:
-                self.auth_header_format.format(password="dummy")
-            except KeyError as e:
-                raise SourceError(
-                    "SourceMirror specified auth-header-format without a 
password", detail=self.auth_header_format
-                ) from e
+        self.bearer_auth = extra_data.get("http-auth") == "bearer"
 
         self._mirror_dir = os.path.join(self.get_mirror_directory(), 
utils.url_directory_name(self.original_url))
 
@@ -318,10 +297,10 @@ class DownloadableFileSource(Source):
             else:
                 etag = None
 
-            url_opener_creator = _UrlOpenerCreator(self._parse_netrc(), 
self.auth_header_format)
+            url_opener_creator = _UrlOpenerCreator(self._parse_netrc())
 
             local_file, new_etag, error = self.blocking_activity(
-                _download_file, (url_opener_creator, self.url, etag, td), 
activity_name
+                _download_file, (url_opener_creator, self.url, etag, td, 
self.bearer_auth), activity_name
             )
 
             if error:
@@ -374,12 +353,11 @@ class DownloadableFileSource(Source):
 
 
 class _UrlOpenerCreator:
-    def __init__(self, netrc_config, auth_header_format):
+    def __init__(self, netrc_config):
         self.netrc_config = netrc_config
-        self.auth_header_format = auth_header_format
 
-    def get_url_opener(self):
-        if not self.auth_header_format and self.netrc_config:
+    def get_url_opener(self, bearer_auth):
+        if self.netrc_config and not bearer_auth:
             netrc_pw_mgr = _NetrcPasswordManager(self.netrc_config)
             http_auth = urllib.request.HTTPBasicAuthHandler(netrc_pw_mgr)
             ftp_handler = _NetrcFTPOpener(self.netrc_config)
diff --git a/tests/sources/tar.py b/tests/sources/tar.py
index 2ba3833a3..391912cac 100644
--- a/tests/sources/tar.py
+++ b/tests/sources/tar.py
@@ -384,7 +384,7 @@ def test_use_netrc_bearer_auth(cli, datafiles, tmpdir):
 
         #
         # Configure the project to load our source mirror plugin which
-        # reports the "auth-header-format" extra data
+        # reports the "http-auth" extra data
         #
         additional_config = {
             "aliases": {"tmpdir": server.base_url()},
diff --git a/tests/sources/tar/fetch/sourcemirrors/bearermirror.py 
b/tests/sources/tar/fetch/sourcemirrors/bearermirror.py
index 1acaa621d..f8a6c7143 100644
--- a/tests/sources/tar/fetch/sourcemirrors/bearermirror.py
+++ b/tests/sources/tar/fetch/sourcemirrors/bearermirror.py
@@ -25,7 +25,7 @@ class Sample(SourceMirror):
     ) -> str:
 
         if extra_data is not None:
-            extra_data["auth-header-format"] = "Bearer {password}"
+            extra_data["http-auth"] = "bearer"
 
         return self.aliases[alias][0] + source_url
 

Reply via email to