blob: ba20ceeec0236ce204bdabfdb667d85cc83bd28c [file] [log] [blame]
syntax = "proto3";
package metropolis.proto.api;
option go_package = "source.monogon.dev/metropolis/proto/api";
import "metropolis/proto/common/common.proto";
import "metropolis/proto/ext/authorization.proto";
// Management service available to Cluster Managers, allowing operational work
// to be performed on the cluster (eg. adding nodes, retrieving information
// about a running cluster, etc.).
service Management {
// GetRegisterTicket retrieves the current RegisterTicket which is required
// for new nodes to register into the cluster. Presenting this ticket on
// registration does not automatically grant access to arbitrary node
// registration. Instead, it is used to guard the API surface of the
// Register RPC from potential denial of service attacks, and can be
// regenerated at any time in case it leaks.
rpc GetRegisterTicket(GetRegisterTicketRequest) returns (GetRegisterTicketResponse) {
option (metropolis.proto.ext.authorization) = {
need: PERMISSION_GET_REGISTER_TICKET
};
}
// GetClusterInfo retrieves publicly available summary information about
// this cluster, notably data required for nodes to register into a cluster
// or join it (other than the Register Ticket, which is gated by an
// additional permission).
rpc GetClusterInfo(GetClusterInfoRequest) returns (GetClusterInfoResponse) {
option (metropolis.proto.ext.authorization) = {
need: PERMISSION_READ_CLUSTER_STATUS
};
}
// GetNodes retrieves information about nodes in the cluster. Currently,
// it returns all available data about all nodes.
rpc GetNodes(GetNodesRequest) returns (stream Node) {
option (metropolis.proto.ext.authorization) = {
need: PERMISSION_READ_CLUSTER_STATUS
};
}
// ApproveNode progresses a node's registration process by changing its state
// in the cluster from NEW to STANDBY, if not yet STANDBY. This is required
// for the node to fully become part of the cluster (ie. have an UP state),
// and is required to be called by a manager manually.
//
// Managers can find out what nodes require approval by performing
// a GetNodes call and filtering for nodes in the NEW state. This call is
// idempotent and can be executed multiple times, and is a no-op if the node
// is already in the STANDBY or even UP states.
//
// In the future, approval process will be governed by cluster policy, but
// currently any node can be approved by a manager, and the manager is
// responsible for performing an out-of-band attestation of the node being/
// approved (eg. by verifying that the node that is being approved has the
// same public key as what the registering node displays in its startup
// logs).
rpc ApproveNode(ApproveNodeRequest) returns (ApproveNodeResponse) {
option (metropolis.proto.ext.authorization) = {
need: PERMISSION_APPROVE_NODE
};
}
// UpdateNodeRoles updates a single node's roles.
rpc UpdateNodeRoles(UpdateNodeRolesRequest) returns (UpdateNodeRolesResponse) {
option (metropolis.proto.ext.authorization) = {
need: PERMISSION_UPDATE_NODE_ROLES
};
}
}
message GetRegisterTicketRequest {
}
message GetRegisterTicketResponse {
// Opaque bytes that comprise the RegisterTicket.
bytes ticket = 1;
}
message GetClusterInfoRequest {
}
message GetClusterInfoResponse {
// cluster_directory contains information about individual nodes in the
// cluster that can be used to dial the cluster's services.
metropolis.proto.common.ClusterDirectory cluster_directory = 1;
// ca_certificate is the x509 DER encoded CA certificate of the cluster.
bytes ca_certificate = 2;
}
message GetNodesRequest {
// filter is a CEL expression used to limit the count of GetNodes results.
// Each processed node protobuf message is exposed to the filter as
// "node" variable, while related state and health enum constants are
// anchored in the root namespace, eg. NODE_STATE_UP, or HEARTBEAT_TIMEOUT.
// A node is returned each time the expression is evaluated as true. If
// empty, all nodes are returned.
string filter = 1;
}
// Node in a Metropolis cluster, streamed by Management.GetNodes. For each node
// in the cluster, this message will be emitted and will contain information
// about that node.
//
// The fields contained are node fields that PERMISSION_READ_CLUSTER_STATUS
// allows access to, ie. 'non-private' fields, ones that might be internal to
// the cluster and possibly considered sensitive information about the
// infrastructure, but whose knowledge does not allow to escalate privileges
// within the cluster.
message Node {
// Raw Ed25519 public key of this node, which can be used to generate
// the node's ID. This is always set.
bytes pubkey = 1;
// State of the node from the point of view of the cluster. This is
// always set.
metropolis.proto.common.NodeState state = 2;
// Last reported status by the Node, absent if a node hasn't yet reported
// its status.
metropolis.proto.common.NodeStatus status = 3;
// Roles assigned by the cluster. This is always set.
metropolis.proto.common.NodeRoles roles = 4;
// Health describes node's health as seen from the cluster perspective.
enum Health {
INVALID = 0;
// UNKNOWN is used whenever there were no heartbeats received from a
// given node AND too little time has passed since last Curator leader
// election to know whether the node is actually timing out. UNKNOWN
// is also returned for nodes which NodeState does not equal
// NODE_STATE_UP.
UNKNOWN = 1;
// HEALTHY describes nodes that have sent a heartbeat recently.
HEALTHY = 2;
// HEARTBEAT_TIMEOUT describes nodes that have not sent a heartbeat in
// the interval specified by curator.HeartbeatTimeout.
HEARTBEAT_TIMEOUT = 3;
}
Health health = 5;
// heartbeat_timestamp is the duration since the last of the node's
// heartbeats was received, expressed in nanoseconds. It equals zero if no
// heartbeats were received.
int64 heartbeat_timestamp = 6;
}
message ApproveNodeRequest {
// Raw public key of the node being approved, has to correspond to a node
// currently in the cluster.
bytes pubkey = 1;
}
message ApproveNodeResponse {
}
// UpdateNodeRolesRequest updates roles of a single node matching pubkey. All
// role fields are optional, and no change will result if they're either unset
// or if their value matches existing state.
message UpdateNodeRolesRequest {
// pubkey is the Ed25519 public key of this node, which can be used to
// generate the node's ID. This is always set.
bytes pubkey = 1;
// kubernetesWorker adjusts the appropriate role when set. Nodes performing
// this role must also be consensus members.
optional bool kubernetesWorker = 2;
optional bool consensusMember = 3;
}
message UpdateNodeRolesResponse {
}