// Copyright 2017 Google LLC. All Rights Reserved.
//
// 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.

syntax = "proto3";

option go_package = "github.com/google/certificate-transparency-go/trillian/ctfe/configpb";

package configpb;

import "crypto/keyspb/keyspb.proto";
import "google/protobuf/any.proto";
import "google/protobuf/timestamp.proto";

message LogBackend {
  // name defines the name of the log backend for use in LogConfig messages and must be unique.
  string name = 1;
  // backend_spec defines the RPC endpoint that clients should use to send requests
  // to this log backend. These should be in the same format as rpcBackendFlag in the
  // CTFE main and must not be an empty string.
  string backend_spec = 2;
}

// LogBackendSet supports a configuration where a single set of frontends handle
// requests for multiple backends. For example this could be used to run different
// backends in different geographic regions.
message LogBackendSet {
  repeated LogBackend backend = 1;
}

// LogConfigSet is a set of LogConfig messages.
message LogConfigSet {
  repeated LogConfig config = 1;
}

// LogConfig describes the configuration options for a log instance.
//
// NEXT_ID: 22
message LogConfig {
  // The ID of a Trillian tree that stores the log data. The tree type must be
  // LOG for regular CT logs. For mirror logs it must be either PREORDERED_LOG
  // or LOG, and can change at runtime. CTFE in mirror mode uses only read API
  // which is common for both types.
  int64 log_id = 1;
  // prefix is the name of the log. It will come after the global or
  // override handler prefix. For example if the handler prefix is "/logs"
  // and prefix is "vogon" the get-sth handler for this log will be
  // available at "/logs/vogon/ct/v1/get-sth". The prefix cannot be empty
  // and must not include "/" path separator characters.
  string prefix = 2;
  // override_handler_prefix if set to a non empty value overrides the global
  // handler prefix for an individual log. For example this field is set to
  // "/otherlogs" then a log with prefix "vogon" will make it's get-sth handler
  // available at "/otherlogs/vogon/ct/v1/get-sth" regardless of what the
  // global prefix is. Can be set to '/' to make the get-sth handler register
  // at "/vogon/ct/v1/get-sth".
  string override_handler_prefix = 13;
  // Paths to the files containing root certificates that are acceptable to the
  // log. The certs are served through get-roots endpoint. Optional in mirrors.
  repeated string roots_pem_file = 3;
  // The private key used for signing STHs etc. Not required for mirrors.
  google.protobuf.Any private_key = 4;
  // The public key matching the above private key (if both are present). It is
  // used only by mirror logs for verifying the source log's signatures, but can
  // be specified for regular logs as well for the convenience of test tools.
  keyspb.PublicKey public_key = 5;
  // If reject_expired is true then the certificate validity period will be
  // checked against the current time during the validation of submissions.
  // This will cause expired certificates to be rejected.
  bool reject_expired = 6;
  // If reject_unexpired is true then CTFE rejects certificates that are either
  // currently valid or not yet valid.
  bool reject_unexpired = 17;
  // If set, ext_key_usages will restrict the set of such usages that the
  // server will accept. By default all are accepted. The values specified
  // must be ones known to the x509 package.
  repeated string ext_key_usages = 7;
  // not_after_start defines the start of the range of acceptable NotAfter
  // values, inclusive.
  // Leaving this unset implies no lower bound to the range.
  google.protobuf.Timestamp not_after_start = 8;
  // not_after_limit defines the end of the range of acceptable NotAfter values,
  // exclusive.
  // Leaving this unset implies no upper bound to the range.
  google.protobuf.Timestamp not_after_limit = 9;
  // accept_only_ca controls whether or not *only* certificates with the CA bit
  // set will be accepted.
  bool accept_only_ca = 10;
  // backend_name if set indicates which backend serves this log. The name must be
  // one of those defined in the LogBackendSet.
  string log_backend_name = 11;
  // If set, the log is a mirror, i.e. it serves the data of another (source)
  // log. It doesn't handle write requests (add-chain, etc.), so it's not a
  // fully fledged RFC-6962 log, but the tree read requests like get-entries and
  // get-consistency-proof are compatible. A mirror doesn't have the source
  // log's key and can't sign STHs. Consequently, the log operator must ensure
  // to channel source log's STHs into CTFE.
  bool is_mirror = 12;

  // If set, the log serves only read endpoints, and rejects writes through the
  // add-[pre-]chain endpoint.
  bool is_readonly = 19;

  // The Maximum Merge Delay (MMD) of this log in seconds. See RFC6962 section 3
  // for definition of MMD. If zero, the log does not provide an MMD guarantee
  // (for example, it is a frozen log).
  int32 max_merge_delay_sec = 14;
  // The merge delay that the underlying log implementation is able/targeting to
  // provide. This option is exposed in CTFE metrics, and can be particularly
  // useful to catch when the log is behind but has not yet violated the strict
  // MMD limit.
  // Log operator should decide what exactly EMD means for them. For example, it
  // can be a 99-th percentile of merge delays that they observe, and they can
  // alert on the actual merge delay going above a certain multiple of this EMD.
  int32 expected_merge_delay_sec = 15;

  // The STH that this log will serve permanently (if present). Frozen STH must
  // be signed by this log's private key, and will be verified using the public
  // key specified in this config.
  SignedTreeHead frozen_sth = 16;

  // A list of X.509 extension OIDs, in dotted string form (e.g. "2.3.4.5")
  // which should cause submissions to be rejected.
  repeated string reject_extensions = 18;

  // CTFE storage connection string in the following format in general:
  // driver://[username[:password]@][protocol[(host[:port])]][/[schema|database][?options]]
  //
  // MySQL/MariaDB:
  // mysql://[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...&paramN=valueN]
  //
  // This is required when the issuance chain storage backend is CTFE.
  // 
  // Warning: CT log operators are advised not to re-use the same connection 
  // string across multiple LogConfigs due to the log lifecycle.
  string ctfe_storage_connection_string = 20;

  // An optional storage backend for the issuance chain in ExtraData. 
  // By default, the storage backend is Trillian GRPC. To use CTFE as the 
  // storage backend, the CTFE storage connection string needs to be specified.
  // Do not change this value during the log's lifetime.
  enum IssuanceChainStorageBackend {
    ISSUANCE_CHAIN_STORAGE_BACKEND_TRILLIAN_GRPC = 0;
    ISSUANCE_CHAIN_STORAGE_BACKEND_CTFE = 1;
  }
  IssuanceChainStorageBackend extra_data_issuance_chain_storage_backend = 21;
}

// LogMultiConfig wraps up a LogBackendSet and corresponding LogConfigSet so
// that they can easily be parsed as a single proto.
message LogMultiConfig {
  // The set of backends that this configuration will use to send requests to.
  // The names of the backends in the LogBackendSet must all be distinct.
  LogBackendSet backends = 1;
  // The set of logs that will use the above backends. All the protos in this
  // LogConfigSet must set a valid log_backend_name for the config to be usable.
  LogConfigSet log_configs = 2;
}

// SignedTreeHead represents the structure returned by the get-sth CT method.
// See RFC6962 sections 3.5 and 4.3 for reference.
// TODO(pavelkalinnikov): Find a better place for this type.
message SignedTreeHead {
  int64 tree_size = 1;
  int64 timestamp = 2;
  bytes sha256_root_hash = 3;
  bytes tree_head_signature = 4;
}
