go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/common/proto/sidecar/auth.proto (about) 1 // Copyright 2023 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 syntax = "proto3"; 16 17 package luci.sidecar; 18 19 option go_package = "go.chromium.org/luci/common/proto/sidecar"; 20 21 import "google/rpc/status.proto"; 22 23 24 // Auth exposes methods to authenticate user credentials and to make 25 // authorization checks. 26 service Auth { 27 // Authenticate receives metadata of the incoming call and uses it to 28 // authenticate the caller, i.e. it extracts appropriate credentials and 29 // verifies they are valid. 30 // 31 // Optionally checks if the authenticated identity is a member of groups 32 // given by `groups` request field, returning groups the identity is a member 33 // of in `groups` response field (which will be a subset of groups passed in 34 // the request). This is useful for implementing simple broad group-based 35 // authorization checks skipping extra RPCs. For more flexible checks see 36 // IsMember and HasPermission RPCs. 37 // 38 // Returns: 39 // * OK if the server understood the request and performed the 40 // authentication. The outcome (which can include an error if credentials 41 // are invalid) is available as part of AuthenticateResponse. OK is 42 // returned as well if the request doesn't have credentials attached at 43 // all or they were invalid. In that case AuthenticateResponse contains 44 // `anonymous` or `error` outcomes respectively. 45 // * UNAUTHENTICATED if the call to the sidecar server itself failed due to 46 // invalid (corrupted, expired, etc) RPC credentials, i.e. credentials of 47 // the sidecar client itself, not credentials inside AuthenticateRequest. 48 // This response MUST be presented as INTERNAL error to the end user, 49 // since it indicates some internal misconfiguration between the 50 // application server and the sidecar service, unrelated to credentials 51 // sent by the end-user. 52 // * PERMISSION_DENIED if the call to the sidecar server itself is not 53 // allowed. This response MUST also be presented as INTERNAL error to 54 // the end user. 55 // * INTERNAL on transient internal errors that SHOULD be retried. 56 rpc Authenticate(AuthenticateRequest) returns (AuthenticateResponse); 57 58 // IsMember checks if an identity belongs to any of the given groups. 59 // 60 // Returns: 61 // * OK with the outcome of the check (which may be negative) if the check 62 // was performed successfully. 63 // * INVALID_ARGUMENT if the request is malformed. 64 // * UNAUTHENTICATED if the call to the sidecar server failed due to invalid 65 // (corrupted, expired, etc) RPC credentials. This response MUST be 66 // presented as INTERNAL error to the end user, since it indicates some 67 // internal misconfiguration between the application server and the 68 // sidecar service. 69 // * PERMISSION_DENIED if the call to the sidecar server itself is not 70 // allowed. This response MUST also be presented as INTERNAL error to 71 // the end user. 72 // * INTERNAL on transient internal errors that SHOULD be retried. 73 rpc IsMember(IsMemberRequest) returns (IsMemberResponse); 74 75 // HasPermission check if an identity has a permission in a realm. 76 // 77 // Can only check permissions registered when the sidecar server was started 78 // via `-sidecar-subscribe-to-permission` command line flag. Checks for any 79 // other permission will end up with INVALID_ARGUMENT error. 80 // 81 // Returns: 82 // * OK with the outcome of the check (which may be negative) if the check 83 // was performed successfully. 84 // * INVALID_ARGUMENT if the request is malformed or the specified 85 // permission was not registered with the sidecar server via 86 // `-sidecar-subscribe-to-permission` command line flag. 87 // * UNAUTHENTICATED if the call to the sidecar server failed due to invalid 88 // (corrupted, expired, etc) RPC credentials. This response MUST be 89 // presented as INTERNAL error to the end user, since it indicates some 90 // internal misconfiguration between the application server and the 91 // sidecar service. 92 // * PERMISSION_DENIED if the call to the sidecar server itself is not 93 // allowed. This response MUST also be presented as INTERNAL error to 94 // the end user. 95 // * INTERNAL on transient internal errors that SHOULD be retried. 96 rpc HasPermission(HasPermissionRequest) returns (HasPermissionResponse); 97 } 98 99 100 // AuthenticateRequest contains information about an incoming request that needs 101 // to be authenticated. 102 // 103 // To be forward compatible the application server should send all incoming 104 // headers (or metadata in gRPC case) and let the sidecar server decide which 105 // entries to use. If necessary, the application server can omit entries that 106 // are obviously not used for authentication (for example custom metadata 107 // entries used by the application server itself). But generally it should not 108 // be cherry-picking headers it thinks carry authentication credentials and 109 // sending only them. 110 // 111 // Note that in environments where the application server runs behind a 112 // TLS-terminating load balancer (all cloud environments are like that), 113 // metadata with key `Host` (for HTTP v1) or `:authority` (for HTTP v2 and gRPC) 114 // is especially important to propagate, since it contains the verified 115 // (by the load balancer) hostname of the service being called. It is often 116 // needed to check JWT token audience. Omitting it may result in some JWT tokens 117 // not being authenticated. 118 // 119 // If the application server terminates TLS itself, it MUST also itself verify 120 // `Host` header (or `:authority` pseudo-header) matches the expected service 121 // hostname before calling Authenticate. 122 message AuthenticateRequest { 123 // The protocol used by the end user to call the application server. Affects 124 // how some metadata keys are interpreted. 125 enum Protocol { 126 PROTOCOL_UNSPECIFIED = 0; 127 HTTP1 = 1; 128 HTTP2 = 2; 129 GRPC = 3; 130 } 131 Protocol protocol = 1; 132 133 // An HTTP header or gRPC metadatum. 134 message Metadata { 135 // Metadata key. Case-insensitive. 136 // 137 // If `protocol` is `GRPC`, keys ending with `-bin` indicate the value 138 // is base64-encoded. The application server MUST base64-encode binary 139 // metadata values before passing them to the sidecar server. 140 // 141 // For other protocols, keys ending with `-bin` have no special meaning, 142 // since they don't support arbitrary binary headers. 143 string key = 1; 144 // Metadata value. 145 // 146 // If `protocol` is `GRPC` and the key ends with `-bin`, this MUST be 147 // the base64-encoded value. The sidecar server will decode it into its 148 // original binary form before using it. 149 // 150 // For other protocols, keys ending with `-bin` have no special meaning, 151 // since they don't support arbitrary binary headers. 152 string value = 2; 153 } 154 repeated Metadata metadata = 2; 155 156 // List of groups to check an authenticated identity is a member of. 157 // 158 // The result of this check is returned via `groups` response field. 159 repeated string groups = 3; 160 } 161 162 163 // AuthenticateResponse is a result of authentication (successful or not). 164 // 165 // The primary result of the authentication is `identity` which is a LUCI 166 // identity string (`<kind>:<value>` pair, e.g. `user:someone@example.com`). 167 // It can be passed to methods that do authorization checks. Additional details 168 // are available via `outcome` oneof. If the request is anonymous or 169 // authentication failed, the identity is set to `anonymous:anonymous`. 170 // 171 // If credentials are present, but invalid (e.g. expired JWT), error details are 172 // returned as part of `error` outcome. 173 message AuthenticateResponse { 174 // An authenticated identity (`<kind>:<value>`). Details are in `outcome`. 175 string identity = 1; 176 // Sidecar server information for logging and debugging. 177 ServerInfo server_info = 2; 178 179 // List of groups the identity is a member of. 180 // 181 // This is a subset of groups passed via `groups` request field. 182 repeated string groups = 3; 183 184 message Anonymous { 185 // Nothing here. 186 } 187 188 message User { 189 // An authenticated user email. Always set. 190 string email = 1; 191 // A full user name, if available. 192 string name = 2; 193 // An URL to profile picture, if available. 194 string picture = 3; 195 // OAuth client ID if the request was authenticated using OAuth. 196 string client_id = 4; 197 } 198 199 message Project { 200 // LUCI project name representing the context of the call. 201 string project = 1; 202 // Identity string of the LUCI service that makes the call. 203 string service = 2; 204 } 205 206 oneof outcome { 207 // Set if the RPC to the sidecar succeeded, but passed credentials are bad. 208 google.rpc.Status error = 10; 209 // The request had no recognized credentials attached. 210 Anonymous anonymous = 11; 211 // The request had an end-user credentials attached. 212 User user = 12; 213 // The request is an internal LUCI call from another LUCI service. 214 Project project = 13; 215 } 216 } 217 218 219 // IsMemberRequest specifies an identity and a list of groups to check. 220 message IsMemberRequest { 221 // Identity to check a membership of as a `<kind>:<value>` string. 222 // 223 // This is the same identity as returned in AuthenticateResponse. Possible 224 // formats: 225 // * `anonymous:anonymous` for an anonymous caller. 226 // * `user:<email>` for an end user or a service account. 227 // * `project:<name>` for a LUCI project calling a LUCI service. 228 string identity = 1; 229 230 // List of groups to check memberships in, must have at least one entry. 231 // 232 // The check is overall positive if `identity` is a member of at least one 233 // group here. 234 repeated string groups = 2; 235 } 236 237 238 // IsMemberResponse contains outcome of a groups membership check. 239 message IsMemberResponse { 240 // True if the identity is a member of at least one group. 241 bool is_member = 1; 242 // Sidecar server information for logging and debugging. 243 ServerInfo server_info = 2; 244 } 245 246 247 // HasPermissionRequest identifies an identity and a permission to check. 248 message HasPermissionRequest { 249 // Identity to check a permission of as a `<kind>:<value>` string. 250 // 251 // This is the same identity as returned in AuthenticateResponse. Possible 252 // formats: 253 // * `anonymous:anonymous` for an anonymous caller. 254 // * `user:<email>` for an end user or a service account. 255 // * `project:<name>` for a LUCI project calling a LUCI service. 256 string identity = 1; 257 258 // Permission to check as `<service>.<subject>.<verb>` string. 259 // 260 // The sidecar server can only check permissions registered when it was 261 // started via `-sidecar-subscribe-to-permission` command line flag. Checks 262 // for any other permission will end up with INVALID_ARGUMENT error. 263 string permission = 2; 264 265 // A realm to check the permission in as `<project>:<realm>` string. 266 // 267 // A non-existing realm is replaced with the corresponding root realm (e.g. if 268 // `projectA:some/realm` doesn't exist, `projectA:@root` will be used in its 269 // place). If the project doesn't exist, all its realms (including the root 270 // realm) are considered empty. The permission check ends with negative 271 // outcome in that case. 272 string realm = 3; 273 274 // Attributes are the context of this particular permission check and are used 275 // as inputs to `conditions` predicates in conditional bindings. If a service 276 // supports conditional bindings, it must document what attributes it passes 277 // with each permission it checks. 278 map<string, string> attributes = 4; 279 } 280 281 282 // HasPermissionResponse contains outcome of a permission check. 283 message HasPermissionResponse { 284 // True if the identity has the requested permission. 285 bool has_permission = 1; 286 // Sidecar server information for logging and debugging. 287 ServerInfo server_info = 2; 288 } 289 290 291 // ServerInfo is returned with every response. It contains details about the 292 // sidecar server that handled the call and its current state. Useful for 293 // debugging. Should usually be logged by the application server in its internal 294 // logs. Do not return this to the end user. 295 message ServerInfo { 296 // Service name of the LUCI Sidecar server to identify its monitoring metrics. 297 string sidecar_service = 1; 298 // Job name of the LUCI Sidecar server to identify its monitoring metrics. 299 string sidecar_job = 2; 300 // Hostname of the LUCI Sidecar server to identify its monitoring metrics. 301 string sidecar_host = 3; 302 // Version of the LUCI Sidecar server for logs. 303 string sidecar_version = 4; 304 // Hostname of LUCI Auth service that produced AuthDB. 305 string auth_db_service = 5; 306 // Revision of LUCI AuthDB used during authorization checks. 307 int64 auth_db_rev = 6; 308 }