/**
 * 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.hadoop.security;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.CommonConfigurationKeys;
import org.apache.hadoop.minikdc.MiniKdc;
import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
import org.apache.hadoop.test.GenericTestUtils;
import org.apache.hadoop.util.Time;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.slf4j.event.Level;

import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_KERBEROS_KEYTAB_LOGIN_AUTORENEWAL_ENABLED;
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_KERBEROS_MIN_SECONDS_BEFORE_RELOGIN;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.File;
import java.io.IOException;
import java.security.Principal;
import java.security.PrivilegedExceptionAction;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import javax.security.auth.Subject;
import javax.security.auth.kerberos.KerberosPrincipal;
import javax.security.auth.kerberos.KerberosTicket;
import javax.security.auth.login.LoginContext;

/**
 * Verify UGI login from keytab. Check that the UGI is
 * configured to use keytab to catch regressions like
 * HADOOP-10786.
 */
public class TestUGILoginFromKeytab {

  private MiniKdc kdc;
  private File workDir;
  private ExecutorService executor;

  @Rule
  public final TemporaryFolder folder = new TemporaryFolder();

  @Before
  public void startMiniKdc() throws Exception {
    // This setting below is required. If not enabled, UGI will abort
    // any attempt to loginUserFromKeytab.
    Configuration conf = new Configuration();
    conf.set(CommonConfigurationKeys.HADOOP_SECURITY_AUTHENTICATION,
        "kerberos");
    UserGroupInformation.setConfiguration(conf);
    UserGroupInformation.setShouldRenewImmediatelyForTests(true);
    workDir = folder.getRoot();
    kdc = new MiniKdc(MiniKdc.createConf(), workDir);
    kdc.start();
    executor = Executors.newCachedThreadPool();

  }

  @After
  public void stopMiniKdc() {
    if (kdc != null) {
      kdc.stop();
    }
    if (executor != null) {
      executor.shutdownNow();
    }
  }

  /**
   * Login from keytab using the MiniKDC.
   */
  @Test
  public void testUGILoginFromKeytab() throws Exception {
    long beforeLogin = Time.now();
    String principal = "foo";
    File keytab = new File(workDir, "foo.keytab");
    kdc.createPrincipal(keytab, principal);

    UserGroupInformation.loginUserFromKeytab(principal, keytab.getPath());
    UserGroupInformation ugi = UserGroupInformation.getLoginUser();
    Assert.assertTrue("UGI should be configured to login from keytab",
        ugi.isFromKeytab());

    User user = getUser(ugi.getSubject());
    Assert.assertNotNull(user.getLogin());
 
    Assert.assertTrue("User login time is less than before login time, "
        + "beforeLoginTime:" + beforeLogin + " userLoginTime:" + user.getLastLogin(),
            user.getLastLogin() > beforeLogin);
  }

  /**
   * Login from keytab using the MiniKDC and verify the UGI can successfully
   * relogin from keytab as well. This will catch regressions like HADOOP-10786.
   */
  @Test
  public void testUGIReLoginFromKeytab() throws Exception {
    String principal = "foo";
    File keytab = new File(workDir, "foo.keytab");
    kdc.createPrincipal(keytab, principal);

    UserGroupInformation.loginUserFromKeytab(principal, keytab.getPath());
    UserGroupInformation ugi = UserGroupInformation.getLoginUser();
    Assert.assertTrue("UGI should be configured to login from keytab",
        ugi.isFromKeytab());

    // Verify relogin from keytab.
    User user = getUser(ugi.getSubject());
    final long firstLogin = user.getLastLogin();
    final LoginContext login1 = user.getLogin();
    Assert.assertNotNull(login1);

    // Sleep for 2 secs to have a difference between first and second login
    Thread.sleep(2000);

    ugi.reloginFromKeytab();
    final long secondLogin = user.getLastLogin();
    final LoginContext login2 = user.getLogin();
    Assert.assertTrue("User should have been able to relogin from keytab",
        secondLogin > firstLogin);
    Assert.assertNotNull(login2);
    Assert.assertNotSame(login1, login2);
  }

