// Copyright 2016 The LUCI Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.

syntax = "proto3";

package tokenserver.admin;

option go_package = "go.chromium.org/luci/tokenserver/api/admin/v1;admin";

import "google/protobuf/empty.proto";

import "go.chromium.org/luci/server/auth/delegation/messages/delegation.proto";
import "go.chromium.org/luci/tokenserver/api/machine_token.proto";


// Admin service is used by service administrators to manage the server.
service Admin {
  // ImportCAConfigs makes the server read 'tokenserver.cfg'.
  rpc ImportCAConfigs(google.protobuf.Empty) returns (ImportedConfigs);

  // ImportDelegationConfigs makes the server read 'delegation.cfg'.
  rpc ImportDelegationConfigs(google.protobuf.Empty) returns (ImportedConfigs);

  // ImportProjectIdentityConfigs makes the server read 'projects.cfg'.
  rpc ImportProjectIdentityConfigs(google.protobuf.Empty) returns (ImportedConfigs);

  // ImportProjectOwnedAccountsConfigs makes the server read 'project_owned_accounts.cfg'.
  rpc ImportProjectOwnedAccountsConfigs(google.protobuf.Empty) returns (ImportedConfigs);

  // InspectMachineToken decodes a machine token and verifies it is valid.
  //
  // It verifies the token was signed by a private key of the token server and
  // checks token's expiration time and revocation status.
  //
  // It tries to give as much information about the token and its status as
  // possible (e.g. it checks for revocation status even if token is already
  // expired).
  //
  // Administrators can use this call to debug issues with tokens.
  //
  // Returns:
  //   InspectMachineTokenResponse for tokens of supported kind.
  //   grpc.InvalidArgument error for unsupported token kind.
  //   grpc.Internal error for transient errors.
  rpc InspectMachineToken(InspectMachineTokenRequest) returns (InspectMachineTokenResponse);

  // InspectDelegationToken decodes a delegation token and verifies it is valid.
  //
  // It verifies the token was signed by a private key of the token server and
  // checks token's expiration time.
  //
  // It tries to give as much information about the token and its status as
  // possible (e.g. attempts to decode the body even if the signing key has been
  // rotated already).
  //
  // Administrators can use this call to debug issues with tokens.
  //
  // Returns:
  //   InspectDelegationTokenResponse for tokens of supported kind.
  //   grpc.InvalidArgument error for unsupported token kind.
  //   grpc.Internal error for transient errors.
  rpc InspectDelegationToken(InspectDelegationTokenRequest) returns (InspectDelegationTokenResponse);
}


// ImportedConfigs is returned by Import<something>Configs methods on success.
message ImportedConfigs {
  // The revision of the configs that are now in the datastore.
  //
  // It's either the imported revision, if configs change, or a previously known
  // revision, if configs at HEAD are same.
  string revision = 1;
}


// InspectMachineTokenRequest is body of InspectMachineToken RPC call.
//
// It contains machine token of some kind.
message InspectMachineTokenRequest {
  // The type of token being checked.
  //
  // Currently only LUCI_MACHINE_TOKEN is supported. This is also the default.
  tokenserver.MachineTokenType token_type = 1;

  // The token body. Exact meaning depends on token_type.
  string token = 2;
}


// InspectMachineTokenResponse is return value of InspectMachineToken RPC call.
message InspectMachineTokenResponse {
  // True if the token is valid.
  //
  // A token is valid if its signature is correct, it hasn't expired yet and
  // the credentials it was built from (e.g. a certificate) wasn't revoked.
  bool valid = 1;

  // Human readable summary of why token is invalid.
  //
  // Summarizes the rest of the fields of this struct. Set only if 'valid' is
  // false.
  string invalidity_reason = 2;

  // True if the token signature was verified.
  //
  // It means the token was generated by the token server and its body is not
  // a garbage. Note that a token can be correctly signed, but invalid (if it
  // has expired or was revoked).
  //
  // If 'signed' is false, the fields below may (or may not) be a garbage.
  //
  // The token server uses private keys managed by Google Cloud Platform, they
  // are constantly being rotated and "old" signatures become invalid over time
  // (when corresponding keys are rotated out of existence).
  //
  // If 'signed' is false, use the rest of the response only as FYI, possibly
  // invalid or even maliciously constructed.
  bool signed = 3;

  // True if the token signature was verified and token hasn't expired yet.
  //
  // We use "non_" prefix to make default 'false' value safer.
  bool non_expired = 4;

  // True if the token signature was verified and the token wasn't revoked.
  //
  // It is possible for an expired token to be non revoked. They are independent
  // properties.
  //
  // We use "non_" prefix to make default 'false' value safer.
  bool non_revoked = 5;

  // Id of a private key used to sign this token, if applicable.
  string signing_key_id = 6;

  // Name of a CA that issued the cert the token is based on, if applicable.
  //
  // Resolved from 'ca_id' field of the token body.
  string cert_ca_name = 7;

  // The decoded token body (depends on token_type request parameter). Empty if
  // token was malformed and couldn't be deserialized.
  oneof token_type {
    tokenserver.MachineTokenBody luci_machine_token = 20;
  }
}


// InspectDelegationTokenRequest is body of InspectDelegationToken RPC call.
message InspectDelegationTokenRequest {
  // The token body.
  string token = 1;
}


// InspectDelegationTokenResponse is return value of InspectDelegationToken RPC.
message InspectDelegationTokenResponse {
  // True if the token is valid.
  //
  // A token is valid if its signature is correct and it hasn't expired yet.
  bool valid = 1;

  // Human readable summary of why token is invalid.
  //
  // Summarizes the rest of the fields of this struct. Set only if 'valid' is
  // false.
  string invalidity_reason = 2;

  // True if the token signature was verified.
  //
  // It means the token was generated by the token server and its body is not
  // a garbage. Note that a token can be correctly signed, but invalid (if it
  // has expired).
  //
  // If 'signed' is false, the fields below may (or may not) be a garbage.
  //
  // The token server uses private keys managed by Google Cloud Platform, they
  // are constantly being rotated and "old" signatures become invalid over time
  // (when corresponding keys are rotated out of existence).
  //
  // If 'signed' is false, use the rest of the response only as FYI, possibly
  // invalid or even maliciously constructed.
  bool signed = 3;

  // True if the token signature was verified and token hasn't expired yet.
  //
  // We use "non_" prefix to make default 'false' value safer.
  bool non_expired = 4;

  // The deserialized token envelope.
  //
  // May be empty if token was malformed and couldn't be deserialized.
  messages.DelegationToken envelope = 5;

  // The deserialized token body (deserialized 'envelope.serialized_subtoken').
  //
  // May be empty if token was malformed and couldn't be deserialized.
  messages.Subtoken subtoken = 6;
}
