// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

syntax = "proto3";
package pb;

import "google/protobuf/timestamp.proto";
import "sdk/logical/event.proto";
import "sdk/logical/identity.proto";
import "sdk/logical/plugin.proto";

option go_package = "github.com/hashicorp/vault/sdk/plugin/pb";

message Empty {}

message Header {
  repeated string header = 1;
}

message ProtoError {
  // Error type can be one of:
  // ErrTypeUnknown uint32 = iota
  // ErrTypeUserError
  // ErrTypeInternalError
  // ErrTypeCodedError
  // ErrTypeStatusBadRequest
  // ErrTypeUnsupportedOperation
  // ErrTypeUnsupportedPath
  // ErrTypeInvalidRequest
  // ErrTypePermissionDenied
  // ErrTypeMultiAuthzPending
  // ErrTypeUnrecoverable
  uint32 err_type = 1;
  string err_msg = 2;
  int64 err_code = 3;
}

// Paths is the structure of special paths that is used for SpecialPaths.
message Paths {
  // Root are the paths that require a root token to access
  repeated string root = 1;

  // Unauthenticated are the paths that can be accessed without any auth.
  repeated string unauthenticated = 2;

  // LocalStorage are paths (prefixes) that are local to this instance; this
  // indicates that these paths should not be replicated
  repeated string local_storage = 3;

  // SealWrapStorage are storage paths that, when using a capable seal,
  // should be seal wrapped with extra encryption. It is exact matching
  // unless it ends with '/' in which case it will be treated as a prefix.
  repeated string seal_wrap_storage = 4;

  // WriteForwardedStorage are storage paths that, when running on a PR
  // Secondary cluster, cause a GRPC call up to the PR Primary cluster's
  // active node to handle storage.Put(...) and storage.Delete(...) events.
  //
  // See extended note in /sdk/logical/logical.go.
  repeated string write_forwarded_storage = 5;
}

message Request {
  // Id is the uuid associated with each request
  string id = 1;

  // If set, the name given to the replication secondary where this request
  // originated
  string ReplicationCluster = 2;

  // Operation is the requested operation type
  string operation = 3;

  // Path is the part of the request path not consumed by the
  // routing. As an example, if the original request path is "prod/aws/foo"
  // and the AWS logical backend is mounted at "prod/aws/", then the
  // final path is "foo" since the mount prefix is trimmed.
  string path = 4;

  // Request data is a JSON object that must have keys with string type.
  string data = 5;

  // Secret will be non-nil only for Revoke and Renew operations
  // to represent the secret that was returned prior.
  Secret secret = 6;

  // Auth will be non-nil only for Renew operations
  // to represent the auth that was returned prior.
  Auth auth = 7;

  // Headers will contain the http headers from the request. This value will
  // be used in the audit broker to ensure we are auditing only the allowed
  // headers.
  map<string, Header> headers = 8;

  // ClientToken is provided to the core so that the identity
  // can be verified and ACLs applied. This value is passed
  // through to the logical backends but after being salted and
  // hashed.
  string client_token = 9;

  // ClientTokenAccessor is provided to the core so that the it can get
  // logged as part of request audit logging.
  string client_token_accessor = 10;

  // DisplayName is provided to the logical backend to help associate
  // dynamic secrets with the source entity. This is not a sensitive
  // name, but is useful for operators.
  string display_name = 11;

  // MountPoint is provided so that a logical backend can generate
  // paths relative to itself. The `Path` is effectively the client
  // request path with the MountPoint trimmed off.
  string mount_point = 12;

  // MountType is provided so that a logical backend can make decisions
  // based on the specific mount type (e.g., if a mount type has different
  // aliases, generating different defaults depending on the alias)
  string mount_type = 13;

  // MountAccessor is provided so that identities returned by the authentication
  // backends can be tied to the mount it belongs to.
  string mount_accessor = 14;

  // WrapInfo contains requested response wrapping parameters
  RequestWrapInfo wrap_info = 15;

  // ClientTokenRemainingUses represents the allowed number of uses left on the
  // token supplied
  int64 client_token_remaining_uses = 16;

  // EntityID is the identity of the caller extracted out of the token used
  // to make this request
  string entity_id = 17;

  // PolicyOverride indicates that the requestor wishes to override
  // soft-mandatory Sentinel policies
  bool policy_override = 18;

  // Whether the request is unauthenticated, as in, had no client token
  // attached. Useful in some situations where the client token is not made
  // accessible.
  bool unauthenticated = 19;

  // Connection will be non-nil only for credential providers to
  // inspect the connection information and potentially use it for
  // authentication/protection.
  Connection connection = 20;
}

