/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the "Elastic License
 * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
 * Public License v 1"; you may not use this file except in compliance with, at
 * your election, the "Elastic License 2.0", the "GNU Affero General Public
 * License v3.0 only", or the "Server Side Public License, v 1".
 */
apply plugin: 'elasticsearch.internal-cluster-test'
apply plugin: 'elasticsearch.internal-java-rest-test'
apply plugin: 'elasticsearch.internal-cluster-test'

esplugin {
  description = 'The EC2 discovery plugin allows to use AWS API for the unicast discovery mechanism.'
  classname ='org.elasticsearch.discovery.ec2.Ec2DiscoveryPlugin'
}

def patched = Attribute.of('patched', Boolean)

configurations {
  compileClasspath {
    attributes {
      attribute(patched, true)
    }
  }
  runtimeClasspath {
    attributes {
      attribute(patched, true)
    }
  }
  testCompileClasspath {
    attributes {
      attribute(patched, true)
    }
  }
  testRuntimeClasspath {
    attributes {
      attribute(patched, true)
    }
  }
}

dependencies {

  implementation "software.amazon.awssdk:annotations:${versions.awsv2sdk}"
  implementation "software.amazon.awssdk:apache-client:${versions.awsv2sdk}"
  implementation "software.amazon.awssdk:auth:${versions.awsv2sdk}"
  implementation "software.amazon.awssdk:aws-core:${versions.awsv2sdk}"
  implementation "software.amazon.awssdk:ec2:${versions.awsv2sdk}"
  implementation "software.amazon.awssdk:endpoints-spi:${versions.awsv2sdk}"
  implementation "software.amazon.awssdk:http-client-spi:${versions.awsv2sdk}"
  implementation "software.amazon.awssdk:identity-spi:${versions.awsv2sdk}"
  implementation "software.amazon.awssdk:imds:${versions.awsv2sdk}"
  implementation "software.amazon.awssdk:retries-spi:${versions.awsv2sdk}"
  implementation "software.amazon.awssdk:sdk-core:${versions.awsv2sdk}"
  implementation "software.amazon.awssdk:utils:${versions.awsv2sdk}"

  runtimeOnly "software.amazon.awssdk:aws-query-protocol:${versions.awsv2sdk}"
  runtimeOnly "software.amazon.awssdk:checksums-spi:${versions.awsv2sdk}"
  runtimeOnly "software.amazon.awssdk:checksums:${versions.awsv2sdk}"
  runtimeOnly "software.amazon.awssdk:http-auth-aws:${versions.awsv2sdk}"
  runtimeOnly "software.amazon.awssdk:http-auth-spi:${versions.awsv2sdk}"
  runtimeOnly "software.amazon.awssdk:http-auth:${versions.awsv2sdk}"
  runtimeOnly "software.amazon.awssdk:json-utils:${versions.awsv2sdk}"
  runtimeOnly "software.amazon.awssdk:metrics-spi:${versions.awsv2sdk}"
  runtimeOnly "software.amazon.awssdk:profiles:${versions.awsv2sdk}"
  runtimeOnly "software.amazon.awssdk:protocol-core:${versions.awsv2sdk}"
  runtimeOnly "software.amazon.awssdk:regions:${versions.awsv2sdk}"
  runtimeOnly "software.amazon.awssdk:retries:${versions.awsv2sdk}"
  runtimeOnly "software.amazon.awssdk:third-party-jackson-core:${versions.awsv2sdk}"

  implementation "org.apache.httpcomponents:httpclient:${versions.httpclient}"

  runtimeOnly "commons-codec:commons-codec:${versions.commonscodec}"
  runtimeOnly "commons-logging:commons-logging:${versions.commonslogging}"
  runtimeOnly "joda-time:joda-time:2.10.10"
  runtimeOnly "org.apache.httpcomponents:httpcore:${versions.httpcore}"
  runtimeOnly "org.apache.logging.log4j:log4j-1.2-api:${versions.log4j}"
  runtimeOnly "org.slf4j:slf4j-nop:${versions.slf4j}"
  // runtimeOnly("org.apache.logging.log4j:log4j-slf4j-impl:${versions.log4j}") https://github.com/elastic/elasticsearch/issues/93714
  runtimeOnly "org.slf4j:slf4j-api:${versions.slf4j}"
  runtimeOnly "org.reactivestreams:reactive-streams:${versions.reactive_streams}"

  javaRestTestImplementation project(':plugins:discovery-ec2')
  javaRestTestImplementation project(':test:fixtures:aws-fixture-utils')
  javaRestTestImplementation project(':test:fixtures:aws-ec2-fixture')
  javaRestTestImplementation project(':test:fixtures:ec2-imds-fixture')

  testImplementation project(':test:fixtures:aws-fixture-utils')
  testImplementation project(':test:fixtures:ec2-imds-fixture')

  internalClusterTestImplementation project(':test:fixtures:ec2-imds-fixture')

  attributesSchema {
    attribute(patched)
  }
  artifactTypes.getByName("jar") {
    attributes.attribute(patched, false)
  }
  registerTransform(org.elasticsearch.gradle.internal.dependencies.patches.awsv2sdk.Awsv2ClassPatcher) {
    from.attribute(patched, false)
    to.attribute(patched, true)
  }
}

