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

markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/main by this push:
     new adb9c7e7db Fix BZ 69598 - release service account token if it changes
adb9c7e7db is described below

commit adb9c7e7dbb559eff3520d059f24a90dd64dd6b0
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Feb 27 08:49:20 2025 +0000

    Fix BZ 69598 - release service account token if it changes
---
 .../cloud/KubernetesMembershipProvider.java        | 41 ++++++++++++++++++++--
 .../membership/cloud/LocalStrings.properties       |  1 +
 .../membership/cloud/TokenStreamProvider.java      |  9 ++++-
 webapps/docs/changelog.xml                         | 10 ++++++
 4 files changed, 58 insertions(+), 3 deletions(-)

diff --git 
a/java/org/apache/catalina/tribes/membership/cloud/KubernetesMembershipProvider.java
 
b/java/org/apache/catalina/tribes/membership/cloud/KubernetesMembershipProvider.java
index 4d4d35e5bd..59ff620b23 100644
--- 
a/java/org/apache/catalina/tribes/membership/cloud/KubernetesMembershipProvider.java
+++ 
b/java/org/apache/catalina/tribes/membership/cloud/KubernetesMembershipProvider.java
@@ -24,6 +24,8 @@ import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.FileSystems;
 import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.FileTime;
 import java.time.Duration;
 import java.time.Instant;
 import java.util.ArrayList;
