001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *      http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.apache.oozie.action.hadoop;
020
021import com.google.common.base.Preconditions;
022import com.google.common.base.Strings;
023import org.apache.hadoop.conf.Configuration;
024import org.apache.hadoop.fs.FileSystem;
025import org.apache.hadoop.net.NetUtils;
026import org.apache.hadoop.security.Credentials;
027import org.apache.hadoop.security.SecurityUtil;
028import org.apache.hadoop.yarn.api.ApplicationConstants;
029import org.apache.hadoop.yarn.client.api.YarnClient;
030import org.apache.hadoop.yarn.exceptions.YarnException;
031import org.apache.oozie.ErrorCode;
032import org.apache.oozie.action.ActionExecutor;
033import org.apache.oozie.service.HadoopAccessorException;
034import org.apache.oozie.service.HadoopAccessorService;
035import org.apache.oozie.util.XLog;
036
037import java.io.IOException;
038import java.net.URISyntaxException;
039
040public class HadoopTokenHelper {
041    /** The Kerberos principal for the resource manager.*/
042    protected static final String RM_PRINCIPAL = "yarn.resourcemanager.principal";
043    protected static final String HADOOP_YARN_RM = "yarn.resourcemanager.address";
044    private XLog LOG = XLog.getLog(getClass());
045
046    private String getServicePrincipal(final Configuration configuration) {
047        return configuration.get(RM_PRINCIPAL);
048    }
049
050    String getServerPrincipal(final Configuration configuration) throws IOException {
051        return getServerPrincipal(configuration, getServicePrincipal(configuration));
052    }
053
054    /**
055     * Mimic {@link org.apache.hadoop.mapred.Master#getMasterPrincipal}, get Kerberos principal for use as delegation token renewer.
056     *
057     * @param configuration the {@link Configuration} containing the YARN RM address
058     * @param servicePrincipal the configured service principal
059     * @return the server principal originating from the host name and the service principal
060     * @throws IOException when something goes wrong finding out the local address inside
061     * {@link SecurityUtil#getServerPrincipal(String, String)}
062     */
063    private String getServerPrincipal(final Configuration configuration, final String servicePrincipal) throws IOException {
064        Preconditions.checkNotNull(configuration, "configuration has to be filled");
065        Preconditions.checkArgument(!Strings.isNullOrEmpty(servicePrincipal), "servicePrincipal has to be filled");
066        Preconditions.checkArgument(!Strings.isNullOrEmpty(configuration.get(HADOOP_YARN_RM)),
067                String.format("configuration entry %s has to be filled", HADOOP_YARN_RM));
068
069        String serverPrincipal;
070        final String target = configuration.get(HADOOP_YARN_RM);
071
072        try {
073            final String addr = NetUtils.createSocketAddr(target).getHostName();
074            serverPrincipal = SecurityUtil.getServerPrincipal(servicePrincipal, addr);
075            LOG.info("Delegation Token Renewer details: Principal={0},Target={1}", serverPrincipal, target);
076        } catch (final IllegalArgumentException iae) {
077            LOG.warn("An error happened while trying to get server principal. Getting it from service principal anyway.", iae);
078
079            serverPrincipal = servicePrincipal.split("[/@]")[0];
080            LOG.info("Delegation Token Renewer for {0} is {1}", target, serverPrincipal);
081        }
082
083        return serverPrincipal;
084    }
085}