Skip to content

Commit

Permalink
[CALCITE-6590] Remove use of Java SecurityManager in Avatica
Browse files Browse the repository at this point in the history
Also bump ByteBuddy version to 1.15.1
  • Loading branch information
stoty committed Sep 26, 2024
1 parent fe12aea commit 66470fe
Show file tree
Hide file tree
Showing 9 changed files with 39 additions and 24 deletions.
3 changes: 3 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,9 @@ allprojects {
options.encoding = "UTF-8"
}
withType<Test>().configureEach {
if (JavaVersion.current() >= JavaVersion.VERSION_23) {
jvmArgs("-Djava.security.manager=allow")
}
testLogging {
exceptionFormat = TestExceptionFormat.FULL
showStandardStreams = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@
*/
package org.apache.calcite.avatica.remote;

import java.security.PrivilegedAction;
import org.apache.calcite.avatica.util.SecurityUtils;

import java.util.Objects;
import javax.security.auth.Subject;
import java.util.concurrent.Callable;

/**
* HTTP client implementation which invokes the wrapped HTTP client in a doAs with the provided
Expand All @@ -33,9 +34,10 @@ public DoAsAvaticaHttpClient(AvaticaHttpClient wrapped, KerberosConnection kerbe
this.kerberosUtil = Objects.requireNonNull(kerberosUtil);
}

@Override public byte[] send(final byte[] request) {
return Subject.doAs(kerberosUtil.getSubject(), new PrivilegedAction<byte[]>() {
@Override public byte[] run() {
@Override
public byte[] send(final byte[] request) {
return SecurityUtils.callAs(kerberosUtil.getSubject(), new Callable<byte[]>() {
@Override public byte[] call() {
return wrapped.send(request);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ Entry<RenewalTask, Thread> createRenewalThread(LoginContext originalContext,
renewalPeriod);
Thread t = new Thread(task);

// Don't prevent the JVM from existing
// Don't prevent the JVM from exiting
t.setDaemon(true);
// Log an error message if this thread somehow dies
t.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ spotbugs.version=3.1.11

asm.version=7.1
bouncycastle.version=1.70
bytebuddy.version=1.14.10
bytebuddy.version=1.15.1
dropwizard-metrics.version=4.0.5
# We support Guava versions as old as 14.0.1 (the version used by Hive)
# but prefer more recent versions.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.apache.calcite.avatica.remote.Driver.Serialization;
import org.apache.calcite.avatica.remote.Service;
import org.apache.calcite.avatica.remote.Service.RpcMetadataResponse;
import org.apache.calcite.avatica.util.SecurityUtils;

import org.eclipse.jetty.security.Authenticator;
import org.eclipse.jetty.security.ConfigurableSpnegoLoginService;
Expand Down Expand Up @@ -53,7 +54,6 @@
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.security.SecureRandom;
import java.time.Duration;
import java.util.ArrayList;
Expand Down Expand Up @@ -205,8 +205,8 @@ static AvaticaHandler wrapJettyHandler(Handler handler) {
public void start() {
if (null != subject) {
// Run the start in the privileged block (as the kerberos-identified user)
Subject.doAs(subject, new PrivilegedAction<Void>() {
@Override public Void run() {
SecurityUtils.callAs(subject, new Callable<Void>() {
@Override public Void call() {
internalStart();
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,20 @@
*/
package org.apache.calcite.avatica.server;

import java.security.AccessController;
import org.apache.calcite.avatica.util.SecurityUtils;

import java.security.PrivilegedAction;
import java.util.concurrent.Callable;
import java.util.concurrent.ThreadFactory;
import javax.security.auth.Subject;

/**
* Encapsulates creating the new Thread in a doPrivileged and a doAs call.
* The doPrivilieged block is taken from Jetty, and prevents some classloader leak isses.
*
* Also according to Jetty, the referred leak was fixed in JDK17, and the doPriviliged block
* is no longer needed in 17 and later-
*
* Saving the subject, and creating the Thread in the inner doAs call works around
* doPriviliged resetting the kerberos subject, which breaks SPNEGO authentication.
*
Expand All @@ -39,12 +45,13 @@ class SubjectPreservingPrivilegedThreadFactory implements ThreadFactory {
* @param Runnable object for the thread
* @return a new thread, protected from classloader pinning, but keeping the current Subject
*/
@Override
public Thread newThread(Runnable runnable) {
Subject subject = Subject.getSubject(AccessController.getContext());
return AccessController.doPrivileged(new PrivilegedAction<Thread>() {
Subject subject = SecurityUtils.currentSubject();
return SecurityUtils.doPrivileged(new PrivilegedAction<Thread>() {
@Override public Thread run() {
return Subject.doAs(subject, new PrivilegedAction<Thread>() {
@Override public Thread run() {
return SecurityUtils.callAs(subject, new Callable<Thread>() {
@Override public Thread call() {
Thread thread = new Thread(runnable);
thread.setDaemon(true);
thread.setName("avatica_qtp" + hashCode() + "-" + thread.getId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.apache.calcite.avatica.remote.Driver;
import org.apache.calcite.avatica.server.AvaticaJaasKrbUtil;
import org.apache.calcite.avatica.server.HttpServer;
import org.apache.calcite.avatica.util.SecurityUtils;

import org.apache.kerby.kerberos.kerb.KrbException;
import org.apache.kerby.kerberos.kerb.client.KrbConfig;
Expand All @@ -34,13 +35,13 @@
import org.slf4j.LoggerFactory;

import java.io.File;
import java.security.PrivilegedExceptionAction;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import javax.security.auth.Subject;

import static org.junit.Assert.assertEquals;
Expand Down Expand Up @@ -217,8 +218,8 @@ public AvaticaSpnegoTest(String jdbcUrl) {
// The name of the principal

// Run this code, logged in as the subject (the client)
Subject.doAs(clientSubject, new PrivilegedExceptionAction<Void>() {
@Override public Void run() throws Exception {
SecurityUtils.callAs(clientSubject, new Callable<Void>() {
@Override public Void call() throws Exception {
try (Connection conn = DriverManager.getConnection(jdbcUrl)) {
try (Statement stmt = conn.createStatement()) {
assertFalse(stmt.execute("DROP TABLE IF EXISTS " + tableName));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.apache.calcite.avatica.remote.KerberosConnection;
import org.apache.calcite.avatica.remote.Service.RpcMetadataResponse;
import org.apache.calcite.avatica.server.AvaticaHandler;
import org.apache.calcite.avatica.util.SecurityUtils;

import org.apache.kerby.kerberos.kerb.KrbException;
import org.apache.kerby.kerberos.kerb.server.SimpleKdcServer;
Expand All @@ -38,7 +39,6 @@
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.nio.charset.StandardCharsets;
import java.security.AccessController;
import java.security.Principal;
import java.security.PrivilegedAction;
import javax.security.auth.login.Configuration;
Expand Down Expand Up @@ -138,8 +138,9 @@ public static void refreshJaasConfiguration() {
// Configuration keeps a static instance of Configuration that it will return once it
// has been initialized. We need to nuke that static instance to make sure our
// serverSpnegoConfigFile gets read.
AccessController.doPrivileged(new PrivilegedAction<Configuration>() {
public Configuration run() {
SecurityUtils.doPrivileged(new PrivilegedAction<Configuration>() {
@Override
public Configuration run() {
return Configuration.getConfiguration();
}
}).refresh();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.apache.calcite.avatica.SpnegoTestUtil;
import org.apache.calcite.avatica.remote.AvaticaCommonsHttpClientImpl;
import org.apache.calcite.avatica.remote.CommonsHttpClientPoolCache;
import org.apache.calcite.avatica.util.SecurityUtils;

import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.kerby.kerberos.kerb.KrbException;
Expand All @@ -47,9 +48,9 @@
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.Principal;
import java.security.PrivilegedExceptionAction;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.Callable;
import javax.security.auth.Subject;
import javax.security.auth.kerberos.KerberosTicket;

Expand Down Expand Up @@ -216,8 +217,8 @@ private static void setupUsers(File keytabDir) throws KrbException {
final String principalName = clientPrincipals.iterator().next().getName();

// Run this code, logged in as the subject (the client)
byte[] response = Subject.doAs(clientSubject, new PrivilegedExceptionAction<byte[]>() {
@Override public byte[] run() throws Exception {
byte[] response = SecurityUtils.callAs(clientSubject, new Callable<byte[]>() {
@Override public byte[] call() throws Exception {
// Logs in with Kerberos via GSS
GSSManager gssManager = GSSManager.getInstance();
Oid oid = new Oid(SpnegoTestUtil.JGSS_KERBEROS_TICKET_OID);
Expand Down

0 comments on commit 66470fe

Please sign in to comment.