message Auth {
  LeaseOptions lease_options = 1;

  // InternalData is a JSON object that is stored with the auth struct.
  // This will be sent back during a Renew/Revoke for storing internal data
  // used for those operations.
  string internal_data = 2;

  // DisplayName is a non-security sensitive identifier that is
  // applicable to this Auth. It is used for logging and prefixing
  // of dynamic secrets. For example, DisplayName may be "armon" for
  // the github credential backend. If the client token is used to
  // generate a SQL credential, the user may be "github-armon-uuid".
  // This is to help identify the source without using audit tables.
  string display_name = 3;

  // Policies is the list of policies that the authenticated user
  // is associated with.
  repeated string policies = 4;

  // Metadata is used to attach arbitrary string-type metadata to
  // an authenticated user. This metadata will be outputted into the
  // audit log.
  map<string, string> metadata = 5;

  // ClientToken is the token that is generated for the authentication.
  // This will be filled in by Vault core when an auth structure is
  // returned. Setting this manually will have no effect.
  string client_token = 6;

  // Accessor is the identifier for the ClientToken. This can be used
  // to perform management functionalities (especially revocation) when
  // ClientToken in the audit logs are obfuscated. Accessor can be used
  // to revoke a ClientToken and to lookup the capabilities of the ClientToken,
  // both without actually knowing the ClientToken.
  string accessor = 7;

  // Period indicates that the token generated using this Auth object
  // should never expire. The token should be renewed within the duration
  // specified by this period.
  int64 period = 8;

  // Number of allowed uses of the issued token
  int64 num_uses = 9;

  // EntityID is the identifier of the entity in identity store to which the
  // identity of the authenticating client belongs to.
  string entity_id = 10;

  // Alias is the information about the authenticated client returned by
  // the auth backend
  logical.Alias alias = 11;

  // GroupAliases are the informational mappings of external groups which an
  // authenticated user belongs to. This is used to check if there are
  // mappings groups for the group aliases in identity store. For all the
  // matching groups, the entity ID of the user will be added.
  repeated logical.Alias group_aliases = 12;

  // If set, restricts usage of the certificates to client IPs falling within
  // the range of the specified CIDR(s).
  repeated string bound_cidrs = 13;

  // TokenPolicies and IdentityPolicies break down the list in Policies to
  // help determine where a policy was sourced
  repeated string token_policies = 14;
  repeated string identity_policies = 15;

  // Explicit maximum lifetime for the token. Unlike normal TTLs, the maximum
  // TTL is a hard limit and cannot be exceeded, also counts for periodic tokens.
  int64 explicit_max_ttl = 16;

  // TokenType is the type of token being requested
  uint32 token_type = 17;

  // Whether the default policy should be added automatically by core
  bool no_default_policy = 18;
}

message TokenEntry {
  string id = 1;
  string accessor = 2;
  string parent = 3;
  repeated string policies = 4;
  string path = 5;
  map<string, string> meta = 6;
  string display_name = 7;
  int64 num_uses = 8;
  int64 creation_time = 9;
  int64 ttl = 10;
  int64 explicit_max_ttl = 11;
  string role = 12;
  int64 period = 13;
  string entity_id = 14;
  repeated string bound_cidrs = 15;
  string namespace_id = 16;
  string cubbyhole_id = 17;
  uint32 type = 18;
  map<string, string> internal_meta = 19;
  string inline_policy = 20;
  bool no_identity_policies = 21;
  string external_id = 22;
}

message LeaseOptions {
  int64 TTL = 1;

  bool renewable = 2;

  int64 increment = 3;

  google.protobuf.Timestamp issue_time = 4;

  int64 MaxTTL = 5;
}

