// 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.
//
// Copied from Impala and adapted to Kudu.

#pragma once

#include <memory>
#include <mutex>
#include <string>
#include <unordered_map>
#include <utility>

#include <jwt-cpp/jwt.h>

#include "kudu/gutil/ref_counted.h"
#include "kudu/util/logging.h"
#include "kudu/util/promise.h"
#include "kudu/util/thread.h"
#include "kudu/util/status.h"

using DecodedJWT = jwt::decoded_jwt<jwt::traits::kazuho_picojson>;
using JWTVerifier = jwt::verifier<jwt::default_clock, jwt::traits::kazuho_picojson>;

namespace kudu {

// Key-Value map for parsing Json keys.
typedef std::unordered_map<std::string, std::string> JsonKVMap;

// JWTPublicKey:
// This class represent cryptographic public key for JSON Web Token (JWT) verification.
class JWTPublicKey {
 public:
  JWTPublicKey(std::string algorithm, std::string pub_key)
  : verifier_(jwt::verify()), algorithm_(std::move(algorithm)), public_key_(std::move(pub_key)) {}

  // Verify the given decoded token.
  Status Verify(const DecodedJWT& decoded_jwt, const std::string& algorithm) const;

  const std::string& get_algorithm() const { return algorithm_; }
  const std::string& get_key() const { return public_key_; }

 protected:
  // JWT Verifier.
  JWTVerifier verifier_;

