/**
 * 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.crypto.key.kms.server;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.apache.hadoop.crypto.key.KeyProvider;
import org.apache.hadoop.crypto.key.KeyProviderCryptoExtension;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.authorize.AuthorizationException;

import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;

/**
 * A {@link KeyProvider} proxy that checks whether the current user derived via
 * {@link UserGroupInformation}, is authorized to perform the following
 * type of operations on a Key :
 * <ol>
 * <li>MANAGEMENT operations : createKey, rollNewVersion, deleteKey</li>
 * <li>GENERATE_EEK operations : generateEncryptedKey, warmUpEncryptedKeys</li>
 * <li>DECRYPT_EEK operation : decryptEncryptedKey</li>
 * <li>READ operations : getKeyVersion, getKeyVersions, getMetadata,
 * getKeysMetadata, getCurrentKey</li>
 * </ol>
 * The read operations (getCurrentKeyVersion / getMetadata) etc are not checked.
 */
public class KeyAuthorizationKeyProvider extends KeyProviderCryptoExtension {

  public static final String KEY_ACL = "key.acl.";
  private static final String KEY_ACL_NAME = KEY_ACL + "name";

  public enum KeyOpType {
    ALL, READ, MANAGEMENT, GENERATE_EEK, DECRYPT_EEK;
  }

  /**
   * Interface that needs to be implemented by a client of the
   * <code>KeyAuthorizationKeyProvider</code>.
   */
  public static interface KeyACLs {
    
    /**
     * This is called by the KeyProvider to check if the given user is
     * authorized to perform the specified operation on the given acl name.
     * @param aclName name of the key ACL
     * @param ugi User's UserGroupInformation
     * @param opType Operation Type 
     * @return true if user has access to the aclName and opType else false
     */
    public boolean hasAccessToKey(String aclName, UserGroupInformation ugi,
        KeyOpType opType);

    /**
     * 
     * @param aclName ACL name
     * @param opType Operation Type
     * @return true if AclName exists else false 
     */
    public boolean isACLPresent(String aclName, KeyOpType opType);
  }

  private final KeyProviderCryptoExtension provider;
  private final KeyACLs acls;
  private Lock readLock;
  private Lock writeLock;

  /**
   * The constructor takes a {@link KeyProviderCryptoExtension} and an
   * implementation of <code>KeyACLs</code>. All calls are delegated to the
   * provider keyProvider after authorization check (if required)
   * @param keyProvider  the key provider
   * @param acls the Key ACLs
   */
  public KeyAuthorizationKeyProvider(KeyProviderCryptoExtension keyProvider,
      KeyACLs acls) {
    super(keyProvider, null);
    this.provider = keyProvider;
    this.acls = acls;
    ReadWriteLock lock = new ReentrantReadWriteLock(true);
    readLock = lock.readLock();
    writeLock = lock.writeLock();
  }

  // This method first checks if "key.acl.name" attribute is present as an
  // attribute in the provider Options. If yes, use the aclName for any
  // subsequent access checks, else use the keyName as the aclName and set it
  // as the value of the "key.acl.name" in the key's metadata.
  private void authorizeCreateKey(String keyName, Options options,
      UserGroupInformation ugi) throws IOException{
    Preconditions.checkNotNull(ugi, "UserGroupInformation cannot be null");
    Map<String, String> attributes = options.getAttributes();
    String aclName = attributes.get(KEY_ACL_NAME);
    boolean success = false;
    if (Strings.isNullOrEmpty(aclName)) {
      if (acls.isACLPresent(keyName, KeyOpType.MANAGEMENT)) {
        options.setAttributes(ImmutableMap.<String, String> builder()
            .putAll(attributes).put(KEY_ACL_NAME, keyName).build());
        success =
            acls.hasAccessToKey(keyName, ugi, KeyOpType.MANAGEMENT)
                || acls.hasAccessToKey(keyName, ugi, KeyOpType.ALL);
      } else {
        success = false;
      }
    } else {
      success = acls.isACLPresent(aclName, KeyOpType.MANAGEMENT) &&
          (acls.hasAccessToKey(aclName, ugi, KeyOpType.MANAGEMENT)
          || acls.hasAccessToKey(aclName, ugi, KeyOpType.ALL));
    }
    if (!success)
      throw new AuthorizationException(String.format("User [%s] is not"
          + " authorized to create key !!", ugi.getShortUserName()));
  }

  private void checkAccess(String aclName, UserGroupInformation ugi,
      KeyOpType opType) throws AuthorizationException {
    Preconditions.checkNotNull(aclName, "Key ACL name cannot be null");
    Preconditions.checkNotNull(ugi, "UserGroupInformation cannot be null");
    if (acls.isACLPresent(aclName, opType) &&
        (acls.hasAccessToKey(aclName, ugi, opType)
            || acls.hasAccessToKey(aclName, ugi, KeyOpType.ALL))) {
      return;
    } else {
      throw new AuthorizationException(String.format("User [%s] is not"
          + " authorized to perform [%s] on key with ACL name [%s]!!",
          ugi.getShortUserName(), opType, aclName));
    }
  }

  @Override
  public KeyVersion createKey(String name, Options options)
      throws NoSuchAlgorithmException, IOException {
    writeLock.lock();
    try {
      authorizeCreateKey(name, options, getUser());
      return provider.createKey(name, options);
    } finally {
      writeLock.unlock();
    }
  }

