import org.apache.commons.lang3.StringUtils
import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.security.{SecurityUtil, UserGroupInformation}
import org.apache.kerby.kerberos.kerb.keytab.Keytab
import org.slf4j.Logger
import sun.security.provider.ConfigFile
import java.io.File
import java.net.{URI, URL}
import java.nio.file.{Files, Paths}
import scala.collection.JavaConversions._
import scala.collection.JavaConverters._
import scala.io.Source
case class KerberosConf(var principal: String,var keytab: String,var krb5conf: String="/etc/krb5.conf")
object KerberosUtils {
val LOG: Logger = org.slf4j.LoggerFactory.getLogger(KerberosUtils.getClass)
val JAVA_SECURITY_KRB5_CONF = "java.security.krb5.conf"
val JAVA_SECURITY_AUTH_LOGIN_CONFIG = "java.security.auth.login.config"
def loginKerberos(krb5Principal: String, krb5KeytabPath: String, krb5ConfPath: String, hadoopConf: Configuration): Boolean = {
val authType = hadoopConf.get("hadoop.security.authentication")
if (!"kerberos".equalsIgnoreCase(authType)) {
LOG.error(s"kerberos utils get hadoop authentication type [${authType}] ,not kerberos!")
} else {
LOG.info(s"kerberos utils get hadoop authentication type [${authType}]!")
}
UserGroupInformation.setConfiguration(hadoopConf)
System.setProperty(JAVA_SECURITY_KRB5_CONF, krb5ConfPath)
System.setProperty("javax.security.auth.useSubjectCredsOnly", "false")
UserGroupInformation.loginUserFromKeytab(krb5Principal, krb5KeytabPath)
val user = UserGroupInformation.getLoginUser
if (user.getAuthenticationMethod == UserGroupInformation.AuthenticationMethod.KERBEROS) {
val usnm: String = user.getShortUserName
LOG.info(s"kerberos utils login success, curr user: ${usnm}")
true
} else {
LOG.info("kerberos utils login failed")
false
}
}
def loginKerberos(krb5Principal: String, krb5KeytabPath: String, krb5ConfPath: String): Boolean = {
val hadoopConf = ConfigUtils.getHadoopConfig
hadoopConf.get("hadoop.security.authentication")
loginKerberos(krb5Principal, krb5KeytabPath, krb5ConfPath, hadoopConf)
}
def loginKerberos(kerberosConf: KerberosConf): Boolean = {
loginKerberos(kerberosConf.principal, kerberosConf.keytab, kerberosConf.krb5conf)
}
def loginKerberos(krb5Principal: String, krb5KeytabPath: String, krb5ConfPath: String, hadoopConfDir: String): Boolean = {
ConfigUtils.setHadoopConfDir(hadoopConfDir)
loginKerberos(krb5Principal, krb5KeytabPath, krb5ConfPath)
}
def loginKerberos(): Boolean = {
var principal: String = null
var keytabPath: String = null
var krb5ConfPath: String = null
val classPath: URL = this.getClass.getResource("/")
val classPathObj = Paths.get(classPath.toURI)
var keytabPathList = Files.list(classPathObj).iterator().asScala.toList
keytabPathList = keytabPathList.filter(p => p.toString.toLowerCase().endsWith(".keytab")).toList
val krb5ConfPathList = keytabPathList.filter(p => p.toString.toLowerCase().endsWith("krb5.conf")).toList
if (keytabPathList.nonEmpty) {
val ktPath = keytabPathList.get(0)
val absPath = ktPath.toAbsolutePath
val keytab = Keytab.loadKeytab(new File(absPath.toString))
val pri = keytab.getPrincipals.get(0).getName
if (StringUtils.isNotEmpty(pri)) {
principal = pri
keytabPath = ktPath.toString
}
}
if (krb5ConfPathList.nonEmpty) {
val confPath = krb5ConfPathList.get(0)
krb5ConfPath = confPath.toAbsolutePath.toString
}
if (StringUtils.isNotEmpty(principal) && StringUtils.isNotEmpty(keytabPath) && StringUtils.isNotEmpty(krb5ConfPath)) {
ConfigUtils.configHadoop()
val hadoopConf = ConfigUtils.hadoopConfiguration
loginKerberos(principal, keytabPath, krb5ConfPath, hadoopConf)
} else {
false
}
}
def getCurrLoginUser(): String = {
var usnm: String = null
val user = UserGroupInformation.getLoginUser
if (user.getAuthenticationMethod == UserGroupInformation.AuthenticationMethod.KERBEROS) {
usnm = user.getShortUserName
LOG.debug(s"Kerberos curr login user: ${usnm}")
}
usnm
}
def parseKafkaJaasFile(path: String): KerberosConf = {
val spi = new ConfigFile.Spi(new URI(path))
val opts = spi.engineGetAppConfigurationEntry("KafkaClient").head.getOptions
val principal: String = opts.get("principal").toString
val keytab: String = opts.get("keyTab").toString
KerberosConf(principal,keytab)
}
}