message Secret {
  LeaseOptions lease_options = 1;

  // InternalData is a JSON object that is stored with the secret.
  // This will be sent back during a Renew/Revoke for storing internal data
  // used for those operations.
  string internal_data = 2;

  // LeaseID is the ID returned to the user to manage this secret.
  // This is generated by Vault core. Any set value will be ignored.
  // For requests, this will always be blank.
  string lease_id = 3;
}

message Response {
  // Secret, if not nil, denotes that this response represents a secret.
  Secret secret = 1;

  // Auth, if not nil, contains the authentication information for
  // this response. This is only checked and means something for
  // credential backends.
  Auth auth = 2;

  // Response data is a JSON object that must have string keys. For
  // secrets, this data is sent down to the user as-is. To store internal
  // data that you don't want the user to see, store it in
  // Secret.InternalData.
  string data = 3;

  // Redirect is an HTTP URL to redirect to for further authentication.
  // This is only valid for credential backends. This will be blanked
  // for any logical backend and ignored.
  string redirect = 4;

  // Warnings allow operations or backends to return warnings in response
  // to user actions without failing the action outright.
  repeated string warnings = 5;

  // Information for wrapping the response in a cubbyhole
  ResponseWrapInfo wrap_info = 6;

  // Headers will contain the http headers from the response. This value will
  // be used in the audit broker to ensure we are auditing only the allowed
  // headers.
  map<string, Header> headers = 7;
}

message ResponseWrapInfo {
  // Setting to non-zero specifies that the response should be wrapped.
  // Specifies the desired TTL of the wrapping token.
  int64 TTL = 1;

  // The token containing the wrapped response
  string token = 2;

  // The token accessor for the wrapped response token
  string accessor = 3;

  // The creation time. This can be used with the TTL to figure out an
  // expected expiration.
  google.protobuf.Timestamp creation_time = 4;

  // If the contained response is the output of a token creation call, the
  // created token's accessor will be accessible here
  string wrapped_accessor = 5;

  // WrappedEntityID is the entity identifier of the caller who initiated the
  // wrapping request
  string wrapped_entity_id = 6;

  // The format to use. This doesn't get returned, it's only internal.
  string format = 7;

  // CreationPath is the original request path that was used to create
  // the wrapped response.
  string creation_path = 8;

  // Controls seal wrapping behavior downstream for specific use cases
  bool seal_wrap = 9;
}

message RequestWrapInfo {
  // Setting to non-zero specifies that the response should be wrapped.
  // Specifies the desired TTL of the wrapping token.
  int64 TTL = 1;

  // The format to use for the wrapped response; if not specified it's a bare
  // token
  string format = 2;

  // A flag to conforming backends that data for a given request should be
  // seal wrapped
  bool seal_wrap = 3;
}

// HandleRequestArgs is the args for HandleRequest method.
message HandleRequestArgs {
  uint32 storage_id = 1;
  Request request = 2;
}

// HandleRequestReply is the reply for HandleRequest method.
message HandleRequestReply {
  Response response = 1;
  ProtoError err = 2;
}

// InitializeArgs is the args for Initialize method.
message InitializeArgs {}

// InitializeReply is the reply for Initialize method.
message InitializeReply {
  ProtoError err = 1;
}

// SpecialPathsReply is the reply for SpecialPaths method.
message SpecialPathsReply {
  Paths paths = 1;
}

// HandleExistenceCheckArgs is the args for HandleExistenceCheck method.
message HandleExistenceCheckArgs {
  uint32 storage_id = 1;
  Request request = 2;
}

// HandleExistenceCheckReply is the reply for HandleExistenceCheck method.
message HandleExistenceCheckReply {
  bool check_found = 1;
  bool exists = 2;
  ProtoError err = 3;
}

// SetupArgs is the args for Setup method.
message SetupArgs {
  uint32 broker_id = 1;
  map<string, string> Config = 2;
  string backendUUID = 3;
}

// SetupReply is the reply for Setup method.
message SetupReply {
  string err = 1;
}

// TypeReply is the reply for the Type method.
message TypeReply {
  uint32 type = 1;
}

