Skip to content

Commit 39b5ca7

Browse files
kumaabpradeepagrawal8184
authored andcommitted
RANGER-5475: add JWT support in RangerRESTClient
1 parent 9e58b54 commit 39b5ca7

4 files changed

Lines changed: 112 additions & 24 deletions

File tree

agents-audit/core/src/test/java/org/apache/ranger/audit/utils/RangerJSONAuditWriterTest.java

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ public void verifyAppendToFileWhenEnabledWithConfig() throws Exception {
7373
assertTrue(jsonAuditWriter.logJSON(Collections.singleton("Last log file will be opened in append mode and this event will be written")));
7474
assertTrue(jsonAuditWriter.logJSON(Collections.singleton("This event will also be written in append mode")));
7575

76-
jsonAuditWriter.fileSystem.deleteOnExit(jsonAuditWriter.auditPath);
76+
if (jsonAuditWriter.auditPath != null) {
77+
jsonAuditWriter.fileSystem.deleteOnExit(jsonAuditWriter.auditPath);
78+
}
7779
}
7880

7981
@Test
@@ -120,8 +122,12 @@ public void verifyFileRolloverWithAppend() throws Exception {
120122
assertNotEquals(auditPath1, jsonAuditWriter.auditPath);
121123

122124
// cleanup
123-
jsonAuditWriter.fileSystem.deleteOnExit(auditPath1);
124-
jsonAuditWriter.fileSystem.deleteOnExit(jsonAuditWriter.auditPath);
125+
if (auditPath1 != null) {
126+
jsonAuditWriter.fileSystem.deleteOnExit(auditPath1);
127+
}
128+
if (jsonAuditWriter.auditPath != null) {
129+
jsonAuditWriter.fileSystem.deleteOnExit(jsonAuditWriter.auditPath);
130+
}
125131
jsonAuditWriter.closeWriter();
126132
}
127133

@@ -150,8 +156,12 @@ public void verifyNoAppendToFileWhenDisabledWithConfig() throws Exception {
150156
assertFalse(jsonAuditWriter.reUseLastLogFile);
151157

152158
// cleanup
153-
jsonAuditWriter.fileSystem.deleteOnExit(auditPath1);
154-
jsonAuditWriter.fileSystem.deleteOnExit(jsonAuditWriter.auditPath);
159+
if (auditPath1 != null) {
160+
jsonAuditWriter.fileSystem.deleteOnExit(auditPath1);
161+
}
162+
if (jsonAuditWriter.auditPath != null) {
163+
jsonAuditWriter.fileSystem.deleteOnExit(jsonAuditWriter.auditPath);
164+
}
155165
}
156166

157167
@Test
@@ -175,8 +185,12 @@ public void verifyFileRolloverAfterThreshold() throws Exception {
175185
assertTrue(jsonAuditWriter.logJSON(Collections.singleton("Second file created since rollover happened!")));
176186

177187
// cleanup
178-
jsonAuditWriter.fileSystem.deleteOnExit(auditPath1);
179-
jsonAuditWriter.fileSystem.deleteOnExit(jsonAuditWriter.auditPath);
188+
if (auditPath1 != null) {
189+
jsonAuditWriter.fileSystem.deleteOnExit(auditPath1);
190+
}
191+
if (jsonAuditWriter.auditPath != null) {
192+
jsonAuditWriter.fileSystem.deleteOnExit(jsonAuditWriter.auditPath);
193+
}
180194
jsonAuditWriter.closeWriter();
181195
}
182196
}

agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTClient.java

Lines changed: 89 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,11 @@
4848
import javax.ws.rs.core.MediaType;
4949
import javax.ws.rs.core.Response;
5050