tasks.named("dependencyLicenses").configure {
  mapping from: 'annotations',              to: 'aws-sdk-2'
  mapping from: 'apache-client',            to: 'aws-sdk-2'
  mapping from: 'auth',                     to: 'aws-sdk-2'
  mapping from: 'aws-core',                 to: 'aws-sdk-2'
  mapping from: 'aws-query-protocol',       to: 'aws-sdk-2'
  mapping from: 'checksums',                to: 'aws-sdk-2'
  mapping from: 'checksums-spi',            to: 'aws-sdk-2'
  mapping from: 'ec2',                      to: 'aws-sdk-2'
  mapping from: 'endpoints-spi',            to: 'aws-sdk-2'
  mapping from: 'http-auth',                to: 'aws-sdk-2'
  mapping from: 'http-auth-aws',            to: 'aws-sdk-2'
  mapping from: 'http-auth-spi',            to: 'aws-sdk-2'
  mapping from: 'http-client-spi',          to: 'aws-sdk-2'
  mapping from: 'identity-spi',             to: 'aws-sdk-2'
  mapping from: 'imds',                     to: 'aws-sdk-2'
  mapping from: 'json-utils',               to: 'aws-sdk-2'
  mapping from: 'metrics-spi',              to: 'aws-sdk-2'
  mapping from: 'profiles',                 to: 'aws-sdk-2'
  mapping from: 'protocol-core',            to: 'aws-sdk-2'
  mapping from: 'regions',                  to: 'aws-sdk-2'
  mapping from: 'retries',                  to: 'aws-sdk-2'
  mapping from: 'retries-spi',              to: 'aws-sdk-2'
  mapping from: 'sdk-core',                 to: 'aws-sdk-2'
  mapping from: 'third-party-jackson-core', to: 'aws-sdk-2'
  mapping from: 'utils',                    to: 'aws-sdk-2'
}

esplugin.bundleSpec.from('config/discovery-ec2') {
    into 'config'
}

