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

madhan pushed a commit to branch ranger-2.8
in repository https://gitbox.apache.org/repos/asf/ranger.git


The following commit(s) were added to refs/heads/ranger-2.8 by this push:
     new 7182ae3fc RANGER-5475: add JWT support in RangerRESTClient (#831)
7182ae3fc is described below

commit 7182ae3fc80c6afd3246727d8a862d396f3b89af
Author: Abhishek Kumar <[email protected]>
AuthorDate: Sat Jan 31 18:46:38 2026 -0800

    RANGER-5475: add JWT support in RangerRESTClient (#831)
    
    (cherry picked from commit f98a149d56fb4589cc47d03e55bd16b0adf4a153)
---
 .../ranger/plugin/util/RangerRESTClient.java       | 132 ++++++++++++++++++---
 .../tagsync/sink/tagadmin/TagAdminRESTSink.java    |   2 +-
 .../process/RangerUgSyncRESTClient.java            |   7 +-
 3 files changed, 118 insertions(+), 23 deletions(-)

diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTClient.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTClient.java
index 2b6d8030e..a1f72a934 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTClient.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTClient.java
@@ -19,9 +19,11 @@
 
 package org.apache.ranger.plugin.util;
 
+import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
+import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.security.KeyManagementException;
@@ -47,6 +49,7 @@
 import javax.ws.rs.core.Response;
 
 import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
+import com.sun.jersey.api.client.ClientRequest;
 import com.sun.jersey.api.client.filter.ClientFilter;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.Validate;
@@ -89,6 +92,10 @@ public class RangerRESTClient {
        public static final String RANGER_SSL_KEYMANAGER_ALGO_TYPE              
                         = KeyManagerFactory.getDefaultAlgorithm();
        public static final String RANGER_SSL_TRUSTMANAGER_ALGO_TYPE            
                 = TrustManagerFactory.getDefaultAlgorithm();
        public static final String RANGER_SSL_CONTEXT_ALGO_TYPE                 
                     = "TLSv1.2";
+       public static final String JWT_HEADER_PREFIX                            
     = "Bearer ";
+
+       private final List<String> configuredURLs;
+       private final String       propertyPrefix;
 
        private String  mUrl;
        private String  mSslConfigFileName;
@@ -103,23 +110,28 @@ public class RangerRESTClient {
        private String mTrustStoreURL;
        private String mTrustStoreAlias;
        private String mTrustStoreFile;
-       private String       mTrustStoreType;
-       private int          mRestClientConnTimeOutMs;
+       private String mTrustStoreType;
+       private int    mRestClientConnTimeOutMs;
        private int    mRestClientReadTimeOutMs;
        private int    maxRetryAttempts;
        private int    retryIntervalMs;
        private int    lastKnownActiveUrlIndex;
 
-       private final List<String> configuredURLs;
-
        private volatile Client client;
        private volatile Client cookieAuthClient;
-       private ClientFilter    basicAuthFilter = null;
+       private          ClientFilter jwtAuthFilter;
+       private          ClientFilter basicAuthFilter;
 
        public RangerRESTClient(String url, String sslConfigFileName, 
Configuration config) {
-               mUrl               = url;
-               mSslConfigFileName = sslConfigFileName;
-               configuredURLs     = StringUtil.getURLs(mUrl);
+               this(url, sslConfigFileName, config, getPropertyPrefix(config));
+       }
+
+       public RangerRESTClient(String url, String sslConfigFileName, 
Configuration config, String propertyPrefix) {
+               mUrl                = url;
+               mSslConfigFileName  = sslConfigFileName;
+               configuredURLs      = StringUtil.getURLs(mUrl);
+        this.propertyPrefix = propertyPrefix;
+
                if (StringUtil.isEmpty(url)) {
                        throw new IllegalArgumentException("Ranger URL is null 
or empty. Likely caused by incorrect configuration");
                } else {
@@ -205,6 +217,10 @@ public Client getClient() {
                return result;
        }
 
+       private static String getPropertyPrefix(Configuration config) {
+               return (config instanceof RangerPluginConfig) ? 
((RangerPluginConfig) config).getPropertyPrefix() : "ranger.plugin";
+       }
+
        private Client getCookieAuthClient() {
                Client ret = cookieAuthClient;
 
@@ -215,6 +231,10 @@ private Client getCookieAuthClient() {
                                if (ret == null) {
                                        cookieAuthClient = buildClient();
 
+                                       if (jwtAuthFilter != null) {
+                                               
cookieAuthClient.removeFilter(jwtAuthFilter);
+                                       }
+
                                        if (basicAuthFilter != null) {
                                                
cookieAuthClient.removeFilter(basicAuthFilter);
                                        }
@@ -257,8 +277,11 @@ public boolean verify(String urlHostName, SSLSession 
session) {
                        client = Client.create(config);
                }
 
-               if (basicAuthFilter != null && 
!client.isFilterPresent(basicAuthFilter)) {
-                       client.addFilter(basicAuthFilter);
+               // use JWT if present
+               ClientFilter authFilter = jwtAuthFilter != null ? jwtAuthFilter 
: basicAuthFilter;
+
+               if (authFilter != null && !client.isFilterPresent(authFilter)) {
+                       client.addFilter(authFilter);
                }
 
                // Set Connection Timeout and ReadTime for the PolicyRefresh
@@ -268,6 +291,23 @@ public boolean verify(String urlHostName, SSLSession 
session) {
                return client;
        }
 
+       private void setJWTFilter(String jwtAsString) {
+               if (StringUtils.isNotBlank(jwtAsString)) {
+                       LOG.info("Registering JWT auth header in REST client");
+
+                       jwtAuthFilter = new ClientFilter() {
+                               @Override
+                               public ClientResponse handle(ClientRequest 
clientRequest) throws ClientHandlerException {
+                                       
clientRequest.getHeaders().add("Authorization", JWT_HEADER_PREFIX + 
jwtAsString);
+
+                                       return getNext().handle(clientRequest);
+                               }
+                       };
+               } else {
+                       jwtAuthFilter = null;
+               }
+       }
+
        private void setBasicAuthFilter(String username, String password) {
                if (StringUtils.isNotEmpty(username) && 
StringUtils.isNotEmpty(password)) {
                        basicAuthFilter = new HTTPBasicAuthFilter(username, 
password);
@@ -311,22 +351,76 @@ private void init(Configuration config) {
 
                }
 
-               final String pluginPropertyPrefix;
-
-               if (config instanceof RangerPluginConfig) {
-                       pluginPropertyPrefix = ((RangerPluginConfig) 
config).getPropertyPrefix();
-               } else {
-                       pluginPropertyPrefix = "ranger.plugin";
-               }
+               String jwtAsString = fetchJWT(propertyPrefix, config);
+               String username    = config.get(propertyPrefix + 
".policy.rest.client.username");
+               String password    = config.get(propertyPrefix + 
".policy.rest.client.password");
 
-               String username = config.get(pluginPropertyPrefix + 
".policy.rest.client.username");
-               String password = config.get(pluginPropertyPrefix + 
".policy.rest.client.password");
+               setJWTFilter(jwtAsString);
 
                if (StringUtils.isNotBlank(username) && 
StringUtils.isNotBlank(password)) {
                        setBasicAuthFilter(username, password);
                }
        }
 
+       private String fetchJWT(String propertyPrefix, Configuration config) {
+               final String jwtSrc = config.get(propertyPrefix + 
".policy.rest.client.jwt.source");
+
+               if (StringUtils.isNotEmpty(jwtSrc)) {
+                       switch (jwtSrc) {
+                               case "env":
+                                       String jwtEnvVar = 
config.get(propertyPrefix + ".policy.rest.client.jwt.env");
+
+                                       if (StringUtils.isNotEmpty(jwtEnvVar)) {
+                                               String jwt = 
System.getenv(jwtEnvVar);
+
+                                               if 
(StringUtils.isNotBlank(jwt)) {
+                                                       return jwt;
+                                               }
+                                       }
+                                       break;
+
+                               case "file":
+                                       String jwtFilePath = 
config.get(propertyPrefix + ".policy.rest.client.jwt.file");
+
+                                       if 
(StringUtils.isNotEmpty(jwtFilePath)) {
+                                               File jwtFile = new 
File(jwtFilePath);
+
+                                               if (jwtFile.exists()) {
+                                                       try (BufferedReader 
reader = new BufferedReader(new FileReader(jwtFile))) {
+                                                               String line;
+
+                                                               while ((line = 
reader.readLine()) != null) {
+                                                                       if 
(StringUtils.isNotBlank(line) && !line.startsWith("#")) {
+                                                                               
return line;
+                                                                       }
+                                                               }
+                                                       } catch (IOException e) 
{
+                                                               
LOG.error("Failed to read JWT from file: {}", jwtFilePath, e);
+                                                       }
+                                               }
+                                       }
+                                       break;
+
+                               case "cred":
+                                       String credFilePath = 
config.get(propertyPrefix + ".policy.rest.client.jwt.cred.file");
+                                       String credAlias    = 
config.get(propertyPrefix + ".policy.rest.client.jwt.cred.alias");
+
+                                       if 
(StringUtils.isNotEmpty(credFilePath) && StringUtils.isNotEmpty(credAlias)) {
+                                               String jwt = 
RangerCredentialProvider.getInstance().getCredentialString(credFilePath, 
credAlias);
+
+                                               if 
(StringUtils.isNotBlank(jwt)) {
+                                                       return jwt;
+                                               }
+                                       }
+                                       break;
+                       }
+               } else {
+                       LOG.info("JWT source not configured, proceeding without 
JWT");
+               }
+
+               return null;
+       }
+
        private boolean isSslEnabled(String url) {
                return !StringUtils.isEmpty(url) && 
url.toLowerCase().startsWith("https");
        }
diff --git 
a/tagsync/src/main/java/org/apache/ranger/tagsync/sink/tagadmin/TagAdminRESTSink.java
 
b/tagsync/src/main/java/org/apache/ranger/tagsync/sink/tagadmin/TagAdminRESTSink.java
index cdc31e046..babe57ede 100644
--- 
a/tagsync/src/main/java/org/apache/ranger/tagsync/sink/tagadmin/TagAdminRESTSink.java
+++ 
b/tagsync/src/main/java/org/apache/ranger/tagsync/sink/tagadmin/TagAdminRESTSink.java
@@ -98,7 +98,7 @@ public boolean initialize(Properties properties) {
                }
 
                if (StringUtils.isNotBlank(restUrl)) {
-                       tagRESTClient = new RangerRESTClient(restUrl, 
sslConfigFile, TagSyncConfig.getInstance());
+                       tagRESTClient = new RangerRESTClient(restUrl, 
sslConfigFile, TagSyncConfig.getInstance(), "ranger.tagsync");
                        if (!isKerberized) {
                                tagRESTClient.setBasicAuthInfo(userName, 
password);
                        }
diff --git 
a/ugsync/src/main/java/org/apache/ranger/unixusersync/process/RangerUgSyncRESTClient.java
 
b/ugsync/src/main/java/org/apache/ranger/unixusersync/process/RangerUgSyncRESTClient.java
index e745215b8..3daa9767c 100644
--- 
a/ugsync/src/main/java/org/apache/ranger/unixusersync/process/RangerUgSyncRESTClient.java
+++ 
b/ugsync/src/main/java/org/apache/ranger/unixusersync/process/RangerUgSyncRESTClient.java
@@ -44,10 +44,11 @@ public class RangerUgSyncRESTClient extends 
RangerRESTClient {
        public RangerUgSyncRESTClient(String policyMgrBaseUrls, String 
ugKeyStoreFile, String ugKeyStoreFilepwd,
                        String ugKeyStoreType, String ugTrustStoreFile, String 
ugTrustStoreFilepwd, String ugTrustStoreType,
                        String authenticationType, String principal, String 
keytab, String polMgrUsername, String polMgrPassword) {
+               super(policyMgrBaseUrls, "", 
UserGroupSyncConfig.getInstance().getConfig(), "ranger.usersync");
 
-               super(policyMgrBaseUrls, "", 
UserGroupSyncConfig.getInstance().getConfig());
-               if (!(authenticationType != null && 
AUTH_KERBEROS.equalsIgnoreCase(authenticationType)
-                               && 
SecureClientLogin.isKerberosCredentialExists(principal, keytab))) {
+               boolean isKerberized = 
AUTH_KERBEROS.equalsIgnoreCase(authenticationType) && 
SecureClientLogin.isKerberosCredentialExists(principal, keytab);
+
+               if (!isKerberized) {
                        setBasicAuthInfo(polMgrUsername, polMgrPassword);
                }
 

Reply via email to