/*
 * 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.fs.s3a.auth;

import java.io.IOException;
import java.nio.file.AccessDeniedException;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import com.fasterxml.jackson.core.JsonProcessingException;
import org.junit.Assume;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

import static org.apache.hadoop.fs.contract.ContractTestUtils.touch;
import static org.apache.hadoop.fs.s3a.Constants.*;
import static org.apache.hadoop.fs.s3a.S3ATestUtils.disableFilesystemCaching;
import static org.apache.hadoop.fs.s3a.S3ATestUtils.removeBaseAndBucketOverrides;
import static org.apache.hadoop.fs.s3a.auth.RoleModel.*;
import static org.apache.hadoop.fs.s3a.auth.RolePolicies.*;
import static org.apache.hadoop.fs.s3a.auth.delegation.DelegationConstants.DELEGATION_TOKEN_BINDING;
import static org.apache.hadoop.test.LambdaTestUtils.intercept;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

/**
 * Helper class for testing roles.
 */
@InterfaceAudience.Private
@InterfaceStability.Unstable
public final class RoleTestUtils {

  private static final Logger LOG =
      LoggerFactory.getLogger(RoleTestUtils.class);

  private static final RoleModel MODEL = new RoleModel();


  /** Example ARN of a role. */
  public static final String ROLE_ARN_EXAMPLE
      = "arn:aws:iam::9878543210123:role/role-s3-restricted";


  /** Deny GET requests to all buckets. */
  public static final Statement DENY_S3_GET_OBJECT =
      statement(false, S3_ALL_BUCKETS, S3_GET_OBJECT);

  public static final Statement ALLOW_S3_GET_BUCKET_LOCATION
      =  statement(true, S3_ALL_BUCKETS, S3_GET_BUCKET_LOCATION);

  /**
   * This is AWS policy removes read access from S3.
   * The client does need {@link RolePolicies#S3_GET_BUCKET_LOCATION} to
   * get the bucket location.
   */
  public static final Policy RESTRICTED_POLICY = policy(
      DENY_S3_GET_OBJECT, ALLOW_S3_GET_BUCKET_LOCATION);

  private RoleTestUtils() {
  }

  /**
   * Bind the configuration's {@code ASSUMED_ROLE_POLICY} option to
   * the given policy.
   * @param conf configuration to patch
   * @param policy policy to apply
   * @return the modified configuration
   * @throws JsonProcessingException JSON marshalling error
   */
  public static Configuration bindRolePolicy(final Configuration conf,
      final Policy policy) throws JsonProcessingException {
    String p = MODEL.toJson(policy);
    LOG.info("Setting role policy to policy of size {}:\n{}", p.length(), p);
    conf.set(ASSUMED_ROLE_POLICY, p);
    return conf;
  }

  /**
   * Wrap a set of statements with a policy and bind the configuration's
   * {@code ASSUMED_ROLE_POLICY} option to it.
   * @param conf configuration to patch
   * @param statements statements to aggregate
   * @return the modified configuration
   * @throws JsonProcessingException JSON marshalling error
   */
  public static Configuration bindRolePolicyStatements(
      final Configuration conf,
      final Statement... statements) throws JsonProcessingException {
    return bindRolePolicy(conf, policy(statements));
  }


  /**
   * Try to delete a file, verify that it is not allowed.
   * @param fs filesystem
   * @param path path
   */
  public static void assertDeleteForbidden(final FileSystem fs, final Path path)
      throws Exception {
    intercept(AccessDeniedException.class, "",
        () -> fs.delete(path, true));
  }

  /**
   * Try to touch a file, verify that it is not allowed.
   * @param fs filesystem
   * @param path path
   */
  public static void assertTouchForbidden(final FileSystem fs, final Path path)
      throws Exception {
    intercept(AccessDeniedException.class, "",
        "Caller could create file at " + path,
        () -> {
          touch(fs, path);
          return fs.getFileStatus(path);
        });
  }

  /**
   * Create a config for an assumed role; it also disables FS caching.
   * @param srcConf source config: this is not modified
   * @param roleARN ARN of role
   * @return the new configuration
   */
  @SuppressWarnings("deprecation")
  public static Configuration newAssumedRoleConfig(
      final Configuration srcConf,
      final String roleARN) {
    Configuration conf = new Configuration(srcConf);
    removeBaseAndBucketOverrides(conf,
        DELEGATION_TOKEN_BINDING,
        ASSUMED_ROLE_ARN,
        AWS_CREDENTIALS_PROVIDER);
    conf.set(AWS_CREDENTIALS_PROVIDER, AssumedRoleCredentialProvider.NAME);
    conf.set(ASSUMED_ROLE_ARN, roleARN);
    conf.set(ASSUMED_ROLE_SESSION_NAME, "test");
    conf.set(ASSUMED_ROLE_SESSION_DURATION, "15m");
    disableFilesystemCaching(conf);
    return conf;
  }

  /**
   * Assert that an operation is forbidden.
   * @param <T> type of closure
   * @param contained contained text, may be null
   * @param eval closure to evaluate
   * @return the access denied exception
   * @throws Exception any other exception
   */
  public static <T> AccessDeniedException forbidden(
      final String contained,
      final Callable<T> eval)
      throws Exception {
    return forbidden("", contained, eval);
  }

  /**
   * Assert that an operation is forbidden.
   * @param <T> type of closure
   * @param message error message
   * @param contained contained text, may be null
   * @param eval closure to evaluate
   * @return the access denied exception
   * @throws Exception any other exception
   */
  public static <T> AccessDeniedException forbidden(
      final String message,
      final String contained,
      final Callable<T> eval)
      throws Exception {
    return intercept(AccessDeniedException.class,
        contained, message, eval);
  }

  /**
   * Get the Assumed role referenced by ASSUMED_ROLE_ARN;
   * skip the test if it is unset.
   * @param conf config
   * @return the string
   */
  public static String probeForAssumedRoleARN(Configuration conf) {
    String arn = conf.getTrimmed(ASSUMED_ROLE_ARN, "");
    Assume.assumeTrue("No ARN defined in " + ASSUMED_ROLE_ARN,
        !arn.isEmpty());
    return arn;
  }

  /**
   * Assert that credentials are equal without printing secrets.
   * Different assertions will have different message details.
   * @param message message to use as base of error.
   * @param expected expected credentials
   * @param actual actual credentials.
   */
  public static void assertCredentialsEqual(final String message,
      final MarshalledCredentials expected,
      final MarshalledCredentials actual) {
    // DO NOT use assertEquals() here, as that could print a secret to
    // the test report.
    assertEquals(message + ": access key",
        expected.getAccessKey(),
        actual.getAccessKey());
    assertTrue(message + ": secret key",
        expected.getSecretKey().equals(actual.getSecretKey()));
    assertEquals(message + ": session token",
        expected.getSessionToken(),
        actual.getSessionToken());

  }

  /**
   * Parallel-touch a set of files in the destination directory.
   * @param fs filesystem
   * @param destDir destination
   * @param range range 1..range inclusive of files to create.
   * @return the list of paths created.
   */
  public static List<Path> touchFiles(final FileSystem fs,
      final Path destDir,
      final int range) throws IOException {
    List<Path> paths = IntStream.rangeClosed(1, range)
        .mapToObj((i) -> new Path(destDir, "file-" + i))
                .collect(Collectors.toList());
    for (Path path : paths) {
      touch(fs, path);
    }
    return paths;
  }
}
