/*
 * 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.slider.server.services.security;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.hdfs.DFSConfigKeys;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.security.SecurityUtil;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.security.token.TokenIdentifier;
import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenIdentifier;
import org.apache.hadoop.util.Time;
import org.apache.slider.common.tools.SliderUtils;
import org.apache.slider.server.appmaster.SliderAppMaster;
import org.apache.slider.server.appmaster.actions.AsyncAction;
import org.apache.slider.server.appmaster.actions.QueueAccess;
import org.apache.slider.server.appmaster.actions.RenewingAction;
import org.apache.slider.server.appmaster.state.AppState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.InetAddress;
import java.security.PrivilegedExceptionAction;
import java.text.DateFormat;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 *
 */
public class FsDelegationTokenManager {
  private final QueueAccess queue;
  private RenewingAction<RenewAction> renewingAction;
  private UserGroupInformation remoteUser;
  private UserGroupInformation currentUser;
  private static final Logger
      log = LoggerFactory.getLogger(FsDelegationTokenManager.class);
  private long renewInterval;
  private RenewAction renewAction;
  private String tokenName;

  public FsDelegationTokenManager(QueueAccess queue) throws IOException {
    this.queue = queue;
    this.currentUser = UserGroupInformation.getCurrentUser();
  }

  private void createRemoteUser(Configuration configuration) throws IOException {
    Configuration loginConfig = new Configuration(configuration);
    loginConfig.set(DFSConfigKeys.HADOOP_SECURITY_AUTHENTICATION,
                    "kerberos");
    // using HDFS principal...
    this.remoteUser = UserGroupInformation
        .loginUserFromKeytabAndReturnUGI(
            SecurityUtil.getServerPrincipal(
                loginConfig.get(DFSConfigKeys.DFS_NAMENODE_KERBEROS_PRINCIPAL_KEY),
                InetAddress.getLocalHost().getCanonicalHostName()),
            loginConfig.get(DFSConfigKeys.DFS_NAMENODE_KEYTAB_FILE_KEY));
    log.info("Created remote user {}.  UGI reports current user is {}",
             this.remoteUser, UserGroupInformation.getCurrentUser());
  }

  public void acquireDelegationToken(Configuration configuration)
      throws IOException, InterruptedException {
    if (remoteUser == null) {
      createRemoteUser(configuration);
    }
    if (SliderUtils.isHadoopClusterSecure(configuration) &&
        renewingAction == null) {
      renewInterval = configuration.getLong(
          DFSConfigKeys.DFS_NAMENODE_DELEGATION_TOKEN_RENEW_INTERVAL_KEY,
          DFSConfigKeys.DFS_NAMENODE_DELEGATION_TOKEN_RENEW_INTERVAL_DEFAULT);
      // constructor of action will retrieve initial token.  One may already be
      // associated with user, but its lifecycle/management is not clear so let's
      // create and manage a token explicitly
      renewAction = new RenewAction("HDFS renew",
                                           configuration);
      // set retrieved token as the user associated delegation token and
      // start a renewing action to renew
      Token<?> token = renewAction.getToken();
      currentUser.addToken(token.getService(), token);
      log.info("HDFS delegation token {} acquired and set as credential for current user", token);
      renewingAction = new RenewingAction<RenewAction>(renewAction,
                                          (int) renewInterval,
                                          (int) renewInterval,
                                          TimeUnit.MILLISECONDS,
                                          getRenewingLimit());
      log.info("queuing HDFS delegation token renewal interval of {} milliseconds",
               renewInterval);
      queue(renewingAction);
    }
  }

  public void cancelDelegationToken(Configuration configuration)
      throws IOException, InterruptedException {
    queue.removeRenewingAction(getRenewingActionName());
    if (renewAction != null) {
      renewAction.getToken().cancel(configuration);
    }
    log.info("Renewing action {} removed and HDFS delegation token renewal "
             + "cancelled", getRenewingActionName());
  }

  protected int getRenewingLimit() {
    return 0;
  }

  protected void queue(RenewingAction<RenewAction> action) {
    queue.renewing(getRenewingActionName(),
                   action);
  }

  protected String getRenewingActionName() {
    if (tokenName == null) {
      tokenName = "HDFS renewing token " + UUID.randomUUID();
    }
    return tokenName;
  }

  class RenewAction extends AsyncAction {
    Configuration configuration;
    Token<?> token;
    private long tokenExpiryTime;
    private final FileSystem fs;

