// Copyright (C) 2023 The Android Open Source Project
//
// Licensed 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.

import com.google.common.base.Strings
import com.google.common.flogger.FluentLogger
import com.google.gerrit.extensions.annotations.Listen
import com.google.gerrit.extensions.annotations.PluginName
import com.google.gerrit.extensions.events.LifecycleListener
import com.google.gerrit.metrics.CallbackMetric1
import com.google.gerrit.metrics.Description
import com.google.gerrit.metrics.Field
import com.google.gerrit.metrics.MetricMaker
import com.google.gerrit.server.config.ConfigUtil
import com.google.gerrit.server.config.PluginConfigFactory
import com.google.gerrit.server.git.WorkQueue
import com.google.gerrit.server.logging.Metadata
import com.google.inject.Inject
import com.google.inject.Singleton

import javax.net.ssl.SSLSocket
import javax.net.ssl.SSLSocketFactory
import java.security.cert.Certificate
import java.security.cert.X509Certificate
import java.time.Duration
import java.time.Instant
import java.util.concurrent.ScheduledFuture

import static java.util.concurrent.TimeUnit.HOURS
import static java.util.concurrent.TimeUnit.MILLISECONDS
import static java.util.concurrent.TimeUnit.SECONDS

@Singleton
@Listen
class CertificatesValidityChecker implements LifecycleListener {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass()
  private static final int DEFAULT_CHECK_INTERVAL_HOURS = 24
  private static final int DEFAULT_CHECK_TIMEOUT_MSEC = 1000
  private final WorkQueue queue
  private final PluginConfigFactory config
  private final String pluginName
  private final CertificatesCheckMetrics metrics

  private ScheduledFuture<?> certificatesValidityChecksTask
  private List<String> endpoints
  private boolean started

  @Inject
  CertificatesValidityChecker(WorkQueue queue, PluginConfigFactory cfg,
                                   CertificatesCheckMetrics metrics,
                                   @PluginName String pluginName) {
    this.metrics = metrics
    this.queue = queue
    this.config = cfg
    this.pluginName = pluginName
  }

  @Override
  void start() {
    if (started) {
      logger.atWarning().log("Plugin already started: ignoring duplicate start")
      return
    }

    endpoints = getEndpointsList(config, pluginName)
    long checkIntervalInHours = getCheckIntervalHours(config, pluginName)
    int timeout = config.getGlobalPluginConfig(pluginName).getInt("validation",null,"timeout", DEFAULT_CHECK_TIMEOUT_MSEC)
    logger.atInfo().log("Checking certificates expiry date every %d hours (timeout=%d msec) for %s",
      checkIntervalInHours, timeout, endpoints)

    certificatesValidityChecksTask = queue.getDefaultQueue()
        .scheduleAtFixedRate(
            new CheckCertificatesValidityTask(metrics, endpoints, timeout),
            SECONDS.toMillis(1),
            HOURS.toMillis(checkIntervalInHours),
            MILLISECONDS)
    started = true
  }

  @Override
  void stop() {
    if (certificatesValidityChecksTask != null) {
      certificatesValidityChecksTask.cancel(true)
      certificatesValidityChecksTask = null
    }
    started = false
  }

  private Long getCheckIntervalHours(PluginConfigFactory cfg, String pluginName) {
    String fromConfig =
        Strings.nullToEmpty(cfg.getGlobalPluginConfig(pluginName).getString("validation",null,"checkInterval"))
    return ConfigUtil.getTimeUnit(fromConfig, DEFAULT_CHECK_INTERVAL_HOURS, HOURS)
  }

  private List<String> getEndpointsList(PluginConfigFactory cfg, String pluginName) {
    return cfg.getGlobalPluginConfig(pluginName).getStringList("validation",null,"endpoint")
  }

  private static class CertificatesCheckMetrics {
    private static final Field<String> ENDPOINT_NAME =
        Field.ofString("endpoint_name", Metadata.Builder.&cacheName).build()
    private final CallbackMetric1<String, Integer> metrics

