[client] KUDU-3472 Java client API to import JWT
This patch adds one new method into AsyncKuduClient and KuduClient API
to set a JWT (JSON Web Token) to be used for authentication. The newly
introduced API matches the one introduced in the C++ Kudu client.
Change-Id: Ic43bd1219f4613e9cac11762726a5d6d2cdc764b
Reviewed-on: http://gerrit.cloudera.org:8080/19836
Tested-by: Alexey Serbin <alexey@apache.org>
Reviewed-by: Alexey Serbin <alexey@apache.org>
diff --git a/java/kudu-client/src/main/java/org/apache/kudu/client/AsyncKuduClient.java b/java/kudu-client/src/main/java/org/apache/kudu/client/AsyncKuduClient.java
index 2e8a24e..68aa1b2 100644
--- a/java/kudu-client/src/main/java/org/apache/kudu/client/AsyncKuduClient.java
+++ b/java/kudu-client/src/main/java/org/apache/kudu/client/AsyncKuduClient.java
@@ -80,6 +80,7 @@
import org.apache.kudu.master.Master.TSInfoPB;
import org.apache.kudu.master.Master.TableIdentifierPB;
import org.apache.kudu.master.Master.TabletLocationsPB;
+import org.apache.kudu.security.Token;
import org.apache.kudu.security.Token.SignedTokenPB;
import org.apache.kudu.util.AsyncUtil;
import org.apache.kudu.util.NetUtil;
@@ -1178,6 +1179,24 @@
}
/**
+ * Set JWT (JSON Web Token) to authenticate the client to a server.
+ * <p>
+ * @note If {@link #importAuthenticationCredentials(byte[] authnData)} and
+ * this method are called on the same object, the JWT provided with this call
+ * overrides the corresponding JWT that comes as a part of the imported
+ * authentication credentials (if present).
+ *
+ * @param jwt The JSON web token to set.
+ */
+ @InterfaceStability.Unstable
+ public void jwt(String jwt) {
+ Token.JwtRawPB jwtPB = Token.JwtRawPB.newBuilder()
+ .setJwtData(ByteString.copyFromUtf8(jwt))
+ .build();
+ securityContext.setJsonWebToken(jwtPB);
+ }
+
+ /**
* Get the timeout used for operations on sessions and scanners.
* @return a timeout in milliseconds
*/
diff --git a/java/kudu-client/src/main/java/org/apache/kudu/client/KuduClient.java b/java/kudu-client/src/main/java/org/apache/kudu/client/KuduClient.java
index 1536574..ed2f90e 100644
--- a/java/kudu-client/src/main/java/org/apache/kudu/client/KuduClient.java
+++ b/java/kudu-client/src/main/java/org/apache/kudu/client/KuduClient.java
@@ -22,6 +22,7 @@
import java.util.concurrent.Executor;
import com.google.common.base.Preconditions;
+import com.google.protobuf.ByteString;
import com.stumbleupon.async.Deferred;
import org.apache.yetus.audience.InterfaceAudience;
import org.apache.yetus.audience.InterfaceStability;
@@ -30,6 +31,7 @@
import org.apache.kudu.Schema;
import org.apache.kudu.master.Master.TableIdentifierPB;
+import org.apache.kudu.security.Token;
/**
* A synchronous and thread-safe client for Kudu.
@@ -467,6 +469,21 @@
}
/**
+ * Set JWT (JSON Web Token) to authenticate the client to a server.
+ * <p>
+ * @note If {@link #importAuthenticationCredentials(byte[] authnData)} and
+ * this method are called on the same object, the JWT provided with this call
+ * overrides the corresponding JWT that comes as a part of the imported
+ * authentication credentials (if present).
+ *
+ * @param jwt The JSON web token to set.
+ */
+ @InterfaceStability.Unstable
+ public void jwt(String jwt) {
+ asyncClient.jwt(jwt);
+ }
+
+ /**
* Get the timeout used for operations on sessions and scanners.
* @return a timeout in milliseconds
*/
diff --git a/java/kudu-client/src/main/java/org/apache/kudu/client/SecurityContext.java b/java/kudu-client/src/main/java/org/apache/kudu/client/SecurityContext.java
index 8597e0c..b02c020 100644
--- a/java/kudu-client/src/main/java/org/apache/kudu/client/SecurityContext.java
+++ b/java/kudu-client/src/main/java/org/apache/kudu/client/SecurityContext.java
@@ -278,6 +278,9 @@
if (authnToken != null) {
pb.setAuthnToken(authnToken);
}
+ if (jsonWebToken != null) {
+ pb.setJwt(jsonWebToken);
+ }
pb.addAllCaCertDers(trustedCertDers);
return pb.build().toByteArray();
}
@@ -315,10 +318,9 @@
}
LOG.debug("Importing authentication credentials with {} authn token, " +
- "JWT={} , " +
- "{} cert(s), and realUser={}",
+ "with {} JWT, {} cert(s), and realUser={}",
pb.hasAuthnToken() ? "one" : "no",
- pb.hasJwt() ? pb.getJwt() : "<none>",
+ pb.hasJwt() ? "one" : "no",
pb.getCaCertDersCount(),
pb.hasRealUser() ? pb.getRealUser() : "<none>");
if (pb.hasAuthnToken()) {
@@ -327,7 +329,11 @@
trustCertificates(pb.getCaCertDersList());
if (pb.hasJwt()) {
- jsonWebToken = pb.getJwt();
+ // Don't overwrite the JWT in the context if it's already set.
+ if (!jsonWebToken.hasJwtData() ||
+ (jsonWebToken.hasJwtData() && jsonWebToken.getJwtData().isEmpty())) {
+ jsonWebToken = pb.getJwt();
+ }
}
if (pb.hasRealUser()) {
diff --git a/java/kudu-test-utils/src/test/java/org/apache/kudu/test/TestMiniKuduCluster.java b/java/kudu-test-utils/src/test/java/org/apache/kudu/test/TestMiniKuduCluster.java
index ddfbe6d..c31efb3 100644
--- a/java/kudu-test-utils/src/test/java/org/apache/kudu/test/TestMiniKuduCluster.java
+++ b/java/kudu-test-utils/src/test/java/org/apache/kudu/test/TestMiniKuduCluster.java
@@ -119,31 +119,18 @@
@Test(timeout = 50000)
public void testJwt() throws Exception {
- try {
- MiniKuduClusterBuilder clusterBuilder = new MiniKuduCluster.MiniKuduClusterBuilder()
- .numMasterServers(NUM_MASTERS)
- .numTabletServers(0)
- .enableClientJwt()
- .addJwks("account-id", true);
-
- harness = new KuduTestHarness(clusterBuilder);
- harness.before();
- harness.startAllMasterServers();
-
- String jwt = harness.createJwtFor("account-id", "subject", true);
+ try (MiniKuduCluster cluster = new MiniKuduCluster.MiniKuduClusterBuilder()
+ .numMasterServers(NUM_MASTERS)
+ .numTabletServers(0)
+ .enableClientJwt()
+ .addJwks("account-id", true)
+ .build();
+ KuduClient client = new KuduClientBuilder(cluster.getMasterAddressesAsString()).build()) {
+ String jwt = cluster.createJwtFor("account-id", "subject", true);
assertNotNull(jwt);
- AuthenticationCredentialsPB credentials = AuthenticationCredentialsPB.newBuilder()
- .setJwt(JwtRawPB.newBuilder()
- .setJwtData(ByteString.copyFromUtf8(jwt))
- .build())
- .build();
- AsyncKuduClient c = harness.getAsyncClient();
- c.importAuthenticationCredentials(credentials.toByteArray());
- c.getTablesList();
-
- } catch (Exception e) {
- throw new RuntimeException(e);
+ client.jwt(jwt);
+ client.getTablesList();
}
}