    RenewAction(String name,
                Configuration configuration)
        throws IOException, InterruptedException {
      super(name);
      this.configuration = configuration;
      fs = getFileSystem();
      // get initial token by creating a kerberos authenticated user and
      // invoking token methods as that user
      synchronized (fs) {
        this.token = remoteUser.doAs(new PrivilegedExceptionAction<Token<?>>() {
          @Override
          public Token<?> run() throws Exception {
            log.info("Obtaining HDFS delgation token with user {}",
                     remoteUser.getShortUserName());
            Token token = fs.getDelegationToken(
                remoteUser.getShortUserName());
            tokenExpiryTime = getTokenExpiryTime(token);
            log.info("Initial delegation token obtained with expiry time of {}", getPrintableExirationTime(tokenExpiryTime));
            return token;
          }
        });
      }
      log.info("Initial request returned delegation token {}", token);
    }

    private long getTokenExpiryTime(Token token) throws IOException {
      AbstractDelegationTokenIdentifier id =
          (AbstractDelegationTokenIdentifier)token.decodeIdentifier();
      return id.getMaxDate();
    }

    protected FileSystem getFileSystem()
        throws IOException, InterruptedException {
      // return non-cache FS reference
      return remoteUser.doAs(new PrivilegedExceptionAction<FileSystem>() {
        @Override
        public FileSystem run() throws Exception {
          Configuration config = new Configuration(configuration);
          config.setBoolean("fs.hdfs.impl.disable.cache", true);
          return getRemoteFileSystemForRenewal(config);
        }
      });
    }

    @Override
    public void execute(SliderAppMaster appMaster, QueueAccess queueService,
                        AppState appState)
        throws Exception {
      if (fs != null) {
        synchronized(fs) {
          try {
            long expires = remoteUser.doAs(new PrivilegedExceptionAction<Long>() {
              @Override
              public Long run() throws Exception {
                long expires = token.renew(fs.getConf());
                log.info("HDFS delegation token renewed.  Renewal cycle ends at {}",
                         getPrintableExirationTime(expires));
                return expires;
              }
            });
            long calculatedInterval = tokenExpiryTime - Time.now();
            if ( calculatedInterval < renewInterval ) {
              // time to get a new token since the token will expire before
              // next renewal interval.  Could modify this to be closer to expiry
              // time if deemed necessary....
              log.info("Interval of {} less than renew interval.  Getting new token",
                       calculatedInterval);
              getNewToken();
            } else {
              updateRenewalTime(renewInterval);
            }
          } catch (IOException ie) {
            // token has expired.  get a new one...
            log.info("Exception raised by renew", ie);
            getNewToken();
          }
        }
      }
    }

    private String getPrintableExirationTime(long expires) {
      Date d = new Date(expires);
      return DateFormat.getDateTimeInstance().format(d);
    }

    private void getNewToken()
        throws InterruptedException, IOException {
      try {
        Text service = token.getService();
        Token<?>[] tokens = remoteUser.doAs(new PrivilegedExceptionAction<Token<?>[]>() {
            @Override
            public Token<?>[] run() throws Exception {
              return fs.addDelegationTokens(remoteUser.getShortUserName(), null);
            }
        });
        if (tokens.length == 0) {
          throw new IOException("addDelegationTokens returned no tokens");
        }
        token = findMatchingToken(service, tokens);
        currentUser.addToken(token.getService(), token);

        tokenExpiryTime = getTokenExpiryTime(token);

        log.info("Expired HDFS delegation token replaced and added as credential"
                 + " to current user.  Token expires at {}",
                 getPrintableExirationTime(tokenExpiryTime));
        updateRenewalTime(renewInterval);
      } catch (IOException ie2) {
        throw new IOException("Can't get new delegation token ", ie2);
      }
    }

    private void updateRenewalTime(long interval) {
      long delay = interval - interval/10;
      renewingAction.updateInterval(delay, TimeUnit.MILLISECONDS);
      log.info("Token renewal set for {} ms from now", delay);
    }

    private Token<?> findMatchingToken(Text service, Token<?>[] tokens) {
      Token<?> token = null;
      int i = 0;
      while (token == null && i < tokens.length) {
        if (tokens[i].getService().equals(service)) {
          token = tokens[i];
        }
        i++;
      }

      return token;
    }

    Token<?> getToken() {
      synchronized (fs) {
        return token;
      }
    }
  }

  protected FileSystem getRemoteFileSystemForRenewal(Configuration config)
      throws IOException {
    return FileSystem.get(config);
  }
}