tasks.register("writeTestJavaPolicy") {
  boolean inFips = buildParams.inFipsJvm
  inputs.property("inFipsJvm", inFips)
  final File javaPolicy = new File(layout.buildDirectory.asFile.get(), "tmp/java.policy")
  outputs.file(javaPolicy)
  doLast {
    if (inFips) {
      javaPolicy.write(
        [
          "grant {",
          "permission java.security.SecurityPermission \"putProviderProperty.BCFIPS\";",
          "permission java.security.SecurityPermission \"putProviderProperty.BCJSSE\";",
          "permission java.lang.RuntimePermission \"getProtectionDomain\";",
          "permission java.util.PropertyPermission \"java.runtime.name\", \"read\";",
          "permission org.bouncycastle.crypto.CryptoServicesPermission \"tlsAlgorithmsEnabled\";",
          "permission java.lang.RuntimePermission \"accessClassInPackage.sun.security.internal.spec\";",
          "permission java.lang.RuntimePermission \"accessDeclaredMembers\";",
          "permission java.util.PropertyPermission \"intellij.debug.agent\", \"read\";",
          "permission java.util.PropertyPermission \"intellij.debug.agent\", \"write\";",
          "permission org.bouncycastle.crypto.CryptoServicesPermission \"exportSecretKey\";",
          "permission org.bouncycastle.crypto.CryptoServicesPermission \"exportPrivateKey\";",
          "permission java.io.FilePermission \"\${javax.net.ssl.trustStore}\", \"read\";",
          "permission java.security.SecurityPermission \"getProperty.jdk.tls.disabledAlgorithms\";",
          "permission java.security.SecurityPermission \"getProperty.jdk.certpath.disabledAlgorithms\";",
          "permission java.security.SecurityPermission \"getProperty.keystore.type.compat\";",
          "permission java.security.SecurityPermission \"getProperty.org.bouncycastle.ec.max_f2m_field_size\";",
          "permission java.util.PropertyPermission \"aws.ec2MetadataServiceEndpoint\", \"write\";",
          "permission java.util.PropertyPermission \"http.proxyHost\", \"read\";",
          "permission java.util.PropertyPermission \"aws.region\", \"read\";",
          "};"
        ].join("\n")
      )
    } else {
      javaPolicy.write(
        [
          "grant {",
          "permission java.util.PropertyPermission \"aws.ec2MetadataServiceEndpoint\", \"write\";",
          "permission java.util.PropertyPermission \"http.proxyHost\", \"read\";",
          "permission java.util.PropertyPermission \"aws.region\", \"read\";",
          "};"
        ].join("\n"))
    }
  }
}

tasks.withType(Test).configureEach {
  dependsOn "writeTestJavaPolicy"
  // this is needed for insecure plugins, remove if possible!
  systemProperty 'tests.artifact', project.name

  // this is needed to manipulate aws.ec2MetadataServiceEndpoint system property
  // it is better rather disable security manager at all with `systemProperty 'tests.security.manager', 'false'`
  if (buildParams.inFipsJvm){
    nonInputProperties.systemProperty 'java.security.policy', "=file://${layout.buildDirectory.asFile.get()}/tmp/java.policy"
  } else {
    nonInputProperties.systemProperty 'java.security.policy', "file://${layout.buildDirectory.asFile.get()}/tmp/java.policy"
  }

  systemProperty 'aws.region', 'es-test-region'
}

tasks.named("thirdPartyAudit").configure {
  ignoreMissingClasses(
          // classes are missing
          'javax.servlet.ServletContextEvent',
          'javax.servlet.ServletContextListener',
          'org.apache.avalon.framework.logger.Logger',
          'org.apache.log.Hierarchy',
          'org.apache.log.Logger',
          'javax.jms.Message',

          // eventstream not used by the sync client
          'software.amazon.eventstream.HeaderValue',
          'software.amazon.eventstream.Message',
          'software.amazon.eventstream.MessageDecoder',

          // crt?
          'software.amazon.awssdk.crt.auth.credentials.Credentials',
          'software.amazon.awssdk.crt.auth.signing.AwsSigner',
          'software.amazon.awssdk.crt.auth.signing.AwsSigningConfig',
          'software.amazon.awssdk.crt.auth.signing.AwsSigningConfig$AwsSignatureType',
          'software.amazon.awssdk.crt.auth.signing.AwsSigningConfig$AwsSignedBodyHeaderType',
          'software.amazon.awssdk.crt.auth.signing.AwsSigningConfig$AwsSigningAlgorithm',
          'software.amazon.awssdk.crt.auth.signing.AwsSigningResult',
          'software.amazon.awssdk.crt.http.HttpHeader',
          'software.amazon.awssdk.crt.http.HttpRequest',
          'software.amazon.awssdk.crt.http.HttpRequestBodyStream',
  )
}