 private:
  // Signing Algorithm:
  // Currently support following JSON Web Algorithms (JWA):
  // HS256, HS384, HS512, RS256, RS384, and RS512.
  const std::string algorithm_;
  // Public key value:
  // For EC and RSA families of algorithms, it's the public key converted in PEM-encoded
  // format since jwt-cpp APIs only accept EC/RSA public keys in PEM-encoded format.
  // For HMAC-SHA2, it's Octet Sequence key representing secret key.
  const std::string public_key_;
};

// JWT Public Key for HS256.
// HS256: HMAC using SHA-256.
class HS256JWTPublicKey : public JWTPublicKey {
 public:
  // Throw JWT exception if failed to initialize the verifier.
  HS256JWTPublicKey(std::string algorithm, const std::string& pub_key)
      : JWTPublicKey(std::move(algorithm), pub_key) {
    verifier_.allow_algorithm(jwt::algorithm::hs256(pub_key));
  }
};

// JWT Public Key for HS384.
// HS384: HMAC using SHA-384.
class HS384JWTPublicKey : public JWTPublicKey {
 public:
  // Throw exception if failed to initialize the JWT verifier.
  HS384JWTPublicKey(std::string algorithm, const std::string& pub_key)
      : JWTPublicKey(std::move(algorithm), pub_key) {
    verifier_.allow_algorithm(jwt::algorithm::hs384(pub_key));
  }
};

// JWT Public Key for HS512.
// HS512: HMAC using SHA-512.
class HS512JWTPublicKey : public JWTPublicKey {
 public:
  // Throw JWT exception if failed to initialize the verifier.
  HS512JWTPublicKey(std::string algorithm, const std::string& pub_key)
      : JWTPublicKey(std::move(algorithm), pub_key) {
    verifier_.allow_algorithm(jwt::algorithm::hs512(pub_key));
  }
};

// JWT Public Key for RS256.
// RS256: RSASSA-PKCS1-v1_5 using SHA-256.
class RS256JWTPublicKey : public JWTPublicKey {
 public:
  // Throw JWT exception if failed to initialize the verifier.
  RS256JWTPublicKey(std::string algorithm, const std::string& pub_key)
      : JWTPublicKey(std::move(algorithm), pub_key) {
    verifier_.allow_algorithm(jwt::algorithm::rs256(pub_key, "", "", ""));
  }
};

// JWT Public Key for RS384.
// RS384: RSASSA-PKCS1-v1_5 using SHA-384.
class RS384JWTPublicKey : public JWTPublicKey {
 public:
  // Throw exception if failed to initialize the JWT verifier.
  RS384JWTPublicKey(std::string algorithm, const std::string& pub_key)
      : JWTPublicKey(std::move(algorithm), pub_key) {
    verifier_.allow_algorithm(jwt::algorithm::rs384(pub_key, "", "", ""));
  }
};

// JWT Public Key for RS512.
// RS512: RSASSA-PKCS1-v1_5 using SHA-512.
class RS512JWTPublicKey : public JWTPublicKey {
 public:
  // Throw JWT exception if failed to initialize the verifier.
  RS512JWTPublicKey(std::string algorithm, const std::string& pub_key)
      : JWTPublicKey(std::move(algorithm), pub_key) {
    verifier_.allow_algorithm(jwt::algorithm::rs512(pub_key, "", "", ""));
  }
};

// JWT Public Key for PS256.
// PS256: RSASSA-PSS using SHA-256 and MGF1 with SHA-256.
// RSASSA-PSS is the probabilistic version of RSA.
class PS256JWTPublicKey : public JWTPublicKey {
 public:
  // Throw JWT exception if failed to initialize the verifier.
  PS256JWTPublicKey(std::string algorithm, const std::string& pub_key)
      : JWTPublicKey(std::move(algorithm), pub_key) {
    verifier_.allow_algorithm(jwt::algorithm::ps256(pub_key, "", "", ""));
  }
};

// JWT Public Key for PS384.
// PS384: RSASSA-PSS using SHA-384 and MGF1 with SHA-384.
class PS384JWTPublicKey : public JWTPublicKey {
 public:
  // Throw exception if failed to initialize the JWT verifier.
  PS384JWTPublicKey(std::string algorithm, const std::string& pub_key)
      : JWTPublicKey(std::move(algorithm), pub_key) {
    verifier_.allow_algorithm(jwt::algorithm::ps384(pub_key, "", "", ""));
  }
};

// JWT Public Key for PS512.
// PS512: RSASSA-PSS using SHA-512 and MGF1 with SHA-512.
class PS512JWTPublicKey : public JWTPublicKey {
 public:
  // Throw JWT exception if failed to initialize the verifier.
  PS512JWTPublicKey(std::string algorithm, const std::string& pub_key)
      : JWTPublicKey(std::move(algorithm), pub_key) {
    verifier_.allow_algorithm(jwt::algorithm::ps512(pub_key, "", "", ""));
  }
};

// JWT Public Key for ES256.
// ES256: ECDSA using P-256 and SHA-256.
class ES256JWTPublicKey : public JWTPublicKey {
 public:
  // Throw JWT exception if failed to initialize the verifier.
  ES256JWTPublicKey(std::string algorithm, const std::string& pub_key)
      : JWTPublicKey(std::move(algorithm), pub_key) {
    verifier_.allow_algorithm(jwt::algorithm::es256(pub_key, "", "", ""));
  }
};

// JWT Public Key for ES384.
// ES384: ECDSA using P-384 and SHA-384.
class ES384JWTPublicKey : public JWTPublicKey {
 public:
  // Throw exception if failed to initialize the JWT verifier.
  ES384JWTPublicKey(std::string algorithm, const std::string& pub_key)
      : JWTPublicKey(std::move(algorithm), pub_key) {
    verifier_.allow_algorithm(jwt::algorithm::es384(pub_key, "", "", ""));
  }
};

// JWT Public Key for ES512.
// ES512: ECDSA using P-521 and SHA-512.
class ES512JWTPublicKey : public JWTPublicKey {
 public:
  // Throw JWT exception if failed to initialize the verifier.
  ES512JWTPublicKey(std::string algorithm, const std::string& pub_key)
      : JWTPublicKey(std::move(algorithm), pub_key) {
    verifier_.allow_algorithm(jwt::algorithm::es512(pub_key, "", "", ""));
  }
};

// Construct a JWKPublicKey of HS from the JWK.
class HSJWTPublicKeyBuilder {
 public:
  static Status CreateJWKPublicKey(const JsonKVMap& kv_map,
                                   std::unique_ptr<JWTPublicKey>* pub_key_out);
};

// Construct a JWKPublicKey of RSA from the JWK.
class RSAJWTPublicKeyBuilder {
 public:
  static Status CreateJWKPublicKey(const JsonKVMap& kv_map,
                                   std::unique_ptr<JWTPublicKey>* pub_key_out);

