Repository: lens Updated Branches: refs/heads/master af2c4d6ed -> ea74a2c93
LENS-1506: Kerberos authentication in lens Project: http://git-wip-us.apache.org/repos/asf/lens/repo Commit: http://git-wip-us.apache.org/repos/asf/lens/commit/ea74a2c9 Tree: http://git-wip-us.apache.org/repos/asf/lens/tree/ea74a2c9 Diff: http://git-wip-us.apache.org/repos/asf/lens/diff/ea74a2c9 Branch: refs/heads/master Commit: ea74a2c9306552646196c8a621b864c4afe2b438 Parents: af2c4d6 Author: Ankit Kailaswar <[email protected]> Authored: Thu Apr 5 17:38:07 2018 +0530 Committer: Puneet Gupta <[email protected]> Committed: Thu Apr 5 17:38:07 2018 +0530 ---------------------------------------------------------------------- .../org/apache/lens/driver/hive/HiveDriver.java | 10 +- .../driver/hive/RemoteThriftConnection.java | 14 +- .../RetryingThriftCLIServiceClientSasl.java | 237 +++++++++++++++++++ .../lens/server/api/LensConfConstants.java | 15 ++ .../apache/lens/server/api/util/LensUtil.java | 54 +++++ .../org/apache/lens/server/BaseLensService.java | 22 +- .../org/apache/lens/server/LensServices.java | 63 ++++- .../lens/server/session/HiveSessionService.java | 1 + .../src/main/resources/lensserver-default.xml | 13 + lens-server/src/test/resources/lens-site.xml | 12 + tools/scripts/lens-ctl | 6 +- 11 files changed, 424 insertions(+), 23 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lens/blob/ea74a2c9/lens-driver-hive/src/main/java/org/apache/lens/driver/hive/HiveDriver.java ---------------------------------------------------------------------- diff --git a/lens-driver-hive/src/main/java/org/apache/lens/driver/hive/HiveDriver.java b/lens-driver-hive/src/main/java/org/apache/lens/driver/hive/HiveDriver.java index 2eb94aa..3fd5d2c 100644 --- a/lens-driver-hive/src/main/java/org/apache/lens/driver/hive/HiveDriver.java +++ b/lens-driver-hive/src/main/java/org/apache/lens/driver/hive/HiveDriver.java @@ -57,6 +57,8 @@ import org.apache.hadoop.hive.ql.QueryDisplay.TaskDisplay; import org.apache.hadoop.hive.ql.exec.Task; import org.apache.hadoop.hive.ql.metadata.HiveException; import org.apache.hadoop.hive.ql.session.SessionState; +import org.apache.hadoop.security.UserGroupInformation; +import org.apache.hive.service.auth.HiveAuthFactory; import org.apache.hive.service.cli.*; import org.apache.hive.service.rpc.thrift.TOperationHandle; import org.apache.hive.service.rpc.thrift.TProtocolVersion; @@ -934,7 +936,13 @@ public class HiveDriver extends AbstractLensDriver { SessionHandle hiveSession; if (!lensToHiveSession.containsKey(sessionDbKey)) { try { - hiveSession = getClient().openSession(ctx.getClusterUser(), "", SESSION_CONF); + if (ctx.getHiveConf().getVar(HiveConf.ConfVars.HIVE_SERVER2_AUTHENTICATION) + .equals(HiveAuthFactory.AuthTypes.KERBEROS.toString())) { + String user = UserGroupInformation.getLoginUser().getUserName(); + hiveSession = getClient().openSession(user, "", SESSION_CONF); + } else { + hiveSession = getClient().openSession(ctx.getClusterUser(), "", SESSION_CONF); + } lensToHiveSession.put(sessionDbKey, hiveSession); log.info("New hive session for user: {} , lens session: {} , hive session handle: {} , driver : {}", ctx.getClusterUser(), sessionDbKey, hiveSession.getHandleIdentifier(), getFullyQualifiedName()); http://git-wip-us.apache.org/repos/asf/lens/blob/ea74a2c9/lens-driver-hive/src/main/java/org/apache/lens/driver/hive/RemoteThriftConnection.java ---------------------------------------------------------------------- diff --git a/lens-driver-hive/src/main/java/org/apache/lens/driver/hive/RemoteThriftConnection.java b/lens-driver-hive/src/main/java/org/apache/lens/driver/hive/RemoteThriftConnection.java index 54885f7..d47cb89 100644 --- a/lens-driver-hive/src/main/java/org/apache/lens/driver/hive/RemoteThriftConnection.java +++ b/lens-driver-hive/src/main/java/org/apache/lens/driver/hive/RemoteThriftConnection.java @@ -18,15 +18,17 @@ */ package org.apache.lens.driver.hive; + import org.apache.lens.server.api.error.LensException; import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hive.service.auth.HiveAuthFactory; import org.apache.hive.service.cli.CLIServiceClient; -import org.apache.hive.service.cli.HiveSQLException; import org.apache.hive.service.cli.thrift.RetryingThriftCLIServiceClient; import lombok.extern.slf4j.Slf4j; + /** * Connect to a remote Hive Server 2 service to run driver queries. */ @@ -66,12 +68,18 @@ public class RemoteThriftConnection implements ThriftConnection { log.info("HiveDriver connecting to HiveServer @ {}:{}", conf.getVar(HiveConf.ConfVars.HIVE_SERVER2_THRIFT_BIND_HOST), conf.getIntVar(HiveConf.ConfVars.HIVE_SERVER2_THRIFT_PORT)); - hs2Client = RetryingThriftCLIServiceClient.newRetryingCLIServiceClient(conf); + + if (conf.getVar(HiveConf.ConfVars.HIVE_SERVER2_AUTHENTICATION) + .equals(HiveAuthFactory.AuthTypes.KERBEROS.toString())) { + hs2Client = RetryingThriftCLIServiceClientSasl.newRetryingCLIServiceClient(conf); + } else { + hs2Client = RetryingThriftCLIServiceClient.newRetryingCLIServiceClient(conf); + } log.info("HiveDriver connected to HiveServer @ {}:{}", conf.getVar(HiveConf.ConfVars.HIVE_SERVER2_THRIFT_BIND_HOST), conf.getIntVar(HiveConf.ConfVars.HIVE_SERVER2_THRIFT_PORT)); - } catch (HiveSQLException e) { + } catch (Exception e) { throw new LensException(e); } connected = true; http://git-wip-us.apache.org/repos/asf/lens/blob/ea74a2c9/lens-driver-hive/src/main/java/org/apache/lens/driver/hive/RetryingThriftCLIServiceClientSasl.java ---------------------------------------------------------------------- diff --git a/lens-driver-hive/src/main/java/org/apache/lens/driver/hive/RetryingThriftCLIServiceClientSasl.java b/lens-driver-hive/src/main/java/org/apache/lens/driver/hive/RetryingThriftCLIServiceClientSasl.java new file mode 100644 index 0000000..dfb0a95 --- /dev/null +++ b/lens-driver-hive/src/main/java/org/apache/lens/driver/hive/RetryingThriftCLIServiceClientSasl.java @@ -0,0 +1,237 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.lens.driver.hive; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.lang.reflect.UndeclaredThrowableException; +import java.net.SocketException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import javax.security.sasl.Sasl; +import javax.security.sasl.SaslException; + +import org.apache.lens.server.api.util.LensUtil; + +import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hive.service.auth.KerberosSaslHelper; +import org.apache.hive.service.cli.CLIServiceClient; +import org.apache.hive.service.cli.HiveSQLException; +import org.apache.hive.service.cli.ICLIService; +import org.apache.hive.service.cli.thrift.RetryingThriftCLIServiceClient; +import org.apache.hive.service.cli.thrift.ThriftCLIServiceClient; +import org.apache.hive.service.rpc.thrift.TCLIService; +import org.apache.thrift.TApplicationException; +import org.apache.thrift.protocol.TBinaryProtocol; +import org.apache.thrift.protocol.TProtocol; +import org.apache.thrift.protocol.TProtocolException; +import org.apache.thrift.transport.TSocket; +import org.apache.thrift.transport.TTransport; +import org.apache.thrift.transport.TTransportException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The Class RetryingThriftCLIServiceClientSasl. + * + * This class can be used to connect to hive server using ThriftCLIServiceClient + * with sasl transport protocol. + * + */ +public class RetryingThriftCLIServiceClientSasl implements InvocationHandler { + + public static final Logger LOG = LoggerFactory.getLogger(RetryingThriftCLIServiceClientSasl.class); + + // base client to open thrift connection with client + private ThriftCLIServiceClient base; + + // auto retry on connection failure. + private final int retryLimit; + + // delay in retry post failure + private final int retryDelaySeconds; + + // Hive client conf + private HiveConf conf; + + // transport protocol to use + private TTransport transport; + + public static class CLIServiceClientWrapperSasl extends RetryingThriftCLIServiceClient.CLIServiceClientWrapper { + + public CLIServiceClientWrapperSasl(ICLIService icliService, TTransport tTransport) { + super(icliService, tTransport); + } + } + + private RetryingThriftCLIServiceClientSasl(HiveConf conf) { + this.conf = conf; + this.retryLimit = conf.getIntVar(HiveConf.ConfVars.HIVE_SERVER2_THRIFT_CLIENT_RETRY_LIMIT); + this.retryDelaySeconds = (int) conf.getTimeVar(HiveConf.ConfVars.HIVE_SERVER2_THRIFT_CLIENT_RETRY_DELAY_SECONDS, + TimeUnit.SECONDS); + } + + public static RetryingThriftCLIServiceClient.CLIServiceClientWrapper newRetryingCLIServiceClient(HiveConf conf) + throws Exception { + RetryingThriftCLIServiceClientSasl retryClient = new RetryingThriftCLIServiceClientSasl(conf); + TTransport tTransport = retryClient + .connectWithRetry(conf.getIntVar(HiveConf.ConfVars.HIVE_SERVER2_THRIFT_CLIENT_CONNECTION_RETRY_LIMIT)); + ICLIService cliService = + (ICLIService) Proxy.newProxyInstance(RetryingThriftCLIServiceClientSasl.class.getClassLoader(), + CLIServiceClient.class.getInterfaces(), retryClient); + return new RetryingThriftCLIServiceClient.CLIServiceClientWrapper(cliService, tTransport); + } + + protected TTransport connectWithRetry(int retries) throws Exception { + + TTransportException exception = null; + + for (int i = 0; i < retries; i++) { + try { + return connect(conf); + } catch (TTransportException e) { + exception = e; + LOG.warn("Connection attempt " + i, e); + } + try { + Thread.sleep(retryDelaySeconds * 1000); + } catch (InterruptedException e) { + LOG.warn("Interrupted", e); + } + } + throw new HiveSQLException("Unable to connect after " + retries + " retries", exception); + } + + protected synchronized TTransport connect(HiveConf conf) throws Exception { + + /* + Can not get a renewed ugi in current thread spawned for hive client. + Need to explicitly refresh token with keytab. + This needs further investigation. + */ + LensUtil.refreshLensTGT(conf); + + if (transport != null && transport.isOpen()) { + transport.close(); + } + + String host = conf.getVar(HiveConf.ConfVars.HIVE_SERVER2_THRIFT_BIND_HOST); + int port = conf.getIntVar(HiveConf.ConfVars.HIVE_SERVER2_THRIFT_PORT); + LOG.info("Connecting to " + host + ":" + port); + + transport = new TSocket(host, port); + ((TSocket) transport).setTimeout((int) conf.getTimeVar(HiveConf.ConfVars.SERVER_READ_SOCKET_TIMEOUT, + TimeUnit.SECONDS) * 1000); + + try { + ((TSocket) transport).getSocket().setKeepAlive(conf.getBoolVar(HiveConf.ConfVars.SERVER_TCP_KEEP_ALIVE)); + } catch (SocketException e) { + LOG.error("Error setting keep alive to " + conf.getBoolVar(HiveConf.ConfVars.SERVER_TCP_KEEP_ALIVE), e); + } + + try { + Map<String, String> saslProps = new HashMap<String, String>(); + saslProps.put(Sasl.QOP, "auth-conf,auth-int,auth"); + saslProps.put(Sasl.SERVER_AUTH, "true"); + + transport = KerberosSaslHelper.getKerberosTransport( + conf.getVar(HiveConf.ConfVars.HIVE_SERVER2_KERBEROS_PRINCIPAL), host, + transport, saslProps, false); + } catch (SaslException e) { + LOG.error("Error creating SASL transport", e); + } + + TProtocol protocol = new TBinaryProtocol(transport); + transport.open(); + + LOG.info("Connected to " + host + ":" + port); + + base = new ThriftCLIServiceClient(new TCLIService.Client(protocol)); + return transport; + } + + protected class InvocationResult { + final boolean success; + final Object result; + final Throwable exception; + + InvocationResult(boolean success, Object result, Throwable exception) { + this.success = success; + this.result = result; + this.exception = exception; + } + } + + protected InvocationResult invokeInternal(Method method, Object[] args) throws Throwable { + InvocationResult result; + try { + Object methodResult = method.invoke(base, args); + result = new InvocationResult(true, methodResult, null); + } catch (UndeclaredThrowableException e) { + throw e.getCause(); + } catch (InvocationTargetException e) { + if (e.getCause() instanceof HiveSQLException) { + HiveSQLException hiveExc = (HiveSQLException) e.getCause(); + Throwable cause = hiveExc.getCause(); + if ((cause instanceof TApplicationException) + || (cause instanceof TProtocolException) + || (cause instanceof TTransportException)) { + result =new InvocationResult(false, null, hiveExc); + } else { + throw hiveExc; + } + } else { + throw e.getCause(); + } + } + return result; + } + + + @Override + public Object invoke(Object o, Method method, Object[] args) throws Throwable { + int attempts = 0; + + while (true) { + attempts++; + InvocationResult invokeResult = invokeInternal(method, args); + if (invokeResult.success) { + return invokeResult.result; + } + + // Error because of thrift client, we have to recreate base object + connectWithRetry(conf.getIntVar(HiveConf.ConfVars.HIVE_SERVER2_THRIFT_CLIENT_CONNECTION_RETRY_LIMIT)); + + if (attempts >=retryLimit) { + LOG.error(method.getName() + " failed after " + attempts + " retries.", invokeResult.exception); + throw invokeResult.exception; + } + + LOG.warn("Last call ThriftCLIServiceClient." + method.getName() + " failed, attempts = " + attempts, + invokeResult.exception); + Thread.sleep(retryDelaySeconds * 1000); + } + } +} http://git-wip-us.apache.org/repos/asf/lens/blob/ea74a2c9/lens-server-api/src/main/java/org/apache/lens/server/api/LensConfConstants.java ---------------------------------------------------------------------- diff --git a/lens-server-api/src/main/java/org/apache/lens/server/api/LensConfConstants.java b/lens-server-api/src/main/java/org/apache/lens/server/api/LensConfConstants.java index d5273be..0e05d28 100644 --- a/lens-server-api/src/main/java/org/apache/lens/server/api/LensConfConstants.java +++ b/lens-server-api/src/main/java/org/apache/lens/server/api/LensConfConstants.java @@ -718,8 +718,23 @@ public final class LensConfConstants { public static final String SESSION_EXPIRY_SERVICE_INTERVAL_IN_SECS = SERVER_PFX + "session.expiry.service.interval.secs"; + /** + * Interval at which KDC login runs + */ + public static final String KDC_LOGIN_SERVICE_INTERVAL_IN_MINUTES = SERVER_PFX + + "kdc.login.service.interval.minutes"; + public static final int DEFAULT_SESSION_EXPIRY_SERVICE_INTERVAL_IN_SECS = 3600; + public static final int DEFAULT_KDC_LOGIN_SERVICE_INTERVAL_IN_MINUTES = 360; + + + /** + * Lens principal for kerberos authentication + */ + public static final String LENS_PRINCIPAL = SERVER_PFX + + "principal"; + // Statistics Store configuration keys /** * The Constant STATS_STORE_CLASS. http://git-wip-us.apache.org/repos/asf/lens/blob/ea74a2c9/lens-server-api/src/main/java/org/apache/lens/server/api/util/LensUtil.java ---------------------------------------------------------------------- diff --git a/lens-server-api/src/main/java/org/apache/lens/server/api/util/LensUtil.java b/lens-server-api/src/main/java/org/apache/lens/server/api/util/LensUtil.java index 9d732c1..1060114 100644 --- a/lens-server-api/src/main/java/org/apache/lens/server/api/util/LensUtil.java +++ b/lens-server-api/src/main/java/org/apache/lens/server/api/util/LensUtil.java @@ -18,25 +18,35 @@ */ package org.apache.lens.server.api.util; +import java.io.File; +import java.io.IOException; +import java.net.InetAddress; import java.net.SocketException; import java.net.SocketTimeoutException; import java.util.HashMap; import java.util.Set; +import org.apache.lens.server.api.LensConfConstants; import org.apache.lens.server.api.common.ConfigBasedObjectCreationFactory; +import org.apache.commons.lang.Validate; import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.conf.Configurable; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hadoop.security.SecurityUtil; +import org.apache.hadoop.security.UserGroupInformation; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; /** * Utility methods for Lens */ +@Slf4j public final class LensUtil { private LensUtil() { @@ -113,4 +123,48 @@ public final class LensUtil { } return map; } + + private static void checkIsReadable(String keytabFilePath) { + File keytabFile = new File(keytabFilePath); + if (!keytabFile.exists()) { + throw new IllegalArgumentException("The keytab file does not exist! " + keytabFilePath); + } + + if (!keytabFile.isFile()) { + throw new IllegalArgumentException("The keytab file cannot be a directory! " + keytabFilePath); + } + + if (!keytabFile.canRead()) { + throw new IllegalArgumentException("The keytab file is not readable! " + keytabFilePath); + } + } + + public static void refreshLensTGT(HiveConf conf) throws IOException, IllegalArgumentException { + + String principalString = conf.get(LensConfConstants.LENS_PRINCIPAL); + + Validate.notEmpty(principalString, + "Missing required configuration property: " + LensConfConstants.LENS_PRINCIPAL); + + String principal = SecurityUtil.getServerPrincipal( + principalString, + InetAddress.getLocalHost().getCanonicalHostName()); + + String keytabFilePath = conf.getVar(HiveConf.ConfVars.HIVE_SERVER2_KERBEROS_KEYTAB); + + Validate.notEmpty(keytabFilePath, "Missing required configuration property: " + + HiveConf.ConfVars.HIVE_SERVER2_KERBEROS_KEYTAB.toString()); + checkIsReadable(keytabFilePath); + + Configuration hadoopConf = new Configuration(); + hadoopConf.set("hadoop.security.authentication", "kerberos"); + + UserGroupInformation.setConfiguration(hadoopConf); + + UserGroupInformation.loginUserFromKeytab(principal, keytabFilePath); + + log.info("RetryingThriftCLIServiceClientSasl : Got Kerberos ticket, keytab: {}, Lens principal: {}", + keytabFilePath, principal); + + } } http://git-wip-us.apache.org/repos/asf/lens/blob/ea74a2c9/lens-server/src/main/java/org/apache/lens/server/BaseLensService.java ---------------------------------------------------------------------- diff --git a/lens-server/src/main/java/org/apache/lens/server/BaseLensService.java b/lens-server/src/main/java/org/apache/lens/server/BaseLensService.java index c30a2d7..b5248f3 100644 --- a/lens-server/src/main/java/org/apache/lens/server/BaseLensService.java +++ b/lens-server/src/main/java/org/apache/lens/server/BaseLensService.java @@ -172,7 +172,12 @@ public abstract class BaseLensService extends CompositeService implements Extern SessionHandle sessionHandle; username = UtilityMethods.removeDomain(username); if (auth) { - doPasswdAuth(username, password); + if (cliService.getHiveConf().getVar(ConfVars.HIVE_SERVER2_AUTHENTICATION) + .equals(HiveAuthFactory.AuthTypes.KERBEROS.toString())) { + log.warn("Kerberos is not yet implemented, skipping authentication...."); + } else { + doPasswdAuth(username, password); + } } SessionUser sessionUser = SESSION_USER_INSTANCE_MAP.get(username); if (sessionUser == null) { @@ -202,20 +207,7 @@ public abstract class BaseLensService extends CompositeService implements Extern } String clusterUser = sessionConf.get(LensConfConstants.SESSION_CLUSTER_USER); password = "useless"; - if (cliService.getHiveConf().getVar(ConfVars.HIVE_SERVER2_AUTHENTICATION) - .equals(HiveAuthFactory.AuthTypes.KERBEROS.toString()) - && cliService.getHiveConf().getBoolVar(ConfVars.HIVE_SERVER2_ENABLE_DOAS)) { - String delegationTokenStr = null; - try { - delegationTokenStr = cliService.getDelegationTokenFromMetaStore(username); - } catch (UnsupportedOperationException e) { - // The delegation token is not applicable in the given deployment mode - } - sessionHandle = cliService.openSessionWithImpersonation(clusterUser, password, sessionConf, - delegationTokenStr); - } else { - sessionHandle = cliService.openSession(clusterUser, password, sessionConf); - } + sessionHandle = cliService.openSession(clusterUser, password, sessionConf); } catch (Exception e) { throw new LensException(e); } http://git-wip-us.apache.org/repos/asf/lens/blob/ea74a2c9/lens-server/src/main/java/org/apache/lens/server/LensServices.java ---------------------------------------------------------------------- diff --git a/lens-server/src/main/java/org/apache/lens/server/LensServices.java b/lens-server/src/main/java/org/apache/lens/server/LensServices.java index 903b19f..5f4a699 100644 --- a/lens-server/src/main/java/org/apache/lens/server/LensServices.java +++ b/lens-server/src/main/java/org/apache/lens/server/LensServices.java @@ -30,10 +30,12 @@ import java.util.concurrent.*; import org.apache.lens.api.error.ErrorCollection; import org.apache.lens.api.error.ErrorCollectionFactory; +import org.apache.lens.server.api.LensConfConstants; import org.apache.lens.server.api.ServiceProvider; import org.apache.lens.server.api.error.LensException; import org.apache.lens.server.api.events.LensEventService; import org.apache.lens.server.api.metrics.MetricsService; +import org.apache.lens.server.api.util.LensUtil; import org.apache.lens.server.metrics.MetricsServiceImpl; import org.apache.lens.server.model.LogSegregationContext; import org.apache.lens.server.model.MappedDiagnosticLogSegregationContext; @@ -49,6 +51,7 @@ import org.apache.hadoop.fs.Path; import org.apache.hadoop.hive.conf.HiveConf; import org.apache.hive.service.CompositeService; import org.apache.hive.service.Service; +import org.apache.hive.service.auth.HiveAuthFactory; import org.apache.hive.service.cli.CLIService; import lombok.Getter; @@ -104,6 +107,11 @@ public class LensServices extends CompositeService implements ServiceProvider { */ public static final String SERVER_STATE_PERSISTENCE_ERRORS = "total-server-state-persistence-errors"; + /** + * The Constant SERVER_STATE_PERSISTENCE_ERRORS. + */ + public static final String KDC_LOGIN_ERRORS = "total-kdc-login-errors"; + /** The service mode. */ @Getter @Setter @@ -112,6 +120,9 @@ public class LensServices extends CompositeService implements ServiceProvider { /** Scheduled Executor which persists the server state periodically*/ private ScheduledExecutorService serverSnapshotScheduler; + /** Scheduled Executor to refresh kerberos tgt*/ + private ScheduledExecutorService kerberosTgtScheduler; + /* Lock for synchronizing persistence of LensServices state */ private final Object statePersistenceLock = new Object(); @@ -122,6 +133,7 @@ public class LensServices extends CompositeService implements ServiceProvider { private long serverStatePersistenceInterval; + private long serverKdcLoginInterval; @Getter private final LogSegregationContext logSegregationContext; @@ -277,12 +289,58 @@ public class LensServices extends CompositeService implements ServiceProvider { } } + /** + * Setup KDC logint thread. + * + */ + private void enableKDCLoginThread() { + + try { + LensUtil.refreshLensTGT(conf); + } catch (Exception e) { + throw new RuntimeException(e); + } + + serverKdcLoginInterval = conf.getInt(LensConfConstants.KDC_LOGIN_SERVICE_INTERVAL_IN_MINUTES, + LensConfConstants.DEFAULT_KDC_LOGIN_SERVICE_INTERVAL_IN_MINUTES); + + ThreadFactory factory = new BasicThreadFactory.Builder() + .namingPattern("Lens-server-refresh-tgt-Thread-%d") + .daemon(true) + .priority(Thread.NORM_PRIORITY) + .build(); + kerberosTgtScheduler = Executors.newSingleThreadScheduledExecutor(factory); + kerberosTgtScheduler.scheduleWithFixedDelay(new Runnable() { + @Override + public void run() { + try { + final String runId = UUID.randomUUID().toString(); + logSegregationContext.setLogSegregationId(runId); + LensUtil.refreshLensTGT(conf); + log.info("KDC login successful for lens."); + } catch (Exception e) { + incrCounter(SERVER_STATE_PERSISTENCE_ERRORS); + log.error("Unable to login to KDC...", e); + } + } + }, 0, serverKdcLoginInterval, TimeUnit.MINUTES); + } + + /* * (non-Javadoc) * * @see org.apache.hive.service.CompositeService#start() */ public synchronized void start() { + + if (cliService.getHiveConf().getVar(HiveConf.ConfVars.HIVE_SERVER2_AUTHENTICATION) + .equals(HiveAuthFactory.AuthTypes.KERBEROS.toString())) { + + enableKDCLoginThread(); + log.info("Enabled kerberos tgt login at {} minutes interval", serverKdcLoginInterval); + } + if (getServiceState() != STATE.STARTED) { super.start(); } @@ -310,9 +368,12 @@ public class LensServices extends CompositeService implements ServiceProvider { } } }, serverStatePersistenceInterval, serverStatePersistenceInterval, TimeUnit.MILLISECONDS); + log.info("Enabled periodic persistence of lens server state at {} millis interval", - serverStatePersistenceInterval); + serverStatePersistenceInterval); + } + } /** http://git-wip-us.apache.org/repos/asf/lens/blob/ea74a2c9/lens-server/src/main/java/org/apache/lens/server/session/HiveSessionService.java ---------------------------------------------------------------------- diff --git a/lens-server/src/main/java/org/apache/lens/server/session/HiveSessionService.java b/lens-server/src/main/java/org/apache/lens/server/session/HiveSessionService.java index 31ac358..d1ef716 100644 --- a/lens-server/src/main/java/org/apache/lens/server/session/HiveSessionService.java +++ b/lens-server/src/main/java/org/apache/lens/server/session/HiveSessionService.java @@ -335,6 +335,7 @@ public class HiveSessionService extends BaseLensService implements SessionServic this.databaseResourceService = new DatabaseResourceService(DatabaseResourceService.NAME); addService(this.databaseResourceService); this.conf = hiveConf; + super.init(hiveConf); } http://git-wip-us.apache.org/repos/asf/lens/blob/ea74a2c9/lens-server/src/main/resources/lensserver-default.xml ---------------------------------------------------------------------- diff --git a/lens-server/src/main/resources/lensserver-default.xml b/lens-server/src/main/resources/lensserver-default.xml index 28b1db2..bef8251 100644 --- a/lens-server/src/main/resources/lensserver-default.xml +++ b/lens-server/src/main/resources/lensserver-default.xml @@ -965,4 +965,17 @@ "lens.cube.metastore.enable.datacompleteness.check" is set. </description> </property> + + <property> + <name>lens.server.kdc.login.service.interval.minutes</name> + <value>360</value> + <description>interval in minutes to refresh auth token when kerberos is enabled on hdfs and/or hive, metastore</description> + </property> + + <property> + <name>lens.server.principal</name> + <value>lens/[email protected]</value> + <description>lens server principal name, must be in format lens/_HOST@KDC_REALM</description> + </property> + </configuration> http://git-wip-us.apache.org/repos/asf/lens/blob/ea74a2c9/lens-server/src/test/resources/lens-site.xml ---------------------------------------------------------------------- diff --git a/lens-server/src/test/resources/lens-site.xml b/lens-server/src/test/resources/lens-site.xml index 7e5f522..f5a0237 100644 --- a/lens-server/src/test/resources/lens-site.xml +++ b/lens-server/src/test/resources/lens-site.xml @@ -207,4 +207,16 @@ <value>3</value> </property> + <property> + <name>lens.server.kdc.login.service.interval.minutes</name> + <value>360</value> + <description>interval in minutes to refresh auth token when kerberos is enabled on hdfs and/or hive, metastore</description> + </property> + + <property> + <name>lens.server.principal</name> + <value>lens/[email protected]</value> + <description>lens server principal name, must be in format lens/_HOST@KDC_REALM</description> + </property> + </configuration> http://git-wip-us.apache.org/repos/asf/lens/blob/ea74a2c9/tools/scripts/lens-ctl ---------------------------------------------------------------------- diff --git a/tools/scripts/lens-ctl b/tools/scripts/lens-ctl index 304b4f5..073ecd8 100755 --- a/tools/scripts/lens-ctl +++ b/tools/scripts/lens-ctl @@ -155,7 +155,8 @@ start() { pushd ${BASEDIR} > /dev/null TIME=`date +%Y%m%d%H%M%s` - nohup ${JAVA_BIN} ${JAVA_PROPERTIES} -cp ${LENSCPPATH} org.apache.lens.server.LensServer $* > "${LENS_LOG_DIR}/lensserver.out.$TIME" 2>&1 < /dev/null & + JAVA_OPTS="-Djavax.security.auth.useSubjectCredsOnly=false" + nohup ${JAVA_BIN} ${JAVA_PROPERTIES} ${JAVA_OPTS} -cp ${LENSCPPATH} org.apache.lens.server.LensServer $* > "${LENS_LOG_DIR}/lensserver.out.$TIME" 2>&1 < /dev/null & echo $! > $LENS_PID_FILE popd > /dev/null @@ -353,5 +354,4 @@ if [ -n "$opt_force" ] ; then else run $args fi -exit 0 - +exit 0 \ No newline at end of file
