blob: a5fd47da7b1e3354eaf4ac29cdc58b6d723e4f88 [file] [log] [blame]
Serge Bazanski6bd41592021-08-23 13:18:37 +02001syntax = "proto3";
2package metropolis.proto.api;
3option go_package = "source.monogon.dev/metropolis/proto/api";
4
Mateusz Zalega944cb532022-06-20 16:54:17 +02005import "google/protobuf/duration.proto";
6
Serge Bazanskibc671d02021-10-05 17:53:32 +02007import "metropolis/proto/common/common.proto";
Serge Bazanski9ffa1f92021-09-01 15:42:23 +02008import "metropolis/proto/ext/authorization.proto";
9
Serge Bazanski56114472021-10-11 14:47:54 +020010// Management service available to Cluster Managers, allowing operational work
11// to be performed on the cluster (eg. adding nodes, retrieving information
12// about a running cluster, etc.).
Serge Bazanski6bd41592021-08-23 13:18:37 +020013service Management {
14 // GetRegisterTicket retrieves the current RegisterTicket which is required
15 // for new nodes to register into the cluster. Presenting this ticket on
16 // registration does not automatically grant access to arbitrary node
17 // registration. Instead, it is used to guard the API surface of the
18 // Register RPC from potential denial of service attacks, and can be
19 // regenerated at any time in case it leaks.
Serge Bazanski9ffa1f92021-09-01 15:42:23 +020020 rpc GetRegisterTicket(GetRegisterTicketRequest) returns (GetRegisterTicketResponse) {
21 option (metropolis.proto.ext.authorization) = {
22 need: PERMISSION_GET_REGISTER_TICKET
23 };
24 }
Serge Bazanski56114472021-10-11 14:47:54 +020025
Serge Bazanskibc671d02021-10-05 17:53:32 +020026 // GetClusterInfo retrieves publicly available summary information about
27 // this cluster, notably data required for nodes to register into a cluster
28 // or join it (other than the Register Ticket, which is gated by an
29 // additional permission).
30 rpc GetClusterInfo(GetClusterInfoRequest) returns (GetClusterInfoResponse) {
31 option (metropolis.proto.ext.authorization) = {
32 need: PERMISSION_READ_CLUSTER_STATUS
33 };
34 }
Serge Bazanski56114472021-10-11 14:47:54 +020035
36 // GetNodes retrieves information about nodes in the cluster. Currently,
37 // it returns all available data about all nodes.
38 rpc GetNodes(GetNodesRequest) returns (stream Node) {
39 option (metropolis.proto.ext.authorization) = {
40 need: PERMISSION_READ_CLUSTER_STATUS
41 };
42 }
Serge Bazanski1612d4b2021-11-12 13:54:15 +010043
44 // ApproveNode progresses a node's registration process by changing its state
45 // in the cluster from NEW to STANDBY, if not yet STANDBY. This is required
46 // for the node to fully become part of the cluster (ie. have an UP state),
47 // and is required to be called by a manager manually.
48 //
49 // Managers can find out what nodes require approval by performing
50 // a GetNodes call and filtering for nodes in the NEW state. This call is
51 // idempotent and can be executed multiple times, and is a no-op if the node
52 // is already in the STANDBY or even UP states.
53 //
54 // In the future, approval process will be governed by cluster policy, but
55 // currently any node can be approved by a manager, and the manager is
56 // responsible for performing an out-of-band attestation of the node being/
57 // approved (eg. by verifying that the node that is being approved has the
58 // same public key as what the registering node displays in its startup
59 // logs).
60 rpc ApproveNode(ApproveNodeRequest) returns (ApproveNodeResponse) {
61 option (metropolis.proto.ext.authorization) = {
62 need: PERMISSION_APPROVE_NODE
63 };
64 }
Mateusz Zalegabb2edbe2022-06-08 11:57:09 +020065
66 // UpdateNodeRoles updates a single node's roles.
67 rpc UpdateNodeRoles(UpdateNodeRolesRequest) returns (UpdateNodeRolesResponse) {
68 option (metropolis.proto.ext.authorization) = {
69 need: PERMISSION_UPDATE_NODE_ROLES
70 };
71 }
Serge Bazanski6bd41592021-08-23 13:18:37 +020072}
73
74message GetRegisterTicketRequest {
75}
76
77message GetRegisterTicketResponse {
78 // Opaque bytes that comprise the RegisterTicket.
79 bytes ticket = 1;
Serge Bazanski2893e982021-09-09 13:06:16 +020080}
Serge Bazanskibc671d02021-10-05 17:53:32 +020081
82message GetClusterInfoRequest {
83}
84
85message GetClusterInfoResponse {
86 // cluster_directory contains information about individual nodes in the
87 // cluster that can be used to dial the cluster's services.
88 metropolis.proto.common.ClusterDirectory cluster_directory = 1;
Serge Bazanski2f58ac02021-10-05 11:47:20 +020089
Serge Bazanskifbd38e22021-10-08 14:41:16 +020090 // ca_certificate is the x509 DER encoded CA certificate of the cluster.
91 bytes ca_certificate = 2;
Serge Bazanskibc671d02021-10-05 17:53:32 +020092}
Serge Bazanski56114472021-10-11 14:47:54 +020093
94message GetNodesRequest {
Mateusz Zalega955e46e2022-05-27 18:00:50 +020095 // filter is a CEL expression used to limit the count of GetNodes results.
96 // Each processed node protobuf message is exposed to the filter as
97 // "node" variable, while related state and health enum constants are
98 // anchored in the root namespace, eg. NODE_STATE_UP, or HEARTBEAT_TIMEOUT.
99 // A node is returned each time the expression is evaluated as true. If
100 // empty, all nodes are returned.
101 string filter = 1;
Serge Bazanski56114472021-10-11 14:47:54 +0200102}
103
104// Node in a Metropolis cluster, streamed by Management.GetNodes. For each node
105// in the cluster, this message will be emitted and will contain information
106// about that node.
107//
108// The fields contained are node fields that PERMISSION_READ_CLUSTER_STATUS
109// allows access to, ie. 'non-private' fields, ones that might be internal to
110// the cluster and possibly considered sensitive information about the
111// infrastructure, but whose knowledge does not allow to escalate privileges
112// within the cluster.
113message Node {
114 // Raw Ed25519 public key of this node, which can be used to generate
115 // the node's ID. This is always set.
116 bytes pubkey = 1;
Serge Bazanski30fd1542023-03-29 14:19:02 +0200117 // Node ID calculated from pubkey, ie. 'metropolis-123456'.
118 string id = 7;
Serge Bazanski56114472021-10-11 14:47:54 +0200119 // State of the node from the point of view of the cluster. This is
120 // always set.
121 metropolis.proto.common.NodeState state = 2;
122 // Last reported status by the Node, absent if a node hasn't yet reported
123 // its status.
124 metropolis.proto.common.NodeStatus status = 3;
125 // Roles assigned by the cluster. This is always set.
126 metropolis.proto.common.NodeRoles roles = 4;
Serge Bazanski1612d4b2021-11-12 13:54:15 +0100127
Mateusz Zalega32b19292022-05-17 13:26:55 +0200128 // Health describes node's health as seen from the cluster perspective.
129 enum Health {
130 INVALID = 0;
131 // UNKNOWN is used whenever there were no heartbeats received from a
132 // given node AND too little time has passed since last Curator leader
133 // election to know whether the node is actually timing out. UNKNOWN
134 // is also returned for nodes which NodeState does not equal
135 // NODE_STATE_UP.
136 UNKNOWN = 1;
137 // HEALTHY describes nodes that have sent a heartbeat recently.
138 HEALTHY = 2;
139 // HEARTBEAT_TIMEOUT describes nodes that have not sent a heartbeat in
140 // the interval specified by curator.HeartbeatTimeout.
141 HEARTBEAT_TIMEOUT = 3;
142 }
143 Health health = 5;
Mateusz Zalega2175ec92022-06-13 09:29:09 +0200144 // time_since_heartbeat is the duration since the last of the node's
145 // heartbeats was received, expressed in nanoseconds. It is only valid with
146 // the health status of either HEALTHY or HEARTBEAT_TIMEOUT.
Mateusz Zalega944cb532022-06-20 16:54:17 +0200147 google.protobuf.Duration time_since_heartbeat = 6;
Mateusz Zalega32b19292022-05-17 13:26:55 +0200148}
Serge Bazanski1612d4b2021-11-12 13:54:15 +0100149
150message ApproveNodeRequest {
151 // Raw public key of the node being approved, has to correspond to a node
152 // currently in the cluster.
153 bytes pubkey = 1;
154}
155
156message ApproveNodeResponse {
Mateusz Zalega32b19292022-05-17 13:26:55 +0200157}
Mateusz Zalegabb2edbe2022-06-08 11:57:09 +0200158
159// UpdateNodeRolesRequest updates roles of a single node matching pubkey. All
160// role fields are optional, and no change will result if they're either unset
161// or if their value matches existing state.
162message UpdateNodeRolesRequest {
Mateusz Zalega9c315f12022-08-11 16:31:22 +0200163 // node uniquely identifies the node subject to this request.
164 oneof node {
165 // pubkey is the Ed25519 public key of this node, which can be used to
166 // generate the node's ID.
167 bytes pubkey = 1;
168 // id is the human-readable identifier of the node, based on its public
169 // key.
170 string id = 4;
171 }
Mateusz Zalegabb2edbe2022-06-08 11:57:09 +0200172
Serge Bazanski15f7f632023-03-14 17:17:20 +0100173 // kubernetesController adjusts the appropriate role when set.
Mateusz Zalegabb2edbe2022-06-08 11:57:09 +0200174 optional bool kubernetesWorker = 2;
Serge Bazanski15f7f632023-03-14 17:17:20 +0100175 // kubernetesController adjusts the appropriate role when set. Nodes performing
176 // this role must also be consensus members.
177 optional bool kubernetesController = 5;
Mateusz Zalegabb2edbe2022-06-08 11:57:09 +0200178 optional bool consensusMember = 3;
179}
180
181message UpdateNodeRolesResponse {
182}