  @Override
  public KeyVersion createKey(String name, byte[] material, Options options)
      throws IOException {
    writeLock.lock();
    try {
      authorizeCreateKey(name, options, getUser());
      return provider.createKey(name, material, options);
    } finally {
      writeLock.unlock();
    }
  }

  @Override
  public KeyVersion rollNewVersion(String name)
      throws NoSuchAlgorithmException, IOException {
    writeLock.lock();
    try {
      doAccessCheck(name, KeyOpType.MANAGEMENT);
      return provider.rollNewVersion(name);
    } finally {
      writeLock.unlock();
    }
  }

  @Override
  public void deleteKey(String name) throws IOException {
    writeLock.lock();
    try {
      doAccessCheck(name, KeyOpType.MANAGEMENT);
      provider.deleteKey(name);
    } finally {
      writeLock.unlock();
    }
  }

  @Override
  public KeyVersion rollNewVersion(String name, byte[] material)
      throws IOException {
    writeLock.lock();
    try {
      doAccessCheck(name, KeyOpType.MANAGEMENT);
      return provider.rollNewVersion(name, material);
    } finally {
      writeLock.unlock();
    }
  }

  @Override
  public void warmUpEncryptedKeys(String... names) throws IOException {
    readLock.lock();
    try {
      for (String name : names) {
        doAccessCheck(name, KeyOpType.GENERATE_EEK);
      }
      provider.warmUpEncryptedKeys(names);
    } finally {
      readLock.unlock();
    }
  }

  @Override
  public EncryptedKeyVersion generateEncryptedKey(String encryptionKeyName)
      throws IOException, GeneralSecurityException {
    readLock.lock();
    try {
      doAccessCheck(encryptionKeyName, KeyOpType.GENERATE_EEK);
      return provider.generateEncryptedKey(encryptionKeyName);
    } finally {
      readLock.unlock();
    }
  }

  private void verifyKeyVersionBelongsToKey(EncryptedKeyVersion ekv)
      throws IOException {
    String kn = ekv.getEncryptionKeyName();
    String kvn = ekv.getEncryptionKeyVersionName();
    KeyVersion kv = provider.getKeyVersion(kvn);
    if (kv == null) {
      throw new IllegalArgumentException(String.format(
          "'%s' not found", kvn));
    }
    if (!kv.getName().equals(kn)) {
      throw new IllegalArgumentException(String.format(
          "KeyVersion '%s' does not belong to the key '%s'", kvn, kn));
    }
  }

  @Override
  public KeyVersion decryptEncryptedKey(EncryptedKeyVersion encryptedKeyVersion)
          throws IOException, GeneralSecurityException {
    readLock.lock();
    try {
      verifyKeyVersionBelongsToKey(encryptedKeyVersion);
      doAccessCheck(
          encryptedKeyVersion.getEncryptionKeyName(), KeyOpType.DECRYPT_EEK);
      return provider.decryptEncryptedKey(encryptedKeyVersion);
    } finally {
      readLock.unlock();
    }
  }

  @Override
  public KeyVersion getKeyVersion(String versionName) throws IOException {
    readLock.lock();
    try {
      KeyVersion keyVersion = provider.getKeyVersion(versionName);
      if (keyVersion != null) {
        doAccessCheck(keyVersion.getName(), KeyOpType.READ);
      }
      return keyVersion;
    } finally {
      readLock.unlock();
    }
  }

  @Override
  public List<String> getKeys() throws IOException {
    return provider.getKeys();
  }

  @Override
  public List<KeyVersion> getKeyVersions(String name) throws IOException {
    readLock.lock();
    try {
      doAccessCheck(name, KeyOpType.READ);
      return provider.getKeyVersions(name);
    } finally {
      readLock.unlock();
    }
  }

  @Override
  public Metadata getMetadata(String name) throws IOException {
    readLock.lock();
    try {
      doAccessCheck(name, KeyOpType.READ);
      return provider.getMetadata(name);
    } finally {
      readLock.unlock();
    }
  }

  @Override
  public Metadata[] getKeysMetadata(String... names) throws IOException {
    readLock.lock();
    try {
      for (String name : names) {
        doAccessCheck(name, KeyOpType.READ);
      }
      return provider.getKeysMetadata(names);
    } finally {
      readLock.unlock();
    }
  }

  @Override
  public KeyVersion getCurrentKey(String name) throws IOException {
    readLock.lock();
    try {
      doAccessCheck(name, KeyOpType.READ);
      return provider.getCurrentKey(name);
    } finally {
      readLock.unlock();
    }
  }

  @Override
  public void flush() throws IOException {
    provider.flush();
  }

  @Override
  public boolean isTransient() {
    return provider.isTransient();
  }

  private void doAccessCheck(String keyName, KeyOpType opType) throws
      IOException {
    Metadata metadata = provider.getMetadata(keyName);
    if (metadata != null) {
      String aclName = metadata.getAttributes().get(KEY_ACL_NAME);
      checkAccess((aclName == null) ? keyName : aclName, getUser(), opType);
    }
  }

  private UserGroupInformation getUser() throws IOException {
    return UserGroupInformation.getCurrentUser();
  }

  @Override
  protected KeyProvider getKeyProvider() {
    return this;
  }

  @Override
  public String toString() {
    return provider.toString();
  }

}
