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  }