message InvalidateKeyArgs {
  string key = 1;
}

// Backend is the interface that plugins must satisfy. The plugin should
// implement the server for this service. Requests will first run the
// HandleExistenceCheck rpc then run the HandleRequests rpc.
service Backend {
  // HandleRequest is used to handle a request and generate a response.
  // The plugins must check the operation type and handle appropriately.
  rpc HandleRequest(HandleRequestArgs) returns (HandleRequestReply);

  // SpecialPaths is a list of paths that are special in some way.
  // See PathType for the types of special paths. The key is the type
  // of the special path, and the value is a list of paths for this type.
  // This is not a regular expression but is an exact match. If the path
  // ends in '*' then it is a prefix-based match. The '*' can only appear
  // at the end.
  rpc SpecialPaths(Empty) returns (SpecialPathsReply);

  // HandleExistenceCheck is used to handle a request and generate a response
  // indicating whether the given path exists or not; this is used to
  // understand whether the request must have a Create or Update capability
  // ACL applied. The first bool indicates whether an existence check
  // function was found for the backend; the second indicates whether, if an
  // existence check function was found, the item exists or not.
  rpc HandleExistenceCheck(HandleExistenceCheckArgs) returns (HandleExistenceCheckReply);

  // Cleanup is invoked during an unmount of a backend to allow it to
  // handle any cleanup like connection closing or releasing of file handles.
  // Cleanup is called right before Vault closes the plugin process.
  rpc Cleanup(Empty) returns (Empty);

  // InvalidateKey may be invoked when an object is modified that belongs
  // to the backend. The backend can use this to clear any caches or reset
  // internal state as needed.
  rpc InvalidateKey(InvalidateKeyArgs) returns (Empty);

  // Setup is used to set up the backend based on the provided backend
  // configuration. The plugin's setup implementation should use the provided
  // broker_id to create a connection back to Vault for use with the Storage
  // and SystemView clients.
  rpc Setup(SetupArgs) returns (SetupReply);

  // Initialize is invoked just after mounting a backend to allow it to
  // handle any initialization tasks that need to be performed.
  rpc Initialize(InitializeArgs) returns (InitializeReply);

  // Type returns the BackendType for the particular backend
  rpc Type(Empty) returns (TypeReply);
}

message StorageEntry {
  string key = 1;
  bytes value = 2;
  bool seal_wrap = 3;
}

message StorageListArgs {
  string prefix = 1;
}

message StorageListReply {
  repeated string keys = 1;
  string err = 2;
}

message StorageGetArgs {
  string key = 1;
}

message StorageGetReply {
  StorageEntry entry = 1;
  string err = 2;
}

message StoragePutArgs {
  StorageEntry entry = 1;
}

message StoragePutReply {
  string err = 1;
}

message StorageDeleteArgs {
  string key = 1;
}

message StorageDeleteReply {
  string err = 1;
}

// Storage is the way that plugins are able read/write data. Plugins should
// implement the client for this service.
service Storage {
  rpc List(StorageListArgs) returns (StorageListReply);
  rpc Get(StorageGetArgs) returns (StorageGetReply);
  rpc Put(StoragePutArgs) returns (StoragePutReply);
  rpc Delete(StorageDeleteArgs) returns (StorageDeleteReply);
}

message TTLReply {
  int64 TTL = 1;
}

message TaintedReply {
  bool tainted = 1;
}

message CachingDisabledReply {
  bool disabled = 1;
}

message ReplicationStateReply {
  int32 state = 1;
}

message ResponseWrapDataArgs {
  string data = 1;
  int64 TTL = 2;
  bool JWT = 3;
}

message ResponseWrapDataReply {
  ResponseWrapInfo wrap_info = 1;
  string err = 2;
}

message MlockEnabledReply {
  bool enabled = 1;
}

message LocalMountReply {
  bool local = 1;
}

message EntityInfoArgs {
  string entity_id = 1;
}

message EntityInfoReply {
  logical.Entity entity = 1;
  string err = 2;
}

message GroupsForEntityReply {
  repeated logical.Group groups = 1;
  string err = 2;
}

message PluginEnvReply {
  logical.PluginEnvironment plugin_environment = 1;
  string err = 2;
}