    @Inject
    CertificatesCheckMetrics(MetricMaker metricMaker) {
      this.metrics =
          metricMaker.newCallbackMetric(
              "certificates/number_of_day_to_expire/per_endpoint",
              Integer.class,
              new Description("Per-endpoint certificate expiration date")
                  .setGauge()
                  .setUnit("days"),
              ENDPOINT_NAME)
    }

    def setMetric(String endpoint, int numberOfDays) {
      metrics.set(endpoint, numberOfDays)
    }
  }

  private static class CheckCertificatesValidityTask implements Runnable {
    private static final FluentLogger logger = FluentLogger.forEnclosingClass()
    private static final int DNS_TYPE = 2 // The GeneralNameInterface.NAME_DNS value, inaccessible because of being an internal package

    private final CertificatesCheckMetrics metrics
    private final List<String> endpoints
    private final int timeout

    CheckCertificatesValidityTask(CertificatesCheckMetrics metrics, List<String> endpoints, int timeout) {
      this.endpoints = endpoints
      this.metrics = metrics
      this.timeout = timeout
    }

    @Override
    void run() {
      for (String endpoint : endpoints) {
        logger.atFine().log("Checking certificate expiry date for %s endpoint", endpoint)
        SSLSocket conn
        try {
          def (hostname, port) = parseEndpoint(endpoint)
          conn = openConnection(hostname as String, port as int)
          conn.setSoTimeout(timeout)
          conn.startHandshake()
          X509Certificate[] certs = conn.getSession().getPeerCertificates().findAll {it instanceof X509Certificate}

          for (X509Certificate cert : certs) {
            def certsAlternativeNames = cert.subjectAlternativeNames
            def certsDnsNames = certsAlternativeNames.findAll{it[0] == DNS_TYPE}.collect{it[1]}
            if (certsDnsNames.empty) {
              logger.atFine().log("[%s] Skipping X.509 Certificate %s because there are no subjectAlternativeNames of DNS type", endpoint, cert)
              continue
            }

            logger.atFine().log("[%s] Checking X.509 DNS names %s against %s:%d", endpoint, certsDnsNames, hostname, port)
            def anyCertIsMatchingDnsNames = certsDnsNames.any{isHostnameMatching(hostname as String, it as String)}
            if (!anyCertIsMatchingDnsNames) {
              logger.atWarning().log("[%s] Skipping X.509 Certificate %s because none of the certificate DNS names %s are matching the hostname %s", endpoint, cert, certsDnsNames, hostname)
              continue
            }

            logger.atFine().log("[%s] X.509 Certificate %s has expiry date %s", endpoint, cert.subjectDN, cert.notAfter)
            def numberOfDaysToExpire = Duration
                .between(Instant.now(), cert.notAfter.toInstant()).toDays()
            metrics
                .setMetric(
                    hostname as String,
                    numberOfDaysToExpire.intValue())

            if (numberOfDaysToExpire >= 0) {
              logger.atInfo().log("[%s] X.509 Certificate %s is valid and has %d days left", endpoint, cert.subjectDN, numberOfDaysToExpire)
            } else {
              logger.atWarning().log("[%s] X.509 Certificate for %s **EXPIRED**", endpoint, cert.subjectDN)
            }
          }
        } catch(e) {
          logger.atSevere()
              .withCause(e)
              .log("Cannot check certificates expiry date for %s endpoint", endpoint)
        } finally {
            conn?.close()
        }
      }
    }

    def parseEndpoint(String endpoint) {
      def hostAndPort = endpoint.split(':')
      if (hostAndPort.size() != 2) {
        throw new IllegalArgumentException("Wrong endpoint format, expected <host>:<port> but was ${endpoint}")
      }

      hostAndPort
    }

    private boolean isHostnameMatching(String hostname, String certName) {
      // Replace the wildcard (*) with a regex wildcard (.*)
      def certPattern = certName.replaceFirst("\\*", ".*")
      return hostname.matches(certPattern)
    }

    private SSLSocket openConnection(String hostname, int port) {
      (SSLSocket) SSLSocketFactory.getDefault()
          .createSocket(hostname, port);
    }
  }
}