  @Test
  public void testGetUGIFromKnownSubject() throws Exception {
    KerberosPrincipal principal = new KerberosPrincipal("user");
    File keytab = new File(workDir, "user.keytab");
    kdc.createPrincipal(keytab, principal.getName());

    UserGroupInformation ugi1 =
      UserGroupInformation.loginUserFromKeytabAndReturnUGI(
        principal.getName(), keytab.getPath());
    Subject subject = ugi1.getSubject();
    User user = getUser(subject);
    Assert.assertNotNull(user);
    LoginContext login = user.getLogin();
    Assert.assertNotNull(login);

    // User instance and/or login context should not change.
    UserGroupInformation ugi2 = UserGroupInformation.getUGIFromSubject(subject);
    Assert.assertSame(user, getUser(ugi2.getSubject()));
    Assert.assertSame(login, user.getLogin());
  }

  @Test
  public void testGetUGIFromExternalSubject() throws Exception {
    KerberosPrincipal principal = new KerberosPrincipal("user");
    File keytab = new File(workDir, "user.keytab");
    kdc.createPrincipal(keytab, principal.getName());

    UserGroupInformation ugi =
      UserGroupInformation.loginUserFromKeytabAndReturnUGI(
        principal.getName(), keytab.getPath());
    Subject subject = ugi.getSubject();
    removeUser(subject);

    // first call to get the ugi should add the User instance w/o a login
    // context.
    UserGroupInformation ugi1 = UserGroupInformation.getUGIFromSubject(subject);
    Assert.assertSame(subject, ugi1.getSubject());
    User user = getUser(subject);
    Assert.assertNotNull(user);
    Assert.assertEquals(principal.getName(), user.getName());
    Assert.assertNull(user.getLogin());

    // subsequent call should not change the existing User instance.
    UserGroupInformation ugi2 = UserGroupInformation.getUGIFromSubject(subject);
    Assert.assertSame(subject, ugi2.getSubject());
    Assert.assertSame(user, getUser(ugi2.getSubject()));
    Assert.assertNull(user.getLogin());
  }

  @Test
  public void testGetUGIFromExternalSubjectWithLogin() throws Exception {
    KerberosPrincipal principal = new KerberosPrincipal("user");
    File keytab = new File(workDir, "user.keytab");
    kdc.createPrincipal(keytab, principal.getName());

    // alter the User's login context to appear to be a foreign and
    // unmanagable context.
    UserGroupInformation ugi =
      UserGroupInformation.loginUserFromKeytabAndReturnUGI(
        principal.getName(), keytab.getPath());
    Subject subject = ugi.getSubject();
    User user = getUser(subject);
    final LoginContext dummyLogin = Mockito.mock(LoginContext.class);
    user.setLogin(dummyLogin);

    // nothing should change.
    UserGroupInformation ugi2 = UserGroupInformation.getUGIFromSubject(subject);
    Assert.assertSame(subject, ugi2.getSubject());
    Assert.assertSame(user, getUser(ugi2.getSubject()));
    Assert.assertSame(dummyLogin, user.getLogin());
  }

  @Test
  public void testUGIRefreshFromKeytab() throws Exception {
    final Configuration conf = new Configuration();
    conf.setBoolean(HADOOP_KERBEROS_KEYTAB_LOGIN_AUTORENEWAL_ENABLED, true);
    SecurityUtil.setAuthenticationMethod(
            UserGroupInformation.AuthenticationMethod.KERBEROS, conf);
    UserGroupInformation.setConfiguration(conf);

    String principal = "bar";
    File keytab = new File(workDir, "bar.keytab");
    kdc.createPrincipal(keytab, principal);

    UserGroupInformation.loginUserFromKeytab(principal, keytab.getPath());

    UserGroupInformation ugi = UserGroupInformation.getLoginUser();

    Assert.assertEquals(UserGroupInformation.AuthenticationMethod.KERBEROS,
        ugi.getAuthenticationMethod());
    Assert.assertTrue(ugi.isFromKeytab());
    Assert.assertTrue(
            UserGroupInformation.isKerberosKeyTabLoginRenewalEnabled());
    Assert.assertTrue(
            UserGroupInformation.getKerberosLoginRenewalExecutor()
                    .isPresent());
  }

