/**
 * 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);
  }

  /**
   * Force re-login from keytab using the MiniKDC and verify the UGI can
   * successfully relogin from keytab as well.
   */
  @Test
  public void testUGIForceReLoginFromKeytab() throws Exception {
    // Set this to false as we are testing force re-login anyways
    UserGroupInformation.setShouldRenewImmediatelyForTests(false);
    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);

    // Force relogin from keytab
    ugi.reloginFromKeytab(true);
    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();
      }
    }
  }
}