 private:
  // Convert JWK's RSA public key to PEM format using OpenSSL API.
  static Status ConvertJwkToPem(
      const std::string& base64_n, const std::string& base64_e, std::string& pub_key);
};

// Construct a JWKPublicKey of EC from the JWK.
class ECJWTPublicKeyBuilder {
 public:
  static Status CreateJWKPublicKey(const JsonKVMap& kv_map,
                                   std::unique_ptr<JWTPublicKey>* pub_key_out);

 private:
  // Convert JWK's EC public key to PEM format using OpenSSL API.
  static Status ConvertJwkToPem(int eccgrp,
                                const std::string& base64_x,
                                const std::string& base64_y,
                                std::string& pub_key);
};

// This class load the JWKS from file or URL, store keys in an internal maps for each
// family of algorithms, and provides API to retrieve key by key-id.
// It's a snapshot of the current JWKS. The JWKSMgr maintains a consistent copy of this
// and updates it atomically when the public keys in JWKS are changed. Clients can obtain
// an immutable copy. Class instances can be created through the implicitly-defined
// default and copy constructors.
class JWKSSnapshot final {
 public:
  JWKSSnapshot() = default;
  JWKSSnapshot(const JWKSSnapshot&) = default;

  // Map from a key ID (kid) to a JWTPublicKey.
  typedef std::unordered_map<std::string, std::unique_ptr<JWTPublicKey>> JWTPublicKeyMap;

  // Load JWKS stored in a JSON file. Returns an error if problems were encountered
  // while parsing/constructing the Json Web keys. If no keys were given in the file,
  // the internal maps will be empty.
  Status LoadKeysFromFile(const std::string& jwks_file_path);
  // Download JWKS JSON file from the given URL, then load the public keys if the
  // checksum of JWKS object is changed. If no keys were given in the URL, the internal
  // maps will be empty.
  Status LoadKeysFromUrl(const std::string& jwks_url, bool jwks_verify_server_certificate,
                         uint64_t cur_jwks_hash, bool* is_changed);


  // Look up the key ID in the internal key maps and returns the key if the lookup was
  // successful, otherwise return nullptr.
  const JWTPublicKey* LookupRSAPublicKey(const std::string& kid) const;
  const JWTPublicKey* LookupHSKey(const std::string& kid) const;
  const JWTPublicKey* LookupECPublicKey(const std::string& kid) const;

  // Return number of keys for each family of algorithms.
  int GetHSKeyNum() const { return static_cast<int>(hs_key_map_.size()); }
  // Return number of keys for RSA.
  int GetRSAPublicKeyNum() const { return static_cast<int>(rsa_pub_key_map_.size()); }
  // Return number of keys for EC.
  int GetECPublicKeyNum() const { return static_cast<int>(ec_pub_key_map_.size()); }

  // Return all keys for HS.
  const JWTPublicKeyMap* GetAllHSKeys() const { return &hs_key_map_; }
  // Return all keys for RSA.
  const JWTPublicKeyMap* GetAllRSAPublicKeys() const { return &rsa_pub_key_map_; }
  // Return all keys for EC.
  const JWTPublicKeyMap* GetAllECPublicKeys() const { return &ec_pub_key_map_; }

