/*
 * 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.hdds.security.x509.keys;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.output.FileWriterWithEncoding;
import org.apache.hadoop.hdds.security.x509.SecurityConfig;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
import org.bouncycastle.util.io.pem.PemWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.nio.file.attribute.PosixFilePermission.OWNER_EXECUTE;
import static java.nio.file.attribute.PosixFilePermission.OWNER_READ;
import static java.nio.file.attribute.PosixFilePermission.OWNER_WRITE;

/**
 * We store all Key material in good old PEM files. This helps in avoiding
 * dealing will persistent Java KeyStore issues. Also when debugging, general
 * tools like OpenSSL can be used to read and decode these files.
 */
public class KeyCodec {
  public final static String PRIVATE_KEY = "PRIVATE KEY";
  public final static String PUBLIC_KEY = "PUBLIC KEY";
  public final static Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
  private final static  Logger LOG =
      LoggerFactory.getLogger(KeyCodec.class);
  private final Path location;
  private final SecurityConfig securityConfig;
  private Set<PosixFilePermission> permissionSet =
      Stream.of(OWNER_READ, OWNER_WRITE, OWNER_EXECUTE)
          .collect(Collectors.toSet());
  private Supplier<Boolean> isPosixFileSystem;

  /**
   * Creates a KeyCodec with component name.
   *
   * @param config - Security Config.
   * @param component - Component String.
   */
  public KeyCodec(SecurityConfig config, String component) {
    this.securityConfig = config;
    isPosixFileSystem = KeyCodec::isPosix;
    this.location = securityConfig.getKeyLocation(component);
  }

  /**
   * Checks if File System supports posix style security permissions.
   *
   * @return True if it supports posix.
   */
  private static Boolean isPosix() {
    return FileSystems.getDefault().supportedFileAttributeViews()
        .contains("posix");
  }

  /**
   * Returns the Permission set.
   *
   * @return Set
   */
  @VisibleForTesting
  public Set<PosixFilePermission> getPermissionSet() {
    return permissionSet;
  }

  /**
   * Returns the Security config used for this object.
   *
   * @return SecurityConfig
   */
  public SecurityConfig getSecurityConfig() {
    return securityConfig;
  }

  /**
   * This function is used only for testing.
   *
   * @param isPosixFileSystem - Sets a boolean function for mimicking files
   * systems that are not posix.
   */
  @VisibleForTesting
  public void setIsPosixFileSystem(Supplier<Boolean> isPosixFileSystem) {
    this.isPosixFileSystem = isPosixFileSystem;
  }

  /**
   * Writes a given key using the default config options.
   *
   * @param keyPair - Key Pair to write to file.
   * @throws IOException - On I/O failure.
   */
  public void writeKey(KeyPair keyPair) throws IOException {
    writeKey(location, keyPair, securityConfig.getPrivateKeyFileName(),
        securityConfig.getPublicKeyFileName(), false);
  }

  /**
   * Writes a given private key using the default config options.
   *
   * @param key - Key to write to file.
   * @throws IOException - On I/O failure.
   */
  public void writePrivateKey(PrivateKey key) throws IOException {
    File privateKeyFile =
        Paths.get(location.toString(),
            securityConfig.getPrivateKeyFileName()).toFile();

    if (Files.exists(privateKeyFile.toPath())) {
      throw new IOException("Private key already exist.");
    }

    try (PemWriter privateKeyWriter = new PemWriter(new
        FileWriterWithEncoding(privateKeyFile, DEFAULT_CHARSET))) {
      privateKeyWriter.writeObject(
          new PemObject(PRIVATE_KEY, key.getEncoded()));
    }
    Files.setPosixFilePermissions(privateKeyFile.toPath(), permissionSet);
  }

