This is an automated email from the ASF dual-hosted git repository.
madhan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/master by this push:
new f98a149d5 RANGER-5475: add JWT support in RangerRESTClient (#831)
f98a149d5 is described below
commit f98a149d56fb4589cc47d03e55bd16b0adf4a153
Author: Abhishek Kumar <[email protected]>
AuthorDate: Sat Jan 31 18:46:38 2026 -0800
RANGER-5475: add JWT support in RangerRESTClient (#831)
---
.../ranger/plugin/util/RangerRESTClient.java | 138 +++++++++++++++++----
.../tagsync/sink/tagadmin/TagAdminRESTSink.java | 2 +-
.../process/RangerUgSyncRESTClient.java | 6 +-
3 files changed, 116 insertions(+), 30 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 da1e0eee9..a073173a9 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
@@ -22,6 +22,7 @@
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientHandlerException;
+import com.sun.jersey.api.client.ClientRequest;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
@@ -48,9 +49,11 @@
import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.Response;
+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;
@@ -82,8 +85,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 final String mSslConfigFileName;
private String mUsername;
@@ -104,30 +109,26 @@ public class RangerRESTClient {
private int lastKnownActiveUrlIndex;
private volatile Client client;
private volatile Client cookieAuthClient;
+ 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 {
setLastKnownActiveUrlIndex((new
Random()).nextInt(getConfiguredURLs().size()));
}
- init(config);
- }
-
- protected static WebResource setQueryParams(WebResource webResource,
Map<String, String> params) {
- WebResource ret = webResource;
-
- if (webResource != null && params != null) {
- for (Map.Entry<String, String> entry : params.entrySet()) {
- ret = ret.queryParam(entry.getKey(), entry.getValue());
- }
- }
- return ret;
+ init(config);
}
public String getUrl() {
@@ -684,6 +685,22 @@ protected void setTrustStoreType(String mTrustStoreType) {
this.mTrustStoreType = mTrustStoreType;
}
+ protected static WebResource setQueryParams(WebResource webResource,
Map<String, String> params) {
+ WebResource ret = webResource;
+
+ if (webResource != null && params != null) {
+ for (Map.Entry<String, String> entry : params.entrySet()) {
+ ret = ret.queryParam(entry.getKey(), entry.getValue());
+ }
+ }
+
+ return ret;
+ }
+
+ private static String getPropertyPrefix(Configuration config) {
+ return (config instanceof RangerPluginConfig) ? ((RangerPluginConfig)
config).getPropertyPrefix() : "ranger.plugin";
+ }
+
private Client getCookieAuthClient() {
Client ret = cookieAuthClient;
@@ -694,6 +711,10 @@ private Client getCookieAuthClient() {
if (ret == null) {
cookieAuthClient = buildClient();
+ if (jwtAuthFilter != null) {
+ cookieAuthClient.removeFilter(jwtAuthFilter);
+ }
+
if (basicAuthFilter != null) {
cookieAuthClient.removeFilter(basicAuthFilter);
}
@@ -732,8 +753,11 @@ private Client buildClient() {
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
@@ -743,6 +767,23 @@ private Client buildClient() {
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);
@@ -780,22 +821,67 @@ 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 = null;
+ 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 58dba7400..961ebfb53 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
@@ -85,7 +85,7 @@ public boolean initialize(Properties properties) {
LOG.debug("isKerberized={}", isKerberized);
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 aab18d0f7..56fca65e0 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
@@ -37,11 +37,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());
+ super(policyMgrBaseUrls, "",
UserGroupSyncConfig.getInstance().getConfig(), "ranger.usersync");
- String authKerberos = "kerberos";
+ boolean isKerberized = "kerberos".equalsIgnoreCase(authenticationType)
&& SecureClientLogin.isKerberosCredentialExists(principal, keytab);
- if (!(authKerberos.equalsIgnoreCase(authenticationType) &&
SecureClientLogin.isKerberosCredentialExists(principal, keytab))) {
+ if (!isKerberized) {
setBasicAuthInfo(polMgrUsername, polMgrPassword);
}