  // Return TRUE if there is no key.
  bool IsEmpty() const {
    return hs_key_map_.empty() && rsa_pub_key_map_.empty() && ec_pub_key_map_.empty();
  }

  uint64_t GetChecksum() const { return jwks_checksum_; }

 private:
  friend class JWKSetParser;

  // Following two functions are called inside Init().
  // Add a RSA public key.
  void AddRSAPublicKey(const std::string& key_id, std::unique_ptr<JWTPublicKey> jwk_pub_key);
  // Add a HS key.
  void AddHSKey(const std::string& key_id, std::unique_ptr<JWTPublicKey> jwk_pub_key);
  // Add an EC public key.
  void AddECPublicKey(const std::string& key_id, std::unique_ptr<JWTPublicKey> jwk_pub_key);

  // Note: According to section 4.5 of RFC 7517 (JSON Web Key), different keys might use
  // the same "kid" value is if they have different "kty" (key type) values but are
  // considered to be equivalent alternatives by the application using them. So keys
  // for each "kty" are saved in different maps.

  // Octet Sequence keys for HS256 (HMAC using SHA-256), HS384 and HS512.
  // kty (key type): oct.
  JWTPublicKeyMap hs_key_map_;
  // Public keys for RSA family of algorithms: RS256, RS384, RS512, PS256, PS384, PS512.
  // kty (key type): RSA.
  JWTPublicKeyMap rsa_pub_key_map_;
  // Public keys for EC family of algorithms: ES256, ES384, ES512.
  // kty (key type): EC.
  JWTPublicKeyMap ec_pub_key_map_;

  // 64 bit checksum of JWKS object.
  // This variable is only used when downloading JWKS from the given URL.
  uint64_t jwks_checksum_ = 0;
};

// An immutable shared JWKS snapshot.
typedef std::shared_ptr<const JWKSSnapshot> JWKSSnapshotPtr;

// JSON Web Key Set (JWKS) conveys the public keys used by the signing party to the
// clients that need to validate signatures. It represents a cryptographic key set in
// JSON data structure.
// This class works as JWKS manager, which load the JWKS from local file or URL.
// Init() should be called during the initialization of the daemon.
// The class is thread safe.
class JWKSMgr {
 public:
   JWKSMgr() {}

  // Destructor is only called for backend tests
  ~JWKSMgr();

  // Load JWKS stored in a JSON file. Returns an error if problems were encountered
  // while parsing/constructing the Json Web keys. If no keys were given in the file,
  // the internal maps will be empty.
  // If the given jwks_uri is a URL, start a working thread which will periodically
  // checks the JWKS URL for updates. This provides support for key rotation.
  Status Init(const std::string& jwks_uri, bool jwks_verify_server_certificate,
              bool is_local_file);

  // Returns a read only snapshot of the current JWKS. This function should be called
  // after calling Init().
  JWKSSnapshotPtr GetJWKSSnapshot() const;

 private:
  // Atomically replaces a JWKS snapshot with a new copy.
  void SetJWKSSnapshot(const JWKSSnapshotPtr& new_jwks);

  // Helper function for working thread which periodically checks the JWKS URL for
  // updates.
  void UpdateJWKSThread();

  // Thread that runs UpdateJWKSThread(). This thread will exit when the
  // shut_down_promise_ is set.
  scoped_refptr<Thread> jwks_update_thread_;
  Promise<bool> shut_down_promise_;

  // JWKS URI.
  std::string jwks_uri_;

  // JWKS insecure TLS
  bool jwks_verify_server_certificate_;

  // The snapshot of the current JWKS. When the checksum of downloaded JWKS json object
  // has been changed, the public keys will be reloaded and the content of this pointer
  // will be atomically swapped.
  JWKSSnapshotPtr current_jwks_;
  // 64 bit checksum of current JWKS object.
  uint64_t current_jwks_checksum_ = 0;

  // Protects current_jwks_.
  mutable std::mutex current_jwks_lock_;
};

} // namespace kudu