  @Test
  public void testUGIRefreshFromKeytabDisabled() throws Exception {
    GenericTestUtils.setLogLevel(UserGroupInformation.LOG, Level.DEBUG);
    final Configuration conf = new Configuration();
    conf.setLong(HADOOP_KERBEROS_MIN_SECONDS_BEFORE_RELOGIN, 1);
    conf.setBoolean(HADOOP_KERBEROS_KEYTAB_LOGIN_AUTORENEWAL_ENABLED, false);
    SecurityUtil.setAuthenticationMethod(
            UserGroupInformation.AuthenticationMethod.KERBEROS, conf);
    UserGroupInformation.setConfiguration(conf);

    String principal = "bar";
    File keytab = new File(workDir, "bar.keytab");
    kdc.createPrincipal(keytab, principal);

    UserGroupInformation.loginUserFromKeytab(principal, keytab.getPath());

    UserGroupInformation ugi = UserGroupInformation.getLoginUser();
    Assert.assertEquals(UserGroupInformation.AuthenticationMethod.KERBEROS,
            ugi.getAuthenticationMethod());
    Assert.assertTrue(ugi.isFromKeytab());
    Assert.assertFalse(
            UserGroupInformation.isKerberosKeyTabLoginRenewalEnabled());
    Assert.assertFalse(
            UserGroupInformation.getKerberosLoginRenewalExecutor()
                    .isPresent());
  }

  private static KerberosTicket getTicket(UserGroupInformation ugi) {
    Set<KerberosTicket> tickets =
        ugi.getSubject().getPrivateCredentials(KerberosTicket.class);
    return tickets.isEmpty() ? null : tickets.iterator().next();
  }

  // verify ugi has expected principal, a keytab, and has a ticket for
  // the expected principal.
  private static KerberosTicket checkTicketAndKeytab(UserGroupInformation ugi,
      KerberosPrincipal principal, boolean expectIsKeytab) {
    Assert.assertEquals("wrong principal",
      principal.getName(), ugi.getUserName());
    Assert.assertEquals("is not keytab",
      expectIsKeytab, ugi.isFromKeytab());
    KerberosTicket ticket = getTicket(ugi);
    Assert.assertNotNull("no ticket", ticket);
    Assert.assertEquals("wrong principal", principal, ticket.getClient());
    return ticket;
  }

  @Test
  public void testReloginForUGIFromSubject() throws Exception {
    KerberosPrincipal principal1 = new KerberosPrincipal("user1");
    File keytab1 = new File(workDir, "user1.keytab");
    kdc.createPrincipal(keytab1, principal1.getName());

    KerberosPrincipal principal2 = new KerberosPrincipal("user2");
    File keytab2 = new File(workDir, "user2.keytab");
    kdc.createPrincipal(keytab2, principal2.getName());

    // Login a user and remove the User instance so it looks like an
    // "external" subject.
    final Subject extSubject =
      UserGroupInformation.loginUserFromKeytabAndReturnUGI(
        principal2.getName(), keytab2.getPath()).getSubject();
    removeUser(extSubject);

    // Login another user.
    UserGroupInformation.loginUserFromKeytab(
        principal1.getName(), keytab1.getPath());
    final UserGroupInformation loginUser = UserGroupInformation.getLoginUser();

    loginUser.doAs(new PrivilegedExceptionAction<Void>() {
      @Override
      public Void run() throws IOException {
        KerberosTicket loginTicket =
            checkTicketAndKeytab(loginUser, principal1, true);

        // get the ugi for the previously logged in subject.
        UserGroupInformation extSubjectUser =
            UserGroupInformation.getUGIFromSubject(extSubject);
        KerberosTicket ticket =
          checkTicketAndKeytab(extSubjectUser, principal2, false);

        // verify login user got a new ticket.
        loginUser.reloginFromKeytab();
        KerberosTicket newLoginTicket =
            checkTicketAndKeytab(loginUser, principal1, true);
        Assert.assertNotEquals(loginTicket.getAuthTime(),
            newLoginTicket.getAuthTime());

        // verify an "external" subject ticket does not change.
        extSubjectUser.reloginFromKeytab();
        Assert.assertSame(ticket,
            checkTicketAndKeytab(extSubjectUser, principal2, false));

        // verify subject ugi relogin did not affect the login user.
        Assert.assertSame(newLoginTicket,
            checkTicketAndKeytab(loginUser, principal1, true));

        return null;
      }
    });
  }