  /**
   * Writes a given public key using the default config options.
   *
   * @param key - Key to write to file.
   * @throws IOException - On I/O failure.
   */
  public void writePublicKey(PublicKey key) throws IOException {
    File publicKeyFile = Paths.get(location.toString(),
        securityConfig.getPublicKeyFileName()).toFile();

    if (Files.exists(publicKeyFile.toPath())) {
      throw new IOException("Private key already exist.");
    }

    try (PemWriter keyWriter = new PemWriter(new
        FileWriterWithEncoding(publicKeyFile, DEFAULT_CHARSET))) {
      keyWriter.writeObject(
          new PemObject(PUBLIC_KEY, key.getEncoded()));
    }
    Files.setPosixFilePermissions(publicKeyFile.toPath(), permissionSet);
  }

  /**
   * Writes a given key using default config options.
   *
   * @param keyPair - Key pair to write
   * @param overwrite - Overwrites the keys if they already exist.
   * @throws IOException - On I/O failure.
   */
  public void writeKey(KeyPair keyPair, boolean overwrite) throws IOException {
    writeKey(location, keyPair, securityConfig.getPrivateKeyFileName(),
        securityConfig.getPublicKeyFileName(), overwrite);
  }

  /**
   * Writes a given key using default config options.
   *
   * @param basePath - The location to write to, override the config values.
   * @param keyPair - Key pair to write
   * @param overwrite - Overwrites the keys if they already exist.
   * @throws IOException - On I/O failure.
   */
  public void writeKey(Path basePath, KeyPair keyPair, boolean overwrite)
      throws IOException {
    writeKey(basePath, keyPair, securityConfig.getPrivateKeyFileName(),
        securityConfig.getPublicKeyFileName(), overwrite);
  }

  /**
   * Reads a Private Key from the PEM Encoded Store.
   *
   * @param basePath - Base Path, Directory where the Key is stored.
   * @param keyFileName - File Name of the private key
   * @return PrivateKey Object.
   * @throws IOException - on Error.
   */
  private PKCS8EncodedKeySpec readKey(Path basePath, String keyFileName)
      throws IOException {
    File fileName = Paths.get(basePath.toString(), keyFileName).toFile();
    String keyData = FileUtils.readFileToString(fileName, DEFAULT_CHARSET);
    final byte[] pemContent;
    try (PemReader pemReader = new PemReader(new StringReader(keyData))) {
      PemObject keyObject = pemReader.readPemObject();
      pemContent = keyObject.getContent();
    }
    return new PKCS8EncodedKeySpec(pemContent);
  }

  /**
   * Returns a Private Key from a PEM encoded file.
   *
   * @param basePath - base path
   * @param privateKeyFileName - private key file name.
   * @return PrivateKey
   * @throws InvalidKeySpecException  - on Error.
   * @throws NoSuchAlgorithmException - on Error.
   * @throws IOException              - on Error.
   */
  public PrivateKey readPrivateKey(Path basePath, String privateKeyFileName)
      throws InvalidKeySpecException, NoSuchAlgorithmException, IOException {
    PKCS8EncodedKeySpec encodedKeySpec = readKey(basePath, privateKeyFileName);
    final KeyFactory keyFactory =
        KeyFactory.getInstance(securityConfig.getKeyAlgo());
    return
        keyFactory.generatePrivate(encodedKeySpec);
  }

  /**
   * Read the Public Key using defaults.
   * @return PublicKey.
   * @throws InvalidKeySpecException - On Error.
   * @throws NoSuchAlgorithmException - On Error.
   * @throws IOException - On Error.
   */
  public PublicKey readPublicKey() throws InvalidKeySpecException,
      NoSuchAlgorithmException, IOException {
    return readPublicKey(this.location.toAbsolutePath(),
        securityConfig.getPublicKeyFileName());
  }

