co.cask.cdap.security.impersonation.DefaultImpersonator.java Source code

Java tutorial

Introduction

Here is the source code for co.cask.cdap.security.impersonation.DefaultImpersonator.java

Source

/*
 * Copyright  2016-2017 Cask Data, Inc.
 *
 * Licensed 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 co.cask.cdap.security.impersonation;

import co.cask.cdap.common.NamespaceNotFoundException;
import co.cask.cdap.common.conf.CConfiguration;
import co.cask.cdap.common.kerberos.ImpersonatedOpType;
import co.cask.cdap.common.kerberos.ImpersonationInfo;
import co.cask.cdap.common.kerberos.OwnerAdmin;
import co.cask.cdap.common.kerberos.SecurityUtil;
import co.cask.cdap.proto.id.NamespaceId;
import co.cask.cdap.proto.id.NamespacedEntityId;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Throwables;
import com.google.inject.Inject;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.authentication.util.KerberosName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.concurrent.Callable;

/**
 * Default implementation of {@link Impersonator} that impersonate using {@link UGIProvider}.
 */
public class DefaultImpersonator implements Impersonator {

    private static final Logger LOG = LoggerFactory.getLogger(DefaultImpersonator.class);

    private final CConfiguration cConf;
    private final OwnerAdmin ownerAdmin;
    private final boolean kerberosEnabled;
    private final UGIProvider ugiProvider;

    @Inject
    @VisibleForTesting
    public DefaultImpersonator(CConfiguration cConf, UGIProvider ugiProvider, OwnerAdmin ownerAdmin) {
        this.cConf = cConf;
        this.ownerAdmin = ownerAdmin;
        this.ugiProvider = ugiProvider;
        this.kerberosEnabled = SecurityUtil.isKerberosEnabled(cConf);
    }

    @Override
    public <T> T doAs(NamespacedEntityId entityId, final Callable<T> callable) throws Exception {
        return doAs(entityId, callable, ImpersonatedOpType.OTHER);
    }

    @Override
    public <T> T doAs(NamespacedEntityId entityId, Callable<T> callable, ImpersonatedOpType impersonatedOpType)
            throws Exception {
        UserGroupInformation ugi = getUGI(entityId, impersonatedOpType);
        return ImpersonationUtils.doAs(ugi, callable);
    }

    @Override
    public UserGroupInformation getUGI(NamespacedEntityId entityId) throws IOException, NamespaceNotFoundException {
        return getUGI(entityId, ImpersonatedOpType.OTHER);
    }

    private UserGroupInformation getUGI(NamespacedEntityId entityId, ImpersonatedOpType impersonatedOpType)
            throws IOException, NamespaceNotFoundException {
        // don't impersonate if kerberos isn't enabled OR if the operation is in the system namespace
        if (!kerberosEnabled || NamespaceId.SYSTEM.equals(entityId.getNamespaceId())) {
            return UserGroupInformation.getCurrentUser();
        }
        try {
            ImpersonationInfo info = SecurityUtil.createImpersonationInfo(ownerAdmin, cConf, entityId,
                    impersonatedOpType);
            LOG.debug("Impersonating principal {} for entity {}, keytab path is {}", info.getPrincipal(), entityId,
                    info.getKeytabURI());
            return getUGI(info);
        } catch (Exception e) {
            Throwables.propagateIfInstanceOf(e, IOException.class);
            throw Throwables.propagate(e);
        }
    }

    private UserGroupInformation getUGI(ImpersonationInfo impersonationInfo) throws IOException {
        // no need to get a UGI if the current UGI is the one we're requesting; simply return it
        String configuredPrincipalShortName = new KerberosName(impersonationInfo.getPrincipal()).getShortName();
        if (UserGroupInformation.getCurrentUser().getShortUserName().equals(configuredPrincipalShortName)) {
            return UserGroupInformation.getCurrentUser();
        }
        return ugiProvider.getConfiguredUGI(impersonationInfo);
    }
}