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

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

commit 93bd4082f14849f4c52ad2185980f1a283ecccb2
Author: Jürg Billeter <[email protected]>
AuthorDate: Fri Jun 21 14:41:38 2024 +0200

    _remotespec.py: Add `access-token-reload-interval` config
---
 doc/source/using_config.rst                |  7 +++++++
 src/buildstream/_cas/casdprocessmanager.py |  4 ++++
 src/buildstream/_remotespec.py             | 30 ++++++++++++++++++++++--------
 3 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/doc/source/using_config.rst b/doc/source/using_config.rst
index cf42119be..a8d70db90 100644
--- a/doc/source/using_config.rst
+++ b/doc/source/using_config.rst
@@ -151,6 +151,7 @@ toplevel of your configuration file, like so:
          client-cert: client.crt
          client-key: client.key
          access-token: access.token
+         access-token-reload-interval: 60
 
 
 Attributes
@@ -712,6 +713,7 @@ The ``auth`` configuration block looks like this:
      client-cert: client.crt
      client-key: client.key
      access-token: access.token
+     access-token-reload-interval: 60
 
 
 Attributes
@@ -740,6 +742,11 @@ Attributes
 
   The path to a token for optional HTTP bearer authentication.
 
+* ``access-token-reload-interval``
+
+  The reload interval in minutes for the specified access token.
+  If not specified, automatic reloading is disabled.
+
 Normally, only the ``server-cert`` is required to securely *download* data
 from remote cache services, while both the ``client-key`` and ``client-cert``
 is required to securely *upload* data to the server.
diff --git a/src/buildstream/_cas/casdprocessmanager.py 
b/src/buildstream/_cas/casdprocessmanager.py
index f65ad4bcc..ab497a8ac 100644
--- a/src/buildstream/_cas/casdprocessmanager.py
+++ b/src/buildstream/_cas/casdprocessmanager.py
@@ -95,6 +95,10 @@ class CASDProcessManager:
                 
casd_args.append("--cas-client-cert={}".format(remote_cache_spec.client_cert_file))
             if remote_cache_spec.access_token_file:
                 
casd_args.append("--cas-access-token={}".format(remote_cache_spec.access_token_file))
+                if remote_cache_spec.access_token_reload_interval is not None:
+                    casd_args.append(
+                        
"--cas-token-reload-interval={}".format(remote_cache_spec.access_token_reload_interval)
+                    )
             if remote_cache_spec.keepalive_time is not None:
                 
casd_args.append("--cas-keepalive-time={}".format(remote_cache_spec.keepalive_time))
 
diff --git a/src/buildstream/_remotespec.py b/src/buildstream/_remotespec.py
index 0845a35cd..6f97d7a38 100644
--- a/src/buildstream/_remotespec.py
+++ b/src/buildstream/_remotespec.py
@@ -72,6 +72,7 @@ class RemoteSpec:
         client_key: str = None,
         client_cert: str = None,
         access_token: str = None,
+        access_token_reload_interval: Optional[int] = None,
         instance_name: Optional[str] = None,
         connection_config: Optional[MappingNode] = None,
         spec_node: Optional[MappingNode] = None,
@@ -98,6 +99,7 @@ class RemoteSpec:
         self.client_key_file: Optional[str] = client_key
         self.client_cert_file: Optional[str] = client_cert
         self.access_token_file: Optional[str] = access_token
+        self.access_token_reload_interval: Optional[int] = 
access_token_reload_interval
 
         #
         # Private members
@@ -136,6 +138,7 @@ class RemoteSpec:
                 self.client_key_file,
                 self.client_cert_file,
                 self.access_token_file,
+                self.access_token_reload_interval,
                 self.keepalive_time,
             )
         )
@@ -237,6 +240,8 @@ class RemoteSpec:
             remote.client_cert = self.client_cert
         if self.access_token_file:
             remote.access_token_path = self.access_token_file
+            if self.access_token_reload_interval is not None:
+                
remote.access_token_reload_interval.FromSeconds(self.access_token_reload_interval
 * 60)
         if self.keepalive_time is not None:
             remote.keepalive_time.FromSeconds(self.keepalive_time)
 
@@ -263,6 +268,7 @@ class RemoteSpec:
         client_key: Optional[str] = None
         client_cert: Optional[str] = None
         access_token: Optional[str] = None
+        access_token_reload_interval: Optional[int] = None
         push: bool = False
         remote_type: str = RemoteType.ENDPOINT
 
@@ -287,7 +293,9 @@ class RemoteSpec:
 
         auth_node = spec_node.get_mapping("auth", None)
         if auth_node:
-            server_cert, client_key, client_cert, access_token = 
cls._parse_auth(auth_node, basedir)
+            server_cert, client_key, client_cert, access_token, 
access_token_reload_interval = cls._parse_auth(
+                auth_node, basedir
+            )
 
         connection_config = spec_node.get_mapping("connection-config", None)
 
@@ -299,6 +307,7 @@ class RemoteSpec:
             client_key=client_key,
             client_cert=client_cert,
             access_token=access_token,
+            access_token_reload_interval=access_token_reload_interval,
             instance_name=instance_name,
             connection_config=connection_config,
             spec_node=spec_node,
@@ -428,28 +437,33 @@ class RemoteSpec:
     #    basedir: The base directory which cert files are relative to, or None
     #
     # Returns:
-    #    A 4 tuple containing the filenames for the server-cert,
-    #    the client-key, the client-cert and the access-token
+    #    A 5 tuple containing the filenames for the server-cert, the 
client-key,
+    #    the client-cert, the access-token and the access-token-reload-interval
     #
     @classmethod
     def _parse_auth(
         cls, auth_node: MappingNode, basedir: Optional[str] = None
-    ) -> Tuple[Optional[str], Optional[str], Optional[str], Optional[str]]:
+    ) -> Tuple[Optional[str], Optional[str], Optional[str], Optional[str], 
Optional[int]]:
 
-        auth_keys = ["server-cert", "client-key", "client-cert", 
"access-token"]
+        auth_path_keys = ["server-cert", "client-key", "client-cert", 
"access-token"]
+        auth_int_keys = ["access-token-reload-interval"]
         auth_values = {}
-        auth_node.validate_keys(auth_keys)
+        auth_node.validate_keys(auth_path_keys + auth_int_keys)
 
-        for key in auth_keys:
+        for key in auth_path_keys:
             value = auth_node.get_str(key, None)
             if value:
                 value = cls._resolve_path(value, basedir)
             auth_values[key] = value
 
+        for key in auth_int_keys:
+            auth_values[key] = auth_node.get_int(key, None)
+
         server_cert = auth_values["server-cert"]
         client_key = auth_values["client-key"]
         client_cert = auth_values["client-cert"]
         access_token = auth_values["access-token"]
+        access_token_reload_interval = 
auth_values["access-token-reload-interval"]
 
         if client_key and not client_cert:
             provenance = auth_node.get_node("client-key").get_provenance()
@@ -463,7 +477,7 @@ class RemoteSpec:
                 "{}: 'client-cert' was specified without 
'client-key'".format(provenance), LoadErrorReason.INVALID_DATA
             )
 
-        return server_cert, client_key, client_cert, access_token
+        return server_cert, client_key, client_cert, access_token, 
access_token_reload_interval
 
     # _load_credential_files():
     #

Reply via email to