org.apache.accumulo.core.client.security.tokens.KerberosToken.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.accumulo.core.client.security.tokens.KerberosToken.java

Source

/*
 * 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.accumulo.core.client.security.tokens;

import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.Set;

import javax.security.auth.DestroyFailedException;

import org.apache.hadoop.security.UserGroupInformation;

/**
 * Authentication token for Kerberos authenticated clients
 *
 * @since 1.7.0
 */
public class KerberosToken implements AuthenticationToken {

    public static final String CLASS_NAME = KerberosToken.class.getName();

    private static final int VERSION = 1;

    private String principal;
    private File keytab;

    /**
     * Creates a token using the provided principal and the currently logged-in user via {@link UserGroupInformation}.
     *
     * @param principal
     *          The user that is logged in
     */
    public KerberosToken(String principal) throws IOException {
        requireNonNull(principal);
        final UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
        checkArgument(ugi.hasKerberosCredentials(), "Subject is not logged in via Kerberos");
        checkArgument(principal.equals(ugi.getUserName()),
                "Provided principal does not match currently logged-in user");
        this.principal = ugi.getUserName();
    }

    /**
     * Creates a Kerberos token for the specified principal using the provided keytab. The principal and keytab combination are verified by attempting a log in.
     * <p>
     * This constructor does not have any side effects.
     *
     * @param principal
     *          The Kerberos principal
     * @param keytab
     *          A keytab file containing the principal's credentials.
     */
    public KerberosToken(String principal, File keytab) throws IOException {
        this(principal, keytab, false);
    }

    /**
     * Creates a token and logs in via {@link UserGroupInformation} using the provided principal and keytab. A key for the principal must exist in the keytab,
     * otherwise login will fail.
     *
     * @param principal
     *          The Kerberos principal
     * @param keytab
     *          A keytab file
     * @param replaceCurrentUser
     *          Should the current Hadoop user be replaced with this user
     * @deprecated since 1.8.0, @see #KerberosToken(String, File)
     */
    @Deprecated
    public KerberosToken(String principal, File keytab, boolean replaceCurrentUser) throws IOException {
        requireNonNull(principal, "Principal was null");
        requireNonNull(keytab, "Keytab was null");
        checkArgument(keytab.exists() && keytab.isFile(), "Keytab was not a normal file");
        UserGroupInformation ugi;
        if (replaceCurrentUser) {
            UserGroupInformation.loginUserFromKeytab(principal, keytab.getAbsolutePath());
            ugi = UserGroupInformation.getCurrentUser();
        } else {
            ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI(principal, keytab.getAbsolutePath());
        }
        this.principal = ugi.getUserName();
        this.keytab = keytab;
    }

    /**
     * Creates a token using the login user as returned by {@link UserGroupInformation#getCurrentUser()}
     *
     * @throws IOException
     *           If the current logged in user cannot be computed.
     */
    public KerberosToken() throws IOException {
        this(UserGroupInformation.getCurrentUser().getUserName());
    }

    @Override
    public KerberosToken clone() {
        try {
            KerberosToken clone = (KerberosToken) super.clone();
            clone.principal = principal;
            clone.keytab = keytab == null ? keytab : keytab.getCanonicalFile();
            return clone;
        } catch (CloneNotSupportedException | IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (!(obj instanceof KerberosToken))
            return false;
        KerberosToken other = (KerberosToken) obj;

        return principal.equals(other.principal);
    }

    /**
     * The identity of the user to which this token belongs to according to Kerberos
     *
     * @return The principal
     */
    public String getPrincipal() {
        return principal;
    }

    /**
     * The keytab file used to perform Kerberos login. Optional, may be null.
     */
    public File getKeytab() {
        return keytab;
    }

    @Override
    public void write(DataOutput out) throws IOException {
        out.writeInt(VERSION);
    }

    @Override
    public void readFields(DataInput in) throws IOException {
        int actualVersion = in.readInt();
        if (VERSION != actualVersion) {
            throw new IOException("Did not find expected version in serialized KerberosToken");
        }
    }

    @Override
    public synchronized void destroy() throws DestroyFailedException {
        principal = null;
    }

    @Override
    public boolean isDestroyed() {
        return null == principal;
    }

    @Override
    public void init(Properties properties) {

    }

    @Override
    public Set<TokenProperty> getProperties() {
        return Collections.emptySet();
    }

    @Override
    public int hashCode() {
        return principal.hashCode();
    }
}