blob: e469d0db986316f527baa95d798820ff9c915c68 [file] [log] [blame]
Serge Bazanski32d73482021-02-01 23:49:17 +01001// Copyright 2020 The Monogon Project Authors.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17syntax = "proto3";
18package metropolis.proto.api;
19option go_package = "source.monogon.dev/metropolis/proto/api";
20
21// Authentication, authorization and accounting.
22service AAA {
23 // Escrow is an endpoint used to retrieve short-lived access credentials to
24 // the cluster. These short-lived access credentials are x509 certificates
25 // that can then be used to directly authenticate to other RPC methods
26 // exposed by Metropolis. This short-lived certificate may or may not be
27 // fully self-standing cryptographically - this depends on the policy and
28 // other configuration of the system. The returned short-lived certificate
29 // may even be used as proofs within next Escrow calls in the case of more
30 // complex flows.
31 //
32 // The client in this RPC is an end-user of the cluster, be it a human or
33 // automated process that runs outside of a Metropolis cluster.
34 //
35 // To retrieve this short-lived certificate, the client must provide
36 // different kind of proofs to the server. Upon connecting and receiving
37 // the initial message from the client, the server will send a list of
38 // proof requests, detailing proofs that the client must need to fulfill to
39 // retrieve the requested credentials. Which proofs are requested depends
40 // on the configuration of the client. The way to fulfill these proofs
41 // depend on their kind, with some being provided in-band (eg. access
42 // credentials, U2F codes), some being provided out of band (eg. an RPC
43 // channel opened from a given IP address or with a given existing TLS
44 // certificate), and some dependent on external systems (eg. SSO).
45 //
46 // If the requested identity within the first EscrowFromClient is not
47 // defined, the server may:
48 //
49 // - Abort the connection immediately with an error about an unknown
50 // identity being requested.
51 // - Continue processing the Escrow RPC as if the identity existed, and
52 // either gather enough other proofs to be able to trust the client
53 // enough to abort it saying that the identity is unknown; or continue
54 // and pretend that the other proofs submitted by the client are
55 // invalid.
56 //
57 // Once the proofs are fulfilled by the client, the server will send an
58 // x509 PEM-encoded certificate that the client can use in subsequent
59 // calls to other Metropolis services.
60 //
61 // TODO(q3k): SPIFFE compatibility for short-lived certificates?
62 //
63 // This escrow flow can thus be used to implement several typical flows
64 // used for 'logging in' cluster users:
65 //
66 // Example: Username and password login
67 //
68 // This shows the simplest possible message flow for a simple interactive
69 // password authentication.
70 //
71 // Client Server
72 // | |
73 // | .---------------------------. |
74 // |----------| parameters < |-------->>>|
75 // | | requested_identity_name: | |
76 // | | "janedoe" | |
77 // | | public_key: | |
78 // | | "DEADBEEF..." | |
79 // | | > | |
80 // | '---------------------------' |
81 // | |
82 // | .---------------------------. |
83 // |<<<-------| needed < |-----------|
84 // | | kind: PLAINTEXT_PASSWORD | |
85 // | | > | |
86 // | '---------------------------' |
87 // | |
88 // | .---------------------------. |
89 // |----------| proofs < |-------->>>|
90 // | | plaintext_password: ".." | |
91 // | | > | |
92 // | '---------------------------' |
93 // | |
94 // | .---------------------------. |
95 // |<<<-------| fulfilled < |-----------|
96 // | | kind: PLAINTEXT_PASSWORD | |
97 // | | > | |
98 // | | emitted_certificate: | |
99 // | | "DEADFOOD..." | |
100 // | '---------------------------' |
101 // | |
102 // |<<<---------------- close ----------------------- |
103 // | |
104 //
105 // Example: multi-phase OIDC with hardware assessment (simplified):
106 //
107 // This first requests a certificate that's valid for one day, and requires
108 // the interactive use of a browser. Then, shorter-term certificates
109 // (actually used to perform RPCs) are requested on demand, their lifetime
110 // corresponding to the access tokens emitted by the IdP, but requiring
111 // no interactive browser access or reconfirmations by the user.
112 //
113 // Client Server
114 // | |
115 // | .--------------------------------------. |
116 // |<<<--| Exchange OIDC login proof and TPM |-->>>|
117 // | | assessment for week-long certificate,| |<--> IdP
118 // | | retrieve 1-day long certificate | |<--> User
119 // | | binding user to a refresh token on | | Browser
120 // | | the server. | |
121 // | '--------------------------------------' |
122 // | |
123 // | .--------------------------------------. | -.
124 // |<<<--| Exchange earlier certificate and TPM |-->>>|<--> IdP
125 // | | hardware assessment for 10-minute | | |
126 // | | long self-standing cryptographic | | > Repeats as
127 // | | certificate used to access other | | | long as
128 // | | services | | \ possible.
129 // | '--------------------------------------' | -'
130 //
131 // FAQ: How does this relate to access via web browsers?
132 //
133 // This flow is explicitly designed to be non dependent on web browers for
134 // security reasons. Due to these requirements, we cannot port this flow to
135 // always also work on browsers. Instead, we focus on the best that a
136 // standalone application on the client side can give us, eg. being able to
137 // use TLS client certificates, perform hardware attestation, and even talk
138 // to HSMs.
139 //
140 // In addition to this gRPC Escrow flow, an alternative flow geared
141 // especially towards web browser access (and eg. bearer token
142 // authentication and OAuth/OpenIDC integration) will be developed for
143 // users whose cluster policy allows for browser access. Both, however,
144 // will lead to retrieving identities from with the same namespace of
145 // entities.
146 //
147 rpc Escrow(stream EscrowFromClient) returns (stream EscrowFromServer);
148}
149
150message EscrowFromClient {
151 // Parameters used for the entirety of the escrow flow. These must be set
152 // only during the first EscrowFromClient message, and are ignored in
153 // further messages.
154 message Parameters {
155 // The requested identity name. This is currently opaque and not defined,
156 // but corresponds to the future 'Entity' system that Metropolis will
157 // implement. Required.
158 string requested_identity_name = 1;
159
160 // Public key for which the short-lived certificate will be issued.
161 // Currently, this must be an ed25519 public key's raw bytes (32
162 // bytes). In the future, other x509 signature algorithms might be
163 // supported.
164 // This key does not have to be the same key as the one that is part of
165 // the presented certificate during the Escrow RPC (if any). However,
166 // some proofs might have stricter requirements.
167 bytes public_key = 2;
168 }
169 Parameters parameters = 1;
170
171 // Proofs. These should only be submitted by the client after the server
172 // requests them, but if they are submitted within the first
173 // EscrowFromClientMessage they will be interpreted too. The problem with
174 // ahead of time proofs is that different a proof request from the server
175 // might parametrize the request in a way that would elicit a different
176 // answer from the client, so care must be taken to ensure that the
177 // requests from the server are verified against the assumption that the
178 // client makes (if any). Ideally, the client should be fully reactive to
179 // requested proofs, and not hardcode any behaviour.
180 message Proofs {
181 // Plaintext password in response to KIND_PLAINTEXT_PASSWORD proof
182 // request.
183 string plaintext_password = 1;
184 }
185 Proofs proofs = 2;
186}
187
188message EscrowFromServer {
189 // A proof requested from the server. Within an Escrow RPC, proofs can be
190 // either 'needed' or 'fulfilled'. Each proof has a kind, and kinds within
191 // all proof requests (either needed or fulfilled) are unique.
192 message ProofRequest {
193 enum Kind {
194 KIND_INVALID = 0;
195 // The client needs to present a long-lived 'refresh' certificate.
196 // If this is in `needed`, it means the client did not present a
197 // certificate and will need to abort this RPC and connect with one
198 // presented.
199 // If the client presents an invalid certificate, the Escrow RPC
200 // will fail.
201 KIND_REFRESH_CERTIFICATE = 1;
202 // The client needs to present a static, plaintext password/token.
203 // This can be fulfilled by setting
204 // EscrowFromClient.proofs.plaintext_password.
205 // If the client presents an invalid password, the Escrow RPC will
206 // fail.
207 KIND_PLAINTEXT_PASSWORD = 2;
208
209 // Future possibilities:
210 // // One-or-two-sided hardware assessment via TPM.
211 // KIND_HARDWARE_ASSESMENT_EXCHANGE = ...
212 // // Making the client proove that the certificate is stored on
213 // // some secure element.
214 // KIND_PRIVATE_KEY_IN_SECURE_ELEMENT = ...
215 // // Making the client go through an OIDC login flow, with the
216 // // server possibly storing the resulting refresh/access tokens.
217 // KIND_OIDC_FLOW_COMPLETION = ...
218 };
219 Kind kind = 1;
220 }
221 // Proofs that the server requests from the client which the client has not
222 // yet fulfilled. Within the lifecycle of the Escrow RPC, the needed proofs
223 // will only move from needed to fulfilled as the client submits more
224 // proofs.
225 repeated ProofRequest needed = 1;
226 // Proofs that the server accepted from the client.
227 repeated ProofRequest fulfilled = 2;
228
229 // If all proof requests are fulfilled, the bytes of the emitted PEM
230 // certificate.
231 bytes emitted_certificate = 3;
232}
233
234// Protobuf-encoded data that is part of certificates emitted by the
235// Metropolis CA. Encoded as protobuf and inserted into a Subject Alternative
236// Name of type otherName with type-id:
237//
238// 2.25.205720787499610521842135044124912906832.1.1
239//
240// TODO(q3k): register something under 1.3.6.1.4.1 and alloacte some OID within
241// that instead of relying on UUIDs within 2.25?
242message CertificateSAN {
243 // Validity descrises how consumers of this certificate should treat the
244 // information contained within it. Currently there's two kinds of
245 // validities, the difference between them being whether or not the
246 // certificate needs to actively be checked for revocation or not.
247 enum Validity {
248 VALIDITY_INVALID = 0;
249 // Certificate must only be used by components that can verify with
250 // Metropolis that it hasn't been revoked. The method (OCSP, CRL)
251 // intentionally left blank for now.
252 VALIDITY_ONLINE = 1;
253 // Certificate can be trusted on cryptographic basis alone as long as
254 // it hasn't expired, without consulting revocation system.
255 VALIDITY_OFFLINE = 2;
256 }
257 Validity validity = 1;
258
259 // Assertions are facts stated about the bearer of this certificate by the
260 // CA that emitted it - in this case, the Metropolis cluster that emitted
261 // it. Each assertion details exactly one fact of one kind, and there can
262 // be multiple assertions of any given kind.
263 message Assertion {
264 // IdentityConfirmed asserts that the emitter of this certificate has
265 // received all the required proofs at the time of issuance to confirm
266 // that the bearer of this certificate is the entity described by the
267 // identity name.
268 message IdentityConfirmed {
269 string name = 1;
270 };
271 // MetropolisRPCAllowed means that that connections established to
272 // Metropolis RPC endpoints will proceed. If given, IdentityConfirmed
273 // must also be given.
274 message MetropolisRPCAllowed {
275 // Future possibilities: scoping to only some (low privilege) RPC
276 // methods, ...
277 };
278 oneof kind {
279 IdentityConfirmed identity_confirmed = 1;
280 MetropolisRPCAllowed metropolis_rpc_allowed = 2;
281 // Future possibilties:
282 // OIDCIdentityConfirmed ...
283 // TPMColocationConfirmed ...
284 // SourceAddressConfirmed ...
285 // ReportedClientConfiguration ...
286 };
287 }
288 repeated Assertion assertions = 2;
289}