message GeneratePasswordFromPolicyRequest {
  string policy_name = 1;
}

message GeneratePasswordFromPolicyReply {
  string password = 1;
}

message ClusterInfoReply {
  string cluster_name = 1;
  string cluster_id = 2;
  string err = 3;
}

// SystemView exposes system configuration information in a safe way for plugins
// to consume. Plugins should implement the client for this service.
service SystemView {
  // DefaultLeaseTTL returns the default lease TTL set in Vault configuration
  rpc DefaultLeaseTTL(Empty) returns (TTLReply);

  // MaxLeaseTTL returns the max lease TTL set in Vault configuration; backend
  // authors should take care not to issue credentials that last longer than
  // this value, as Vault will revoke them
  rpc MaxLeaseTTL(Empty) returns (TTLReply);

  // Tainted, returns true if the mount is tainted. A mount is tainted if it is in the
  // process of being unmounted. This should only be used in special
  // circumstances; a primary use-case is as a guard in revocation functions.
  // If revocation of a backend's leases fails it can keep the unmounting
  // process from being successful. If the reason for this failure is not
  // relevant when the mount is tainted (for instance, saving a CRL to disk
  // when the stored CRL will be removed during the unmounting process
  // anyways), we can ignore the errors to allow unmounting to complete.
  rpc Tainted(Empty) returns (TaintedReply);

  // CachingDisabled returns true if caching is disabled. If true, no caches
  // should be used, despite known slowdowns.
  rpc CachingDisabled(Empty) returns (CachingDisabledReply);

  // ReplicationState indicates the state of cluster replication
  rpc ReplicationState(Empty) returns (ReplicationStateReply);

  // ResponseWrapData wraps the given data in a cubbyhole and returns the
  // token used to unwrap.
  rpc ResponseWrapData(ResponseWrapDataArgs) returns (ResponseWrapDataReply);

  // MlockEnabled returns the configuration setting for enabling mlock on
  // plugins.
  rpc MlockEnabled(Empty) returns (MlockEnabledReply);

  // LocalMount, when run from a system view attached to a request, indicates
  // whether the request is affecting a local mount or not
  rpc LocalMount(Empty) returns (LocalMountReply);

  // EntityInfo returns the basic entity information for the given entity id
  rpc EntityInfo(EntityInfoArgs) returns (EntityInfoReply);

  // PluginEnv returns Vault environment information used by plugins
  rpc PluginEnv(Empty) returns (PluginEnvReply);

  // GroupsForEntity returns the group membership information for the given
  // entity id
  rpc GroupsForEntity(EntityInfoArgs) returns (GroupsForEntityReply);

  // GeneratePasswordFromPolicy generates a password from an existing password policy
  rpc GeneratePasswordFromPolicy(GeneratePasswordFromPolicyRequest) returns (GeneratePasswordFromPolicyReply);

  // ClusterInfo returns the ClusterID information; may be reused if ClusterName is also exposed.
  rpc ClusterInfo(Empty) returns (ClusterInfoReply);
}

message Connection {
  // RemoteAddr is the network address that sent the request.
  string remote_addr = 1;

  // RemotePort is the network port that sent the request.
  int32 remote_port = 3;

  // ConnectionState is the marshalled tls.ConnectionState from the original
  // request
  ConnectionState connection_state = 2;
}

message ConnectionState {
  uint32 version = 1;
  bool handshake_complete = 2;
  bool did_resume = 3;
  uint32 cipher_suite = 4;
  string negotiated_protocol = 5;
  bool negotiated_protocol_is_mutual = 6;
  string server_name = 7;
  CertificateChain peer_certificates = 8;

  repeated CertificateChain verified_chains = 9;
  repeated bytes signed_certificate_timestamps = 10;

  bytes ocsp_response = 11;
  bytes tls_unique = 12;
}

message Certificate {
  bytes asn1_data = 1;
}

message CertificateChain {
  repeated Certificate certificates = 1;
}

message SendEventRequest {
  string event_type = 1;
  logical.EventData event = 2;
}

service Events {
  rpc SendEvent(SendEventRequest) returns (Empty);
}