51+
import java.io.BufferedReader;
5152
import java.io.File;
5253
import java.io.FileInputStream;
5354
import java.io.FileNotFoundException;
55+
import java.io.FileReader;
5456
import java.io.IOException;
5557
import java.io.InputStream;
5658
import java.security.KeyManagementException;
@@ -62,6 +64,7 @@
6264
import java.security.cert.CertificateException;
6365
import java.util.List;
6466
import java.util.Map;
67+
import java.util.Optional;
6568
import java.util.Random;
6669
import java.util.Set;
6770
import java.util.concurrent.TimeUnit;
@@ -83,16 +86,18 @@ public class RangerRESTClient {
8386
public static final String RANGER_POLICYMGR_TRUSTSTORE_FILE_CREDENTIAL = "xasecure.policymgr.clientssl.truststore.credential.file";
8487
public static final String RANGER_POLICYMGR_TRUSTSTORE_FILE_CREDENTIAL_ALIAS = "sslTrustStore";
8588
public static final String RANGER_POLICYMGR_TRUSTSTORE_FILE_TYPE_DEFAULT = "jks";
86-
8789
public static final String RANGER_SSL_KEYMANAGER_ALGO_TYPE = KeyManagerFactory.getDefaultAlgorithm();
8890
public static final String RANGER_SSL_TRUSTMANAGER_ALGO_TYPE = TrustManagerFactory.getDefaultAlgorithm();
8991
public static final String RANGER_SSL_CONTEXT_ALGO_TYPE = "TLSv1.2";
9092

93+
public static final String JWT_HEADER_PREFIX = "Bearer ";
94+
9195
private String mUrl;
9296
private final String mSslConfigFileName;
9397
private String mUsername;
9498
private String mPassword;
9599
private boolean mIsSSL;
100+
private String jwt;
96101
private String mKeyStoreURL;
97102
private String mKeyStoreAlias;
98103
private String mKeyStoreFile;
@@ -108,11 +113,16 @@ public class RangerRESTClient {
108113
private int lastKnownActiveUrlIndex;
109114

110115
private final List<String> configuredURLs;
116+
private final String propertyPrefix;
111117

112118
private volatile Client client;
113119
private volatile Client cookieAuthClient;
114120

115121
public RangerRESTClient(String url, String sslConfigFileName, Configuration config) {
122+
this(url, sslConfigFileName, config, getPropertyPrefix(config));
123+
}
124+
125+
public RangerRESTClient(String url, String sslConfigFileName, Configuration config, String propertyPrefix) {
116126
mUrl = url;
117127
mSslConfigFileName = sslConfigFileName;
118128
configuredURLs = StringUtil.getURLs(mUrl);
@@ -121,6 +131,7 @@ public RangerRESTClient(String url, String sslConfigFileName, Configuration conf
121131
} else {
122132
setLastKnownActiveUrlIndex((new Random()).nextInt(getConfiguredURLs().size()));
123133
}
134+
this.propertyPrefix = propertyPrefix;
124135
init(config);
125136
}
126137

@@ -198,7 +209,7 @@ public Client getClient() {
198209
result = client;
199210

200211
if (result == null) {
201-
result = buildClient(true);
212+
result = buildClient();
202213
client = result;
203214
}
204215
}
@@ -215,7 +226,7 @@ public Client getCookieAuthClient() {
215226
ret = cookieAuthClient;
216227

217228
if (ret == null) {
218-
cookieAuthClient = buildClient(true);
229+
cookieAuthClient = buildClient();
219230
//Pending : need to remove basic auth filter from client.
220231
ret = cookieAuthClient;
221232
}
@@ -225,7 +236,11 @@ public Client getCookieAuthClient() {
225236
return ret;
226237
}
227238

228-
private Client buildClient(boolean isBasicAuth) {
239+
private static String getPropertyPrefix(Configuration config) {
240+
return (config instanceof RangerPluginConfig) ? ((RangerPluginConfig) config).getPropertyPrefix() : "ranger.plugin";
241+
}
242+
243+
private Client buildClient() {
229244
RangerJersey2ClientBuilder.SafeClientBuilder clientBuilder;
230245
ClientConfig config = new ClientConfig();
231246

@@ -263,11 +278,21 @@ public boolean verify(String urlHostName, SSLSession session) {
263278
// Validate that MOXy prevention is properly configured
264279
RangerJersey2ClientBuilder.validateAntiMoxyConfiguration(config);
265280

266-
if (isBasicAuth && StringUtils.isNotEmpty(mUsername) && StringUtils.isNotEmpty(mPassword)) {
281+
final String authHeader;
282+
if (StringUtils.isNotEmpty(jwt)) { // use JWT if present
283+
authHeader = JWT_HEADER_PREFIX + jwt;
284+
LOG.info("Registering JWT auth header in REST client");
285+
} else if (StringUtils.isNotEmpty(mUsername) && StringUtils.isNotEmpty(mPassword)) {
286+
authHeader = "Basic " + java.util.Base64.getEncoder().encodeToString((mUsername + ":" + mPassword).getBytes());
287+
LOG.info("Registering Basic auth header in REST client");
288+
} else {
289+
authHeader = null;
290+
}
291+
292+
if (StringUtils.isNotEmpty(authHeader)) {
267293
config.register(new javax.ws.rs.client.ClientRequestFilter() {
268294
@Override
269295
public void filter(javax.ws.rs.client.ClientRequestContext requestContext) {
270-
String authHeader = "Basic " + java.util.Base64.getEncoder().encodeToString((mUsername + ":" + mPassword).getBytes());
271296
requestContext.getHeaders().add("Authorization", authHeader);
272297
}
273298
});
@@ -314,16 +339,11 @@ private void init(Configuration config) {
314339
}
315340
}
316341

317-
final String pluginPropertyPrefix;
318-
319-
if (config instanceof RangerPluginConfig) {
320-
pluginPropertyPrefix = ((RangerPluginConfig) config).getPropertyPrefix();
321-
} else {
322-
pluginPropertyPrefix = "ranger.plugin";
323-
}
342+
Optional<String> jwtAsString = fetchJWT(propertyPrefix, config);
343+
jwtAsString.ifPresent(s -> this.jwt = s);
324344

325-
String username = config.get(pluginPropertyPrefix + ".policy.rest.client.username");
326-
String password = config.get(pluginPropertyPrefix + ".policy.rest.client.password");
345+
String username = config.get(propertyPrefix + ".policy.rest.client.username");
346+
String password = config.get(propertyPrefix + ".policy.rest.client.password");
327347

328348
if (StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password)) {
329349
setBasicAuthInfo(username, password);
@@ -334,6 +354,60 @@ private boolean isSsl(String url) {
334354
return !StringUtils.isEmpty(url) && url.toLowerCase().startsWith("https");
335355
}
336356

357+
private Optional<String> fetchJWT(String propertyPrefix, Configuration config) {
358+
Optional<String> ret = Optional.empty();
359+
String jwtSrc = config.get(propertyPrefix + ".policy.rest.client.jwt.source");
360+
361+
if (StringUtils.isNotEmpty(jwtSrc)) {
362+
switch(jwtSrc) {
363+
case "env": {
364+
String jwtEnvVar = config.get(propertyPrefix + ".policy.rest.client.jwt.env");
365+
if (StringUtils.isNotEmpty(jwtEnvVar)){
366+
String jwt = System.getenv(jwtEnvVar);
367+
if (StringUtils.isNotBlank(jwt)) {
368+
ret = Optional.of(jwt);
369+
}
370+
}
371+
break;
372+
}
373+
case "file": {
374+
String jwtFilePath = config.get(propertyPrefix + ".policy.rest.client.jwt.file");
375+
if (StringUtils.isNotEmpty(jwtFilePath)){
376+
File jwtFile = new File(jwtFilePath);
377+
if (jwtFile.exists()) {
378+
try (BufferedReader reader = new BufferedReader(new FileReader(jwtFile))) {
379+
String line = null;
380+
while ((line = reader.readLine()) != null) {
381+
if (StringUtils.isNotBlank(line) && !line.startsWith("#")) {
382+
ret = Optional.of(line);
383+
break;
384+
}
385+
}
386+
} catch (IOException e) {
387+
LOG.error("Failed to read JWT from file: {}", jwtFilePath, e);
388+
}
389+
}
390+
}
391+
break;
392+
}
393+
case "cred": {
394+
String credFilePath = config.get(propertyPrefix + ".policy.rest.client.jwt.cred.file");
395+
String credAlias = config.get(propertyPrefix + ".policy.rest.client.jwt.cred.alias");
396+
if (StringUtils.isNotEmpty(credFilePath) && StringUtils.isNotEmpty(credAlias)){
397+
String jwt = RangerCredentialProvider.getInstance().getCredentialString(credFilePath, credAlias);
398+
if (StringUtils.isNotBlank(jwt)) {
399+
ret = Optional.of(jwt);
400+
}
401+
}
402+
break;
403+
}
404+
}
405+
} else {
406+
LOG.info("JWT source not configured, proceeding without JWT");
407+
}
408+
return ret;
409+
}
410+
337411
private KeyManager[] getKeyManagers() {
338412
KeyManager[] kmList = null;
339413

tagsync/src/main/java/org/apache/ranger/tagsync/sink/tagadmin/TagAdminRESTSink.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public boolean initialize(Properties properties) {
8787
LOG.debug("isKerberized={}", isKerberized);
8888

8989
if (StringUtils.isNotBlank(restUrl)) {
90-
tagRESTClient = new RangerRESTClient(restUrl, sslConfigFile, TagSyncConfig.getInstance());
90+
tagRESTClient = new RangerRESTClient(restUrl, sslConfigFile, TagSyncConfig.getInstance(), "ranger.tagsync");
9191

9292
if (!isKerberized) {
9393
tagRESTClient.setBasicAuthInfo(userName, password);

ugsync/src/main/java/org/apache/ranger/unixusersync/process/RangerUgSyncRESTClient.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
public class RangerUgSyncRESTClient extends RangerRESTClient {
3535
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) {
36-
super(policyMgrBaseUrls, "", UserGroupSyncConfig.getInstance().getConfig());
36+
super(policyMgrBaseUrls, "", UserGroupSyncConfig.getInstance().getConfig(), "ranger.usersync");
3737

3838
String authKerberos = "kerberos";
3939

0 commit comments

Comments
 (0)