  @Test
  public void testReloginForLoginFromSubject() throws Exception {
    KerberosPrincipal principal1 = new KerberosPrincipal("user1");
    File keytab1 = new File(workDir, "user1.keytab");
    kdc.createPrincipal(keytab1, principal1.getName());

    KerberosPrincipal principal2 = new KerberosPrincipal("user2");
    File keytab2 = new File(workDir, "user2.keytab");
    kdc.createPrincipal(keytab2, principal2.getName());

    // login principal1 with a keytab.
    UserGroupInformation.loginUserFromKeytab(
        principal1.getName(), keytab1.getPath());
    final UserGroupInformation originalLoginUser =
        UserGroupInformation.getLoginUser();
    Assert.assertNotNull(getUser(originalLoginUser.getSubject()).getLogin());

    originalLoginUser.doAs(new PrivilegedExceptionAction<Void>() {
      @Override
      public Void run() throws IOException {
        KerberosTicket originalLoginUserTicket =
            checkTicketAndKeytab(originalLoginUser, principal1, true);

        // login principal2 from a subject with keytab.  it's external so
        // no login context should be attached to the user.
        final Subject subject =
          UserGroupInformation.loginUserFromKeytabAndReturnUGI(
            principal2.getName(), keytab2.getPath()).getSubject();
        removeUser(subject);

        // verify the new login user is external.
        UserGroupInformation.loginUserFromSubject(subject);
        Assert.assertNull(getUser(subject).getLogin());
        UserGroupInformation extLoginUser =
          UserGroupInformation.getLoginUser();
        KerberosTicket extLoginUserTicket =
            checkTicketAndKeytab(extLoginUser, principal2, false);

        // verify subject-based login user does not get a new ticket, and
        // original login user not affected.
        extLoginUser.reloginFromKeytab();
        Assert.assertSame(extLoginUserTicket,
          checkTicketAndKeytab(extLoginUser, principal2, false));
        Assert.assertSame(originalLoginUserTicket,
          checkTicketAndKeytab(originalLoginUser, principal1, true));

        // verify original login user gets a new ticket, new login user
        // not affected.
        originalLoginUser.reloginFromKeytab();
        Assert.assertNotSame(originalLoginUserTicket,
            checkTicketAndKeytab(originalLoginUser, principal1, true));
        Assert.assertSame(extLoginUserTicket,
            checkTicketAndKeytab(extLoginUser, principal2, false));
        return null;
      }
    });
  }

  @Test
  public void testReloginAfterFailedRelogin() throws Exception {
    KerberosPrincipal principal = new KerberosPrincipal("user1");
    File keytab = new File(workDir, "user1.keytab");
    File keytabBackup = new File(keytab + ".backup");
    kdc.createPrincipal(keytab, principal.getName());

    UserGroupInformation.loginUserFromKeytab(
        principal.getName(), keytab.getPath());
    final UserGroupInformation loginUser = UserGroupInformation.getLoginUser();
    checkTicketAndKeytab(loginUser, principal, true);

    // move the keytab to induce a relogin failure.
    Assert.assertTrue(keytab.renameTo(keytabBackup));
    try {
      loginUser.reloginFromKeytab();
      Assert.fail("relogin should fail");
    } catch (KerberosAuthException kae) {
      // expected.
    }

    // even though no KeyTab object, ugi should know it's keytab based.
    Assert.assertTrue(loginUser.isFromKeytab());
    Assert.assertNull(getTicket(loginUser));

    // move keytab back to enable relogin to succeed.
    Assert.assertTrue(keytabBackup.renameTo(keytab));
    loginUser.reloginFromKeytab();
    checkTicketAndKeytab(loginUser, principal, true);
  }

