From 7864f6210ae5e147654fc9e1bc47b0560eaa79fa Mon Sep 17 00:00:00 2001 From: Kent Yao Date: Mon, 26 Oct 2020 17:59:01 +0800 Subject: [PATCH] auth conf --- .../org/apache/kyuubi/config/KyuubiConf.scala | 73 ++++++++++++++ .../KyuubiAuthenticationFactory.scala | 1 + .../KyuubiDelegationTokenManager.scala | 1 + .../LdapAuthenticationProviderImpl.scala | 1 + .../service/authentication/package.scala | 98 ------------------- .../KyuubiAuthenticationFactorySuite.scala | 79 +++++++++++++++ .../LdapAuthenticationProviderImplSuite.scala | 1 + .../service/authentication/SaslQOPSuite.scala | 1 + 8 files changed, 157 insertions(+), 98 deletions(-) delete mode 100644 kyuubi-common/src/main/scala/org/apache/kyuubi/service/authentication/package.scala create mode 100644 kyuubi-common/src/test/scala/org/apache/kyuubi/service/authentication/KyuubiAuthenticationFactorySuite.scala diff --git a/kyuubi-common/src/main/scala/org/apache/kyuubi/config/KyuubiConf.scala b/kyuubi-common/src/main/scala/org/apache/kyuubi/config/KyuubiConf.scala index cbb960820..613cc5051 100644 --- a/kyuubi-common/src/main/scala/org/apache/kyuubi/config/KyuubiConf.scala +++ b/kyuubi-common/src/main/scala/org/apache/kyuubi/config/KyuubiConf.scala @@ -18,11 +18,13 @@ package org.apache.kyuubi.config import java.time.Duration +import java.util.Locale import java.util.concurrent.ConcurrentHashMap import scala.collection.JavaConverters._ import org.apache.kyuubi.{Logging, Utils} +import org.apache.kyuubi.service.authentication.{AuthTypes, SaslQOP} case class KyuubiConf(loadSysDefault: Boolean = true) extends Logging { private val settings = new ConcurrentHashMap[String, String]() @@ -224,6 +226,77 @@ object KyuubiConf { .timeConf .createWithDefault(Duration.ofMillis(100).toMillis) + val AUTHENTICATION_METHOD: ConfigEntry[String] = buildConf("authentication") + .doc("Client authentication types." + + " NONE: no authentication check." + + " KERBEROS: Kerberos/GSSAPI authentication." + + " LDAP: Lightweight Directory Access Protocol authentication.") + .version("1.0.0") + .stringConf + .transform(_.toUpperCase(Locale.ROOT)) + .checkValues(AuthTypes.values.map(_.toString)) + .createWithDefault(AuthTypes.NONE.toString) + + val AUTHENTICATION_LDAP_URL: OptionalConfigEntry[String] = buildConf("authentication.ldap.url") + .doc("SPACE character separated LDAP connection URL(s).") + .version("1.0.0") + .stringConf + .createOptional + + val AUTHENTICATION_LDAP_BASEDN: OptionalConfigEntry[String] = + buildConf("authentication.ldap.base.dn") + .doc("LDAP base DN.") + .version("1.0.0") + .stringConf + .createOptional + + val AUTHENTICATION_LDAP_DOMAIN: OptionalConfigEntry[String] = + buildConf("authentication.ldap.domain") + .doc("LDAP base DN.") + .version("1.0.0") + .stringConf + .createOptional + + val DELEGATION_KEY_UPDATE_INTERVAL: ConfigEntry[Long] = + buildConf("delegation.key.update.interval") + .doc("") + .version("1.0.0") + .timeConf + .createWithDefault(Duration.ofDays(1).toMillis) + + val DELEGATION_TOKEN_MAX_LIFETIME: ConfigEntry[Long] = + buildConf("delegation.token.max.lifetime") + .doc("") + .version("1.0.0") + .timeConf + .createWithDefault(Duration.ofDays(7).toMillis) + + val DELEGATION_TOKEN_GC_INTERVAL: ConfigEntry[Long] = + buildConf("delegation.token.gc.interval") + .doc("") + .version("1.0.0") + .timeConf + .createWithDefault(Duration.ofHours(1).toMillis) + + val DELEGATION_TOKEN_RENEW_INTERVAL: ConfigEntry[Long] = + buildConf("delegation.token.renew.interval") + .doc("") + .version("1.0.0") + .timeConf + .createWithDefault(Duration.ofDays(7).toMillis) + + val SASL_QOP: ConfigEntry[String] = buildConf("sasl.qop") + .doc("Sasl QOP enable higher levels of protection for Kyuubi communication with clients." + + " auth - authentication only (default)" + + " auth-int - authentication plus integrity protection" + + " auth-conf - authentication plus integrity and confidentiality protectionThis is" + + " applicable only if Kyuubi is configured to use Kerberos authentication.") + .version("1.0.0") + .stringConf + .checkValues(SaslQOP.values.map(_.toString)) + .transform(_.toLowerCase(Locale.ROOT)) + .createWithDefault(SaslQOP.AUTH.toString) + ///////////////////////////////////////////////////////////////////////////////////////////////// // SQL Engine Configuration // ///////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/kyuubi-common/src/main/scala/org/apache/kyuubi/service/authentication/KyuubiAuthenticationFactory.scala b/kyuubi-common/src/main/scala/org/apache/kyuubi/service/authentication/KyuubiAuthenticationFactory.scala index 776f50ac1..4b21338fb 100644 --- a/kyuubi-common/src/main/scala/org/apache/kyuubi/service/authentication/KyuubiAuthenticationFactory.scala +++ b/kyuubi-common/src/main/scala/org/apache/kyuubi/service/authentication/KyuubiAuthenticationFactory.scala @@ -32,6 +32,7 @@ import org.apache.thrift.transport.{TTransportException, TTransportFactory} import org.apache.kyuubi.KyuubiSQLException import org.apache.kyuubi.config.KyuubiConf +import org.apache.kyuubi.config.KyuubiConf._ import org.apache.kyuubi.service.authentication.AuthTypes._ class KyuubiAuthenticationFactory(conf: KyuubiConf) { diff --git a/kyuubi-common/src/main/scala/org/apache/kyuubi/service/authentication/KyuubiDelegationTokenManager.scala b/kyuubi-common/src/main/scala/org/apache/kyuubi/service/authentication/KyuubiDelegationTokenManager.scala index ae7b323ea..3c941589c 100644 --- a/kyuubi-common/src/main/scala/org/apache/kyuubi/service/authentication/KyuubiDelegationTokenManager.scala +++ b/kyuubi-common/src/main/scala/org/apache/kyuubi/service/authentication/KyuubiDelegationTokenManager.scala @@ -20,6 +20,7 @@ package org.apache.kyuubi.service.authentication import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenSecretManager import org.apache.kyuubi.config.KyuubiConf +import org.apache.kyuubi.config.KyuubiConf._ case class KyuubiDelegationTokenManager( keyUpdateInterval: Long, diff --git a/kyuubi-common/src/main/scala/org/apache/kyuubi/service/authentication/LdapAuthenticationProviderImpl.scala b/kyuubi-common/src/main/scala/org/apache/kyuubi/service/authentication/LdapAuthenticationProviderImpl.scala index a7b5b9401..7b55e1c5a 100644 --- a/kyuubi-common/src/main/scala/org/apache/kyuubi/service/authentication/LdapAuthenticationProviderImpl.scala +++ b/kyuubi-common/src/main/scala/org/apache/kyuubi/service/authentication/LdapAuthenticationProviderImpl.scala @@ -24,6 +24,7 @@ import javax.security.sasl.AuthenticationException import org.apache.commons.lang.StringUtils import org.apache.kyuubi.config.KyuubiConf +import org.apache.kyuubi.config.KyuubiConf._ import org.apache.kyuubi.service.ServiceUtils class LdapAuthenticationProviderImpl(conf: KyuubiConf) extends PasswdAuthenticationProvider { diff --git a/kyuubi-common/src/main/scala/org/apache/kyuubi/service/authentication/package.scala b/kyuubi-common/src/main/scala/org/apache/kyuubi/service/authentication/package.scala deleted file mode 100644 index ff0e72086..000000000 --- a/kyuubi-common/src/main/scala/org/apache/kyuubi/service/authentication/package.scala +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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.kyuubi.service - -import java.time.Duration -import java.util.Locale - -import org.apache.kyuubi.config.{ConfigEntry, OptionalConfigEntry} -import org.apache.kyuubi.config.KyuubiConf._ - -package object authentication { - - val AUTHENTICATION_METHOD: ConfigEntry[String] = buildConf("authentication") - .doc("Client authentication types." + - " NONE: no authentication check." + - " KERBEROS: Kerberos/GSSAPI authentication." + - " LDAP: Lightweight Directory Access Protocol authentication.") - .version("1.0.0") - .stringConf - .transform(_.toUpperCase(Locale.ROOT)) - .checkValues(AuthTypes.values.map(_.toString)) - .createWithDefault(AuthTypes.NONE.toString) - - val AUTHENTICATION_LDAP_URL: OptionalConfigEntry[String] = buildConf("authentication.ldap.url") - .doc("SPACE character separated LDAP connection URL(s).") - .version("1.0.0") - .stringConf - .createOptional - - val AUTHENTICATION_LDAP_BASEDN: OptionalConfigEntry[String] = - buildConf("authentication.ldap.base.dn") - .doc("LDAP base DN.") - .version("1.0.0") - .stringConf - .createOptional - - val AUTHENTICATION_LDAP_DOMAIN: OptionalConfigEntry[String] = - buildConf("authentication.ldap.domain") - .doc("LDAP base DN.") - .version("1.0.0") - .stringConf - .createOptional - - val DELEGATION_KEY_UPDATE_INTERVAL: ConfigEntry[Long] = - buildConf("delegation.key.update.interval") - .doc("") - .version("1.0.0") - .timeConf - .createWithDefault(Duration.ofDays(1).toMillis) - - val DELEGATION_TOKEN_MAX_LIFETIME: ConfigEntry[Long] = - buildConf("delegation.token.max.lifetime") - .doc("") - .version("1.0.0") - .timeConf - .createWithDefault(Duration.ofDays(7).toMillis) - - val DELEGATION_TOKEN_GC_INTERVAL: ConfigEntry[Long] = - buildConf("delegation.token.gc.interval") - .doc("") - .version("1.0.0") - .timeConf - .createWithDefault(Duration.ofHours(1).toMillis) - - val DELEGATION_TOKEN_RENEW_INTERVAL: ConfigEntry[Long] = - buildConf("delegation.token.renew.interval") - .doc("") - .version("1.0.0") - .timeConf - .createWithDefault(Duration.ofDays(7).toMillis) - - val SASL_QOP: ConfigEntry[String] = buildConf("sasl.qop") - .doc("Sasl QOP enable higher levels of protection for Kyuubi communication with clients." + - " auth - authentication only (default)" + - " auth-int - authentication plus integrity protection" + - " auth-conf - authentication plus integrity and confidentiality protectionThis is" + - " applicable only if Kyuubi is configured to use Kerberos authentication.") - .version("1.0.0") - .stringConf - .checkValues(SaslQOP.values.map(_.toString)) - .transform(_.toLowerCase(Locale.ROOT)) - .createWithDefault(SaslQOP.AUTH.toString) -} diff --git a/kyuubi-common/src/test/scala/org/apache/kyuubi/service/authentication/KyuubiAuthenticationFactorySuite.scala b/kyuubi-common/src/test/scala/org/apache/kyuubi/service/authentication/KyuubiAuthenticationFactorySuite.scala new file mode 100644 index 000000000..411f8c4fe --- /dev/null +++ b/kyuubi-common/src/test/scala/org/apache/kyuubi/service/authentication/KyuubiAuthenticationFactorySuite.scala @@ -0,0 +1,79 @@ +/* + * 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.kyuubi.service.authentication + +import java.security.Security +import javax.security.auth.login.LoginException + +import org.apache.kyuubi.{KyuubiFunSuite, KyuubiSQLException} +import org.apache.kyuubi.config.KyuubiConf +import org.apache.kyuubi.service.authentication.PlainSASLServer.SaslPlainProvider +import org.apache.kyuubi.util.KyuubiHadoopUtils + + +class KyuubiAuthenticationFactorySuite extends KyuubiFunSuite { + import KyuubiAuthenticationFactory._ + + test("verify proxy access") { + val kyuubiConf = KyuubiConf() + val hadoopConf = KyuubiHadoopUtils.newHadoopConf(kyuubiConf) + + val e1 = intercept[KyuubiSQLException] { + verifyProxyAccess("kent", "yao", "localhost", hadoopConf) + } + assert(e1.getMessage === "Failed to validate proxy privilege of kent for yao") + + kyuubiConf.set("kyuubi.hadoop.proxyuser.kent.groups", "*") + kyuubiConf.set("kyuubi.hadoop.proxyuser.kent.hosts", "*") + val hadoopConf2 = KyuubiHadoopUtils.newHadoopConf(kyuubiConf) + verifyProxyAccess("kent", "yao", "localhost", hadoopConf2) + } + + test("AuthType NONE") { + val kyuubiConf = KyuubiConf() + val auth = new KyuubiAuthenticationFactory(kyuubiConf) + auth.getTTransportFactory + assert(Security.getProviders.exists(_.isInstanceOf[SaslPlainProvider])) + + assert(auth.getIpAddress.isEmpty) + assert(auth.getRemoteUser.isEmpty) + } + + test("AuthType Other") { + val conf = KyuubiConf().set(KyuubiConf.AUTHENTICATION_METHOD, "INVALID") + val e = intercept[IllegalArgumentException](new KyuubiAuthenticationFactory(conf)) + assert(e.getMessage === "The value of kyuubi.authentication should be one of" + + " KERBEROS, LDAP, NONE, NOSASL, but was INVALID") + } + + test("AuthType LDAP") { + val conf = KyuubiConf().set(KyuubiConf.AUTHENTICATION_METHOD, "LDAP") + val authFactory = new KyuubiAuthenticationFactory(conf) + authFactory.getTTransportFactory + assert(Security.getProviders.exists(_.isInstanceOf[SaslPlainProvider])) + } + + + test("AuthType KERBEROS w/o keytab/principal") { + val conf = KyuubiConf().set(KyuubiConf.AUTHENTICATION_METHOD, "KERBEROS") + + val factory = new KyuubiAuthenticationFactory(conf) + val e = intercept[LoginException](factory.getTTransportFactory) + assert(e.getMessage startsWith "Kerberos principal should have 3 parts") + } +} diff --git a/kyuubi-common/src/test/scala/org/apache/kyuubi/service/authentication/LdapAuthenticationProviderImplSuite.scala b/kyuubi-common/src/test/scala/org/apache/kyuubi/service/authentication/LdapAuthenticationProviderImplSuite.scala index 8aea7b24a..d9db50708 100644 --- a/kyuubi-common/src/test/scala/org/apache/kyuubi/service/authentication/LdapAuthenticationProviderImplSuite.scala +++ b/kyuubi-common/src/test/scala/org/apache/kyuubi/service/authentication/LdapAuthenticationProviderImplSuite.scala @@ -41,6 +41,7 @@ import org.apache.mina.util.AvailablePortFinder import org.apache.kyuubi.{KyuubiFunSuite, Utils} import org.apache.kyuubi.config.KyuubiConf +import org.apache.kyuubi.config.KyuubiConf._ class LdapAuthenticationProviderImplSuite extends KyuubiFunSuite { diff --git a/kyuubi-common/src/test/scala/org/apache/kyuubi/service/authentication/SaslQOPSuite.scala b/kyuubi-common/src/test/scala/org/apache/kyuubi/service/authentication/SaslQOPSuite.scala index e9acf7689..258e136f1 100644 --- a/kyuubi-common/src/test/scala/org/apache/kyuubi/service/authentication/SaslQOPSuite.scala +++ b/kyuubi-common/src/test/scala/org/apache/kyuubi/service/authentication/SaslQOPSuite.scala @@ -19,6 +19,7 @@ package org.apache.kyuubi.service.authentication import org.apache.kyuubi.KyuubiFunSuite import org.apache.kyuubi.config.KyuubiConf +import org.apache.kyuubi.config.KyuubiConf.SASL_QOP class SaslQOPSuite extends KyuubiFunSuite {