  /**
   * Returns a public key from a PEM encoded file.
   *
   * @param basePath - base path.
   * @param publicKeyFileName - public key file name.
   * @return PublicKey
   * @throws NoSuchAlgorithmException - on Error.
   * @throws InvalidKeySpecException  - on Error.
   * @throws IOException              - on Error.
   */
  public PublicKey readPublicKey(Path basePath, String publicKeyFileName)
      throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
    PKCS8EncodedKeySpec encodedKeySpec = readKey(basePath, publicKeyFileName);
    final KeyFactory keyFactory =
        KeyFactory.getInstance(securityConfig.getKeyAlgo());
    return
        keyFactory.generatePublic(
            new X509EncodedKeySpec(encodedKeySpec.getEncoded()));

  }


  /**
   * Returns the private key  using defaults.
   * @return PrivateKey.
   * @throws InvalidKeySpecException - On Error.
   * @throws NoSuchAlgorithmException - On Error.
   * @throws IOException - On Error.
   */
  public PrivateKey readPrivateKey() throws InvalidKeySpecException,
      NoSuchAlgorithmException, IOException {
    return readPrivateKey(this.location.toAbsolutePath(),
        securityConfig.getPrivateKeyFileName());
  }


  /**
   * Helper function that actually writes data to the files.
   *
   * @param basePath - base path to write key
   * @param keyPair - Key pair to write to file.
   * @param privateKeyFileName - private key file name.
   * @param publicKeyFileName - public key file name.
   * @param force - forces overwriting the keys.
   * @throws IOException - On I/O failure.
   */
  private synchronized void writeKey(Path basePath, KeyPair keyPair,
      String privateKeyFileName, String publicKeyFileName, boolean force)
      throws IOException {
    checkPreconditions(basePath);

    File privateKeyFile =
        Paths.get(location.toString(), privateKeyFileName).toFile();
    File publicKeyFile =
        Paths.get(location.toString(), publicKeyFileName).toFile();
    checkKeyFile(privateKeyFile, force, publicKeyFile);

    try (PemWriter privateKeyWriter = new PemWriter(new
        FileWriterWithEncoding(privateKeyFile, DEFAULT_CHARSET))) {
      privateKeyWriter.writeObject(
          new PemObject(PRIVATE_KEY, keyPair.getPrivate().getEncoded()));
    }

    try (PemWriter publicKeyWriter = new PemWriter(new
        FileWriterWithEncoding(publicKeyFile, DEFAULT_CHARSET))) {
      publicKeyWriter.writeObject(
          new PemObject(PUBLIC_KEY, keyPair.getPublic().getEncoded()));
    }
    Files.setPosixFilePermissions(privateKeyFile.toPath(), permissionSet);
    Files.setPosixFilePermissions(publicKeyFile.toPath(), permissionSet);
  }

  /**
   * Checks if private and public key file already exists. Throws IOException if
   * file exists and force flag is set to false, else will delete the existing
   * file.
   *
   * @param privateKeyFile - Private key file.
   * @param force - forces overwriting the keys.
   * @param publicKeyFile - public key file.
   * @throws IOException - On I/O failure.
   */
  private void checkKeyFile(File privateKeyFile, boolean force,
                            File publicKeyFile) throws IOException {
    if (privateKeyFile.exists() && force) {
      if (!privateKeyFile.delete()) {
        throw new IOException("Unable to delete private key file.");
      }
    }

    if (publicKeyFile.exists() && force) {
      if (!publicKeyFile.delete()) {
        throw new IOException("Unable to delete public key file.");
      }
    }

    if (privateKeyFile.exists()) {
      throw new IOException("Private Key file already exists.");
    }

    if (publicKeyFile.exists()) {
      throw new IOException("Public Key file already exists.");
    }
  }

  /**
   * Checks if base path exists and sets file permissions.
   *
   * @param basePath - base path to write key
   * @throws IOException - On I/O failure.
   */
  private void checkPreconditions(Path basePath) throws IOException {
    Preconditions.checkNotNull(basePath, "Base path cannot be null");
    if (!isPosixFileSystem.get()) {
      LOG.error("Keys cannot be stored securely without POSIX file system "
          + "support for now.");
      throw new IOException("Unsupported File System for pem file.");
    }

    if (Files.exists(basePath)) {
      // Not the end of the world if we reset the permissions on an existing
      // directory.
      Files.setPosixFilePermissions(basePath, permissionSet);
    } else {
      boolean success = basePath.toFile().mkdirs();
      if (!success) {
        LOG.error("Unable to create the directory for the "
            + "location. Location: {}", basePath);
        throw new IOException("Unable to create the directory for the "
            + "location. Location:" + basePath);
      }
      Files.setPosixFilePermissions(basePath, permissionSet);
    }
  }

}
