blob: cc2ef8acc10aec7a8124780eb272b2226c98fec6 [file] [log] [blame]
/*
* 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.atlas.web.listeners;
import org.apache.atlas.ApplicationProperties;
import org.apache.atlas.AtlasException;
import org.apache.atlas.security.SecurityProperties;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.SecurityUtil;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.util.Shell;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* A class capable of performing a simple or kerberos login.
*/
public class LoginProcessor {
private static final Logger LOG = LoggerFactory.getLogger(LoginProcessor.class);
public static final String ATLAS_AUTHENTICATION_PREFIX = "atlas.authentication.";
public static final String AUTHENTICATION_KERBEROS_METHOD = ATLAS_AUTHENTICATION_PREFIX + "method.kerberos";
public static final String AUTHENTICATION_PRINCIPAL = ATLAS_AUTHENTICATION_PREFIX + "principal";
public static final String AUTHENTICATION_KEYTAB = ATLAS_AUTHENTICATION_PREFIX + "keytab";
/**
* Perform a SIMPLE login based on established OS identity or a kerberos based login using the configured
* principal and keytab (via atlas-application.properties).
*/
public void login() {
// first, let's see if we're running in a hadoop cluster and have the env configured
boolean isHadoopCluster = isHadoopCluster();
Configuration hadoopConfig = isHadoopCluster ? getHadoopConfiguration() : new Configuration(false);
org.apache.commons.configuration.Configuration configuration = getApplicationConfiguration();
if (!isHadoopCluster) {
// need to read the configured authentication choice and create the UGI configuration
setupHadoopConfiguration(hadoopConfig, configuration);
}
doServiceLogin(hadoopConfig, configuration);
}
protected void doServiceLogin(Configuration hadoopConfig,
org.apache.commons.configuration.Configuration configuration) {
UserGroupInformation.setConfiguration(hadoopConfig);
UserGroupInformation ugi = null;
UserGroupInformation.AuthenticationMethod authenticationMethod =
SecurityUtil.getAuthenticationMethod(hadoopConfig);
try {
if (authenticationMethod == UserGroupInformation.AuthenticationMethod.SIMPLE) {
UserGroupInformation.loginUserFromSubject(null);
} else if (authenticationMethod == UserGroupInformation.AuthenticationMethod.KERBEROS) {
String bindAddress = getHostname(configuration);
UserGroupInformation.loginUserFromKeytab(
getServerPrincipal(configuration.getString(AUTHENTICATION_PRINCIPAL), bindAddress),
configuration.getString(AUTHENTICATION_KEYTAB));
}
LOG.info("Logged in user {}", UserGroupInformation.getLoginUser());
} catch (IOException e) {
throw new IllegalStateException(String.format("Unable to perform %s login.", authenticationMethod), e);
}
}
private String getHostname(org.apache.commons.configuration.Configuration configuration) {
String bindAddress = configuration.getString(SecurityProperties.BIND_ADDRESS);
if (bindAddress == null) {
LOG.info("No host name configured. Defaulting to local host name.");
try {
bindAddress = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
throw new IllegalStateException(e);
}
}
return bindAddress;
}
protected void setupHadoopConfiguration(Configuration hadoopConfig, org.apache.commons.configuration.Configuration
configuration) {
String authMethod = "";
String kerberosAuthNEnabled = configuration != null ? configuration.getString(AUTHENTICATION_KERBEROS_METHOD) : null;
// getString may return null, and would like to log the nature of the default setting
if (kerberosAuthNEnabled == null || kerberosAuthNEnabled.equalsIgnoreCase("false")) {
LOG.info("No authentication method configured. Defaulting to simple authentication");
authMethod = "simple";
} else if (kerberosAuthNEnabled.equalsIgnoreCase("true")) {
authMethod = "kerberos";
}
SecurityUtil
.setAuthenticationMethod(UserGroupInformation.AuthenticationMethod.valueOf(authMethod.toUpperCase()),
hadoopConfig);
}
/**
* Return a server (service) principal. The token "_HOST" in the principal will be replaced with the local host
* name (e.g. dgi/_HOST will be changed to dgi/localHostName)
* @param principal the input principal containing an option "_HOST" token
* @return the service principal.
* @throws IOException
*/
private String getServerPrincipal(String principal, String host) throws IOException {
return SecurityUtil.getServerPrincipal(principal, host);
}
/**
* Returns a Hadoop configuration instance.
* @return the configuration.
*/
protected Configuration getHadoopConfiguration() {
return new Configuration();
}
/**
* Returns the metadata application configuration.
* @return the metadata configuration.
* @throws ConfigurationException
*/
protected org.apache.commons.configuration.Configuration getApplicationConfiguration() {
try {
return ApplicationProperties.get();
} catch (AtlasException e) {
LOG.warn("Error reading application configuration", e);
}
return null;
}
/**
* Uses a hadoop shell to discern whether a hadoop cluster is available/configured.
* @return true if a hadoop cluster is detected.
*/
protected boolean isHadoopCluster() {
boolean isHadoopCluster = false;
try {
isHadoopCluster = Shell.getHadoopHome() != null;
} catch (IOException e) {
// ignore - false is default setting
}
return isHadoopCluster;
}
}