@@ -43,8 +45,13 @@ import org.apache.tomcat.util.json.JSONParser;
  */
 
 public class KubernetesMembershipProvider extends CloudMembershipProvider {
+
     private static final Log log = 
LogFactory.getLog(KubernetesMembershipProvider.class);
 
+    private Path saTokenPath;
+    private FileTime saTokenLastModifiedTime;
+
+
     @Override
     public void start(int level) throws Exception {
         if ((level & MembershipService.MBR_RX) == 0) {
@@ -80,8 +87,10 @@ public class KubernetesMembershipProvider extends 
CloudMembershipProvider {
                 saTokenFile = 
"/var/run/secrets/kubernetes.io/serviceaccount/token";
             }
             try {
-                byte[] bytes = 
Files.readAllBytes(FileSystems.getDefault().getPath(saTokenFile));
+                saTokenPath = FileSystems.getDefault().getPath(saTokenFile);
+                byte[] bytes = Files.readAllBytes(saTokenPath);
                 streamProvider = new TokenStreamProvider(new String(bytes, 
StandardCharsets.US_ASCII), caCertFile);
+                saTokenLastModifiedTime = 
Files.getLastModifiedTime(saTokenPath);
             } catch (IOException e) {
                 
log.error(sm.getString("kubernetesMembershipProvider.streamError"), e);
             }
@@ -122,6 +131,7 @@ public class KubernetesMembershipProvider extends 
CloudMembershipProvider {
         heartbeat();
     }
 
+
     @Override
     public boolean stop(int level) throws Exception {
         try {
@@ -131,12 +141,15 @@ public class KubernetesMembershipProvider extends 
CloudMembershipProvider {
         }
     }
 
+
     @Override
     protected Member[] fetchMembers() {
         if (streamProvider == null) {
             return new Member[0];
         }
 
+        reloadSaTokenIfChanged();
+
         List<MemberImpl> members = new ArrayList<>();
 
         try (InputStream stream = streamProvider.openStream(url, headers, 
connectionTimeout, readTimeout);
@@ -149,6 +162,31 @@ public class KubernetesMembershipProvider extends 
CloudMembershipProvider {
         return members.toArray(new Member[0]);
     }
 
+
+    private void reloadSaTokenIfChanged() {
+        if (saTokenPath == null) {
+            // Service account token not being used.
+            return;
+        }
+        if (!Files.exists(saTokenPath)) {
+            // If the service account token is being used, this path should 
exist
+            
log.warn(sm.getString("kubernetesMembershipProvider.serviceAccountTokenMissing",
 saTokenPath));
+            return;
+        }
+        try {
+            FileTime oldSaTokenLastModifiedTime = saTokenLastModifiedTime;
+            saTokenLastModifiedTime = Files.getLastModifiedTime(saTokenPath);
+            // Use != to protect against clock issues
+            if (!saTokenLastModifiedTime.equals(oldSaTokenLastModifiedTime)) {
+                byte[] bytes = Files.readAllBytes(saTokenPath);
+                ((TokenStreamProvider)streamProvider).setToken(new 
String(bytes, StandardCharsets.US_ASCII));
+            }
+        } catch (IOException e) {
+            
log.error(sm.getString("kubernetesMembershipProvider.streamError"), e);
+        }
+    }
+
+
     @SuppressWarnings("unchecked")
     protected void parsePods(Reader reader, List<MemberImpl> members) {
         JSONParser parser = new JSONParser(reader);
@@ -239,5 +277,4 @@ public class KubernetesMembershipProvider extends 
CloudMembershipProvider {
             log.error(sm.getString("kubernetesMembershipProvider.jsonError"), 
e);
         }
     }
-
 }
diff --git 
a/java/org/apache/catalina/tribes/membership/cloud/LocalStrings.properties 
b/java/org/apache/catalina/tribes/membership/cloud/LocalStrings.properties
index 77bc9bbdcc..38b5df453b 100644
--- a/java/org/apache/catalina/tribes/membership/cloud/LocalStrings.properties
+++ b/java/org/apache/catalina/tribes/membership/cloud/LocalStrings.properties
@@ -35,6 +35,7 @@ kubernetesMembershipProvider.jsonError=JSON error
 kubernetesMembershipProvider.memberError=Error creating member
 kubernetesMembershipProvider.noKey=Client certificate key was not specified in 
the environment
 kubernetesMembershipProvider.noNamespace=Namespace not set
+kubernetesMembershipProvider.serviceAccountTokenMissing=Service account token 
not found at [{0}]
 kubernetesMembershipProvider.streamError=Failed to open stream
 
 tokenStream.failedConnection=Failed connection to [{0}] with token [{1}]
diff --git 
a/java/org/apache/catalina/tribes/membership/cloud/TokenStreamProvider.java 
b/java/org/apache/catalina/tribes/membership/cloud/TokenStreamProvider.java
index 0c66e5e4d9..c1efc7a6e6 100644
--- a/java/org/apache/catalina/tribes/membership/cloud/TokenStreamProvider.java
+++ b/java/org/apache/catalina/tribes/membership/cloud/TokenStreamProvider.java
@@ -29,6 +29,7 @@ public class TokenStreamProvider extends 
AbstractStreamProvider {
     private String token;
     private SSLSocketFactory factory;
 
+
     TokenStreamProvider(String token, String caCertFile) throws Exception {
         this.token = token;
         TrustManager[] trustManagers = configureCaCert(caCertFile);
@@ -37,11 +38,18 @@ public class TokenStreamProvider extends 
AbstractStreamProvider {
         this.factory = context.getSocketFactory();
     }
 
+
     @Override
     protected SSLSocketFactory getSocketFactory() {
         return factory;
     }
 
+
+    protected void setToken(String token) {
+        this.token = token;
+    }
+
+
     @Override
     public InputStream openStream(String url, Map<String,String> headers, int 
connectTimeout, int readTimeout)
             throws IOException {
@@ -56,5 +64,4 @@ public class TokenStreamProvider extends 
AbstractStreamProvider {
             throw new IOException(sm.getString("tokenStream.failedConnection", 
url, token), e);
         }
     }
-
 }
\ No newline at end of file
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index ce102da757..6d324572ed 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -220,6 +220,16 @@
       <!-- Entries for backport and removal before 12.0.0-M1 below this line 
-->
     </changelog>
   </subsection>
+  <subsection name="Cluster">
+    <changelog>
+      <!-- Entries for backport and removal before 12.0.0-M1 below this line 
-->
+      <add>
+        <bug>69598</bug>: Add detection of service account token changes to the
+        <code>KubernetesMembershipProvider</code> implementation and reload the
+        token if it changes. Based on a patch by Miroslav Jezbera. (markt)
+      </add>
+    </changelog>
+  </subsection>
   <subsection name="Web applications">
     <changelog>
       <!-- Entries for backport and removal before 12.0.0-M1 below this line 
-->


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to