// 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.
#pragma once

#include <cstdint>
#include <map>
#include <memory>
#include <vector>

#include "kudu/gutil/macros.h"
#include "kudu/gutil/port.h"
#include "kudu/util/rw_mutex.h"

namespace kudu {

class Status;

namespace security {

class SignedTokenPB;
class TokenPB;
class TokenSigningPublicKey;
class TokenSigningPublicKeyPB;
enum class TokenVerificationResult;

// Class responsible for verifying tokens provided to a server.
//
// This class manages a set of public keys, each identified by a sequence
// number. It exposes the latest known sequence number, which can be sent
// to a 'TokenSigner' running on another node. That node can then
// export public keys, which are transferred back to this node and imported
// into the 'TokenVerifier'.
//
// Each signed token also includes the key sequence number that signed it,
// so this class can look up the correct key and verify the token's
// validity and expiration.
//
// Note that this class does not perform any "business logic" around the
// content of a token. It only verifies that the token has a valid signature
// and is not yet expired. Any business rules around authorization or
// authentication are left up to callers.
//
// NOTE: old tokens are never removed from the underlying storage of this
// class. The assumption is that tokens rotate so infreqeuently that this
// slow leak is not worrisome. If this class is adopted for any use cases
// with frequent rotation, GC of expired tokens will need to be added.
//
// This class is thread-safe.
class TokenVerifier {
 public:
  TokenVerifier();
  ~TokenVerifier();

  // Return the highest key sequence number known by this instance.
  //
  // If no keys are known, return -1.
  int64_t GetMaxKnownKeySequenceNumber() const;

  // Import a set of public keys provided by a TokenSigner instance
  // (which might be running on a remote node). If any public keys already
  // exist with matching key sequence numbers, they are replaced by
  // the new keys.
  Status ImportKeys(const std::vector<TokenSigningPublicKeyPB>& keys) WARN_UNUSED_RESULT;

  // Export token signing public keys. Specifying the 'after_sequence_number'
  // allows to get public keys with sequence numbers greater than
  // 'after_sequence_number'. If the 'after_sequence_number' parameter is
  // omitted, all known public keys are exported.
  std::vector<TokenSigningPublicKeyPB> ExportKeys(
      int64_t after_sequence_number = -1) const;

  // Verify the signature on the given signed token, and deserialize the
  // contents into 'token'.
  TokenVerificationResult VerifyTokenSignature(
      const SignedTokenPB& signed_token, TokenPB* token) const;

 private:
  typedef std::map<int64_t, std::unique_ptr<TokenSigningPublicKey>> KeysMap;

  // Lock protecting keys_by_seq_
  mutable RWMutex lock_;
  KeysMap keys_by_seq_;

  DISALLOW_COPY_AND_ASSIGN(TokenVerifier);
};

// Result of a token verification.
// Values added to this enum must also be added to VerificationResultToString().
enum class TokenVerificationResult {
  // The signature is valid and the token is not expired.
  VALID,
  // The token itself is invalid (e.g. missing its signature or data,
  // can't be deserialized, etc).
  INVALID_TOKEN,
  // The signature is invalid (i.e. cryptographically incorrect).
  INVALID_SIGNATURE,
  // The signature is valid, but the token has already expired.
  EXPIRED_TOKEN,
  // The signature is valid, but the signing key is no longer valid.
  EXPIRED_SIGNING_KEY,
  // The signing key used to sign this token is not available.
  UNKNOWN_SIGNING_KEY,
  // The token uses an incompatible feature which isn't supported by this
  // version of the server. We reject the token to give a "default deny"
  // policy.
  INCOMPATIBLE_FEATURE
};

const char* TokenVerificationResultToString(TokenVerificationResult r);

} // namespace security
} // namespace kudu