  // verify getting concurrent relogins blocks to avoid indeterminate
  // credentials corruption, but getting a ugi for the subject does not block.
  @Test(timeout=180000)
  public void testConcurrentRelogin() throws Exception {
    final CyclicBarrier barrier = new CyclicBarrier(2);
    final CountDownLatch latch = new CountDownLatch(1);
    assertTrue(UserGroupInformation.isSecurityEnabled());

    KerberosPrincipal principal = new KerberosPrincipal("testUser");
    File keytab = new File(workDir, "user1.keytab");
    kdc.createPrincipal(keytab, principal.getName());

    // create a keytab ugi.
    final UserGroupInformation loginUgi =
        UserGroupInformation.loginUserFromKeytabAndReturnUGI(
          principal.getName(), keytab.getPath());
    assertEquals(AuthenticationMethod.KERBEROS,
        loginUgi.getAuthenticationMethod());
    assertTrue(loginUgi.isFromKeytab());

    // create a new ugi instance based on subject from the logged in user.
    final UserGroupInformation clonedUgi =
        UserGroupInformation.getUGIFromSubject(loginUgi.getSubject());
    assertEquals(AuthenticationMethod.KERBEROS,
        clonedUgi.getAuthenticationMethod());
    assertTrue(clonedUgi.isFromKeytab());

    // cause first relogin to block on a barrier in logout to verify relogins
    // are atomic.
    User user = getUser(loginUgi.getSubject());
    final LoginContext spyLogin = Mockito.spy(user.getLogin());
    user.setLogin(spyLogin);
    Mockito.doAnswer(new Answer<Void>(){
      @Override
      public Void answer(InvocationOnMock invocation)
          throws Throwable {
        invocation.callRealMethod();
        latch.countDown();
        barrier.await();
        return null;
      }
    }).when(spyLogin).logout();

    Future<Void> relogin = executor.submit(
        new Callable<Void>(){
          @Override
          public Void call() throws Exception {
            Thread.currentThread().setName("relogin");
            loginUgi.reloginFromKeytab();
            return null;
          }
        });
    // wait for the thread to block on the barrier in the logout of the
    // relogin.
    assertTrue("first relogin didn't block",
      latch.await(2, TimeUnit.SECONDS));

    // although the logout removed the keytab instance, verify the ugi
    // knows from its login params that it is supposed to be from a keytab.
    assertTrue(clonedUgi.isFromKeytab());

    // another concurrent re-login should block.
    Mockito.doNothing().when(spyLogin).logout();
    Mockito.doNothing().when(spyLogin).login();
    Future<UserGroupInformation> clonedRelogin = executor.submit(
        new Callable<UserGroupInformation>(){
          @Override
          public UserGroupInformation call() throws Exception {
            Thread.currentThread().setName("clonedRelogin");
            clonedUgi.reloginFromKeytab();
            return clonedUgi;
          }
        });

    try {
      clonedRelogin.get(2, TimeUnit.SECONDS);
      fail("second relogin didn't block!");
    } catch (TimeoutException te) {
      // expected
    }

    // concurrent UGI instantiation should not block and again should
    // know it's supposed to be from a keytab.
    loginUgi.doAs(new PrivilegedExceptionAction<Void>(){
      @Override
      public Void run() throws Exception {
        UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
        assertEquals(principal.getName(), ugi.getUserName());
        assertTrue(ugi.isFromKeytab());
        return null;
      }
    });
    clonedUgi.doAs(new PrivilegedExceptionAction<Void>(){
      @Override
      public Void run() throws Exception {
        UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
        assertEquals(principal.getName(), ugi.getUserName());
        assertTrue(ugi.isFromKeytab());
        return null;
      }
    });

    // second relogin should still be blocked until the original relogin
    // is blocked.
    assertFalse(clonedRelogin.isDone());
    barrier.await();
    relogin.get();
    clonedRelogin.get();
  }

  private User getUser(Subject subject) {
    Iterator<User> iter = subject.getPrincipals(User.class).iterator();
    return iter.hasNext() ? iter.next() : null;
  }

  private void removeUser(Subject subject) {
    // remove User instance so it appears to not be logged in.
    for (Iterator<Principal> iter = subject.getPrincipals().iterator();
         iter.hasNext(); ) {
      if (iter.next() instanceof User) {
        iter.remove();
      }
    }
  }
}
