go.chromium.org/luci@v0.0.0-20250314024836-d9a61d0730e6/tokenserver/api/minter/v1/token_minter.proto (about)

     1  // Copyright 2016 The LUCI Authors. All rights reserved.
     2  // Use of this source code is governed under the Apache License, Version 2.0
     3  // that can be found in the LICENSE file.
     4  
     5  syntax = "proto3";
     6  
     7  package tokenserver.minter;
     8  
     9  option go_package = "go.chromium.org/luci/tokenserver/api/minter/v1;minter";
    10  
    11  import "google/protobuf/timestamp.proto";
    12  
    13  import "go.chromium.org/luci/server/auth/delegation/messages/delegation.proto";
    14  import "go.chromium.org/luci/tokenserver/api/machine_token.proto";
    15  
    16  
    17  // Supported ways of singing the request.
    18  enum SignatureAlgorithm {
    19    UNKNOWN_ALGO    = 0; // used if the field is not initialized
    20    SHA256_RSA_ALGO = 1; // matches x509's sha256WithRSAEncryption
    21  }
    22  
    23  
    24  // Possible kinds of fatal errors.
    25  //
    26  // Non fatal errors are returned as grpc.Internal errors instead.
    27  enum ErrorCode {
    28    SUCCESS                     = 0;
    29    UNSUPPORTED_SIGNATURE       = 1; // used signature_algorithm is not supported
    30    UNSUPPORTED_TOKEN_TYPE      = 2; // requested token_type is not supported
    31    BAD_TIMESTAMP               = 3; // issued_at field is wrong
    32    BAD_CERTIFICATE_FORMAT      = 4; // malformed or unsupported certificate
    33    BAD_SIGNATURE               = 5; // signature doesn't match or can't be verified
    34    UNTRUSTED_CERTIFICATE       = 6; // invalid certificate or can't verify it yet
    35    BAD_TOKEN_ARGUMENTS         = 7; // FQDN or Scopes are invalid or not whitelisted
    36    MACHINE_TOKEN_MINTING_ERROR = 8; // unspecified fatal error when minting a machine token
    37  }
    38  
    39  
    40  // Used by MintServiceAccountToken.
    41  enum ServiceAccountTokenKind {
    42    SERVICE_ACCOUNT_TOKEN_UNSPECIFIED  = 0;
    43    SERVICE_ACCOUNT_TOKEN_ACCESS_TOKEN = 1; // ask for an OAuth2 access token
    44    SERVICE_ACCOUNT_TOKEN_ID_TOKEN     = 2; // ask for an OpenID ID token
    45  }
    46  
    47  
    48  // TokenMinter implements main API of the token server.
    49  //
    50  // It provides an interface for generating:
    51  //
    52  //  * Machine tokens: short lived stateless tokens used in Swarming bot
    53  //    authentication protocol. They are derived from PKI keys deployed on bots,
    54  //    and consumed primarily by Swarming. See MintMachineToken.
    55  //  * Delegation tokens: these are involved whenever a service calls other
    56  //    service on behalf of a user. They are passed via 'X-Delegation-Token-V1'
    57  //    HTTP header along with a credentials of the impersonating user.
    58  //    See MintDelegationToken.
    59  //  * OAuth2 access tokens of project-scoped accounts: these are OAuth2 access
    60  //    tokens that represents an identity associated with a LUCI project. See
    61  //    MintProjectToken.
    62  //  * Service accounts tokens: these are OAuth2 access tokens and ID tokens of
    63  //    service accounts "residing" within various LUCI projects. They are
    64  //    ultimately used by LUCI tasks as task service accounts.
    65  //    See MintServiceAccountToken.
    66  //
    67  // RPCs that were deprecated and removed:
    68  //
    69  //  * MintOAuthTokenGrant and MintOAuthTokenViaGrant: were deprecated by
    70  //    MintServiceAccountToken. Used (also now removed) service_accounts.cfg
    71  //    config file.
    72  service TokenMinter {
    73    // MintMachineToken generates a new token for an authenticated machine.
    74    //
    75    // It checks that provided certificate was signed by some trusted CA, and it
    76    // is still valid (non-expired and hasn't been revoked). It then checks that
    77    // the request was signed by the corresponding private key. Finally it checks
    78    // that the caller is authorized to generate requested kind of token.
    79    //
    80    // If everything checks out, it generates and returns a new machine token.
    81    //
    82    // On fatal error it returns detailed error response via same
    83    // MintMachineTokenResponse. On transient errors it returns generic
    84    // grpc.Internal error.
    85    rpc MintMachineToken(MintMachineTokenRequest) returns (MintMachineTokenResponse);
    86  
    87    // MintDelegationToken generates a new bearer delegation token.
    88    //
    89    // Such token can be sent in 'X-Delegation-Token-V1' header (alongside regular
    90    // credentials like OAuth2 access token) to convey that the caller should be
    91    // authentication as 'delegated_identity' specified in the token.
    92    //
    93    // The delegation tokens are subject to multiple restrictions (embedded in
    94    // the token):
    95    //   * They have expiration time.
    96    //   * They are usable only if presented with a credential of someone from
    97    //     the 'audience' list.
    98    //   * They are usable only on services specified in the 'services' list.
    99    //
   100    // The token server must be configured in advance with all expected
   101    // combinations of (caller identity, delegated identity, audience, service)
   102    // tuples. See DelegationRule in config.proto.
   103    rpc MintDelegationToken(MintDelegationTokenRequest) returns (MintDelegationTokenResponse);
   104  
   105    // MintProjectToken mints an OAuth2 access token that represents an identity
   106    // associated with a LUCI project.
   107    //
   108    // Project-scoped tokens prevent accidental cross-project identity confusion
   109    // when LUCI services access project specific resources such as a source code
   110    // repository.
   111    rpc MintProjectToken(MintProjectTokenRequest) returns (MintProjectTokenResponse);
   112  
   113    // MintServiceAccountToken mints an OAuth2 access token or OpenID ID token
   114    // that belongs to some service account using LUCI Realms for authorization.
   115    //
   116    // As an input it takes a service account email and a name of a LUCI Realm the
   117    // caller is operating in. To authorize the call the token server checks the
   118    // following conditions:
   119    //   1. The caller has luci.serviceAccounts.mintToken permission in the
   120    //      realm, allowing them to "impersonate" all service accounts belonging
   121    //      to this realm.
   122    //   2. The service account has luci.serviceAccounts.existInRealm permission
   123    //      in the realm. This makes the account "belong" to the realm.
   124    //   3. Realm's LUCI project is allowed to impersonate this service account:
   125    //     a. Legacy approach being deprecated: realm's LUCI project is NOT listed
   126    //        in `use_project_scoped_account` set in project_owned_accounts.cfg
   127    //        global config file, but it has service accounts associated with it
   128    //        there via `mapping` field. In that case LUCI Token Server will check
   129    //        `mapping` and then use its own service account when minting tokens.
   130    //     b. New approach being rolled out: realm's LUCI project is listed in
   131    //        `use_project_scoped_account` set in project_owned_accounts.cfg
   132    //        global config file. In that case LUCI Token Server will use
   133    //        project-scoped account associated with this LUCI project when
   134    //        minting service account tokens. This essentially shifts mapping
   135    //        between LUCI projects and service accounts they can use into
   136    //        service account IAM policies.
   137    //
   138    // Check (3) makes sure different LUCI projects can't arbitrarily use each
   139    // others accounts by adding them to their respective realms.cfg. See also
   140    // comments for ServiceAccountsProjectMapping in api/admin/v1/config.proto.
   141    rpc MintServiceAccountToken(MintServiceAccountTokenRequest) returns (MintServiceAccountTokenResponse);
   142  }
   143  
   144  
   145  ////////////////////////////////////////////////////////////////////////////////
   146  // Machine tokens.
   147  
   148  
   149  // MintMachineTokenRequest wraps a serialized and signed MachineTokenRequest
   150  // message.
   151  message MintMachineTokenRequest {
   152    // The protobuf-serialized MachineTokenRequest message, signed by the private
   153    // key that matches MachineTokenRequest.certificate.
   154    //
   155    // We have to send it as a byte blob to avoid dealing with possible protobuf
   156    // serialization inconsistencies when checking the signature.
   157    bytes serialized_token_request = 1;
   158  
   159    // The signature of 'serialized_token_parameters' blob.
   160    //
   161    // See MachineTokenRequest.signature_algorithm for exact meaning.
   162    bytes signature = 2;
   163  }
   164  
   165  
   166  // MachineTokenRequest contains the actual request parameters.
   167  message MachineTokenRequest {
   168    reserved 5;
   169  
   170    // The certificate that identifies a caller (as ASN1-serialized blob).
   171    //
   172    // It will be used to extract machine FQDN (it's CN of the cert) and CA name
   173    // to use to check the cert.
   174    bytes certificate = 1;
   175  
   176    // The signature algorithm used to sign this request.
   177    //
   178    // Defines what's in MintMachineTokenRequest.signature field.
   179    SignatureAlgorithm signature_algorithm = 2;
   180  
   181    // Timestamp when this request was created, by the issuer clock.
   182    google.protobuf.Timestamp issued_at = 3;
   183  
   184    // The token type being requested.
   185    //
   186    // Defines what fields of the response are set.
   187    MachineTokenType token_type = 4;
   188  }
   189  
   190  
   191  // MintMachineTokenResponse is returned by MintMachineToken if the server
   192  // processed the request.
   193  //
   194  // It's returned even if server refuses to mint a token. It contains the error
   195  // details in that case.
   196  message MintMachineTokenResponse {
   197    // Possible kinds of fatal errors.
   198    //
   199    // Non fatal errors are returned as grpc.Internal errors instead.
   200    ErrorCode error_code = 1;
   201  
   202    // Optional detailed error message.
   203    string error_message = 2;
   204  
   205    // On success (SUCCESS error code) contains the produced token.
   206    MachineTokenResponse token_response = 3;
   207  
   208    // Identifier of the service and its version that produced the response.
   209    //
   210    // Set for both successful responses and errors. On success, it is identical
   211    // to token_response.service_version.
   212    string service_version = 4;
   213  }
   214  
   215  
   216  // MachineTokenResponse contains a token requested by MachineTokenRequest.
   217  message MachineTokenResponse {
   218    reserved 1, 20;
   219  
   220    // Identifier of the service and its version that produced the token.
   221    //
   222    // Has the form "<app-id>/<module-version>". Reported to the monitoring by
   223    // the client. This is _not_ a part of the token.
   224    string service_version = 2;
   225  
   226    // The generated token.
   227    //
   228    // The exact field set here depends on a requested type of the token, see
   229    // MachineTokenRequest.token_type.
   230    oneof token_type {
   231      LuciMachineToken luci_machine_token = 21;
   232    }
   233  }
   234  
   235  
   236  // LuciMachineToken is short lived machine token.
   237  //
   238  // It is understood only by LUCI backends. It is a bearer token, that embeds
   239  // machine hostname and details about the machine certificate it was issued for.
   240  // It has short lifetime (usually 1h).
   241  //
   242  // It is expected to be sent to backends in 'X-Luci-Machine-Token' HTTP header.
   243  //
   244  // The token here is supposed to be treated as an opaque base64-encoded blob,
   245  // but in reality it is serialized MachineTokenEnvelope, see machine_token.proto
   246  // and read the comment there for more info about the token format.
   247  message LuciMachineToken {
   248    string machine_token = 1;             // the actual token
   249    google.protobuf.Timestamp expiry = 2; // when the token expires
   250  }
   251  
   252  
   253  ////////////////////////////////////////////////////////////////////////////////
   254  // Delegation tokens.
   255  
   256  
   257  // MintDelegationTokenRequest is passed to MintDelegationToken.
   258  message MintDelegationTokenRequest {
   259    // Identity whose authority is delegated.
   260    //
   261    // A string of the form "user:<email>" or a special token "REQUESTOR" that
   262    // means to delegate caller's own identity. The token server will check its
   263    // ACLs to make sure the caller is authorized to impersonate this identity.
   264    //
   265    // Required.
   266    string delegated_identity = 1;
   267  
   268    // How long the token should be considered valid (in seconds).
   269    //
   270    // Default is 3600 sec.
   271    int64 validity_duration = 2;
   272  
   273    // Who will be able to use the new token.
   274    //
   275    // Each item can be an identity string (e.g. "user:<email>"), a "group:<name>"
   276    // string, special "*" string which means "Any bearer can use the token", or
   277    // "REQUESTOR" string which means "Whoever is making this call can use the
   278    // token".
   279    //
   280    // This is semantically is a set, the order of elements doesn't matter.
   281    //
   282    // Required.
   283    repeated string audience = 3;
   284  
   285    // What services should accept the new token.
   286    //
   287    // List of LUCI services (specified as service identities, e.g.
   288    // "service:app-id" or as https:// root URLs e.g. "https://<host>") that
   289    // should accept this token. May also contain special "*" string, which
   290    // means "All LUCI services".
   291    //
   292    // This is semantically is a set, the order of elements doesn't matter.
   293    //
   294    // Required.
   295    repeated string services = 4;
   296  
   297    // Optional reason why the token is created.
   298    //
   299    // Used only for logging and auditing purposes. Doesn't become part of the
   300    // token.
   301    string intent = 5;
   302  
   303    // Arbitrary key:value pairs embedded into the token by whoever requested it.
   304    // Convey circumstance of why the token is created.
   305    //
   306    // Services that accept the token may use them for additional authorization
   307    // decisions. Please use extremely carefully, only when you control both sides
   308    // of the delegation link and can guarantee that services involved understand
   309    // the tags.
   310    repeated string tags = 6;
   311  }
   312  
   313  
   314  // MintDelegationTokenResponse is returned by MintDelegationToken on success.
   315  //
   316  // Errors are returned via standard gRPC codes.
   317  message MintDelegationTokenResponse {
   318    // The actual base64-encoded signed token.
   319    string token = 1;
   320  
   321    // Same data as in 'token' in deserialized form, just for convenience.
   322    //
   323    // Mostly for JSON encoding users, since they may not understand proto-encoded
   324    // tokens.
   325    messages.Subtoken delegation_subtoken = 2;
   326  
   327    // Identifier of the service and its version that produced the token.
   328    //
   329    // Has the form "<app-id>/<module-version>". This is _not_ part of the token.
   330    // Used only for logging and monitoring.
   331    string service_version = 3;
   332  }
   333  
   334  
   335  ////////////////////////////////////////////////////////////////////////////////
   336  // Service account tokens.
   337  
   338  
   339  // MintProjectTokenRequest is passed to MintProjectToken.
   340  message MintProjectTokenRequest {
   341    // Luci project to which this token will be bound.
   342    string luci_project = 1;
   343  
   344    // Requested OAuth scopes for the token.
   345    repeated string oauth_scope = 2;
   346  
   347    // Minimum token validity duration in seconds.
   348    int64 min_validity_duration = 3;
   349  
   350    // Arbitrary key:value pairs describing circumstances of this call.
   351    //
   352    // Used only for logging and auditing purposes. Not involved in authorization.
   353    repeated string audit_tags = 4;
   354  }
   355  
   356  
   357  // MintProjectTokenResponse is returned by MintProjectToken.
   358  message MintProjectTokenResponse {
   359    // Full service account email.
   360    string service_account_email = 1;
   361  
   362    // OAuth access token.
   363    string access_token = 2;
   364  
   365    // Token expiration timestamp.
   366    google.protobuf.Timestamp expiry = 3;
   367  
   368    // Identifier of the service and its version that produced the token.
   369    //
   370    // Has the form "<app-id>/<module-version>". Used only for logging and
   371    // monitoring.
   372    string service_version = 4;
   373  }
   374  
   375  
   376  // MintServiceAccountTokenRequest is passed to MintServiceAccountToken.
   377  message MintServiceAccountTokenRequest {
   378    // What kind of a token is being requested. Required.
   379    ServiceAccountTokenKind token_kind = 1;
   380    // Email of a service account to grab the token for. Required.
   381    string service_account = 2;
   382    // A LUCI realm to use to authorize the call. Required.
   383    string realm = 3;
   384  
   385    // A list of scopes the OAuth2 access token should have.
   386    //
   387    // Must be set if token_kind is SERVICE_ACCOUNT_TOKEN_ACCESS_TOKEN and must
   388    // be empty otherwise.
   389    repeated string oauth_scope = 4;
   390  
   391    // An audience the ID token should have.
   392    //
   393    // Must be set if token_kind is SERVICE_ACCOUNT_TOKEN_ID_TOKEN and must
   394    // be empty otherwise.
   395    string id_token_audience = 5;
   396  
   397    // Minimally accepted validity duration of the returned token (seconds).
   398    //
   399    // The server may return a token that lives longer than this. The maximum is
   400    // 1h. An attempt to get a token that lives longer than 1h will result in
   401    // an error.
   402    //
   403    // Default is 300 sec.
   404    int64 min_validity_duration = 6;
   405  
   406    // Arbitrary key:value pairs describing circumstances of this call.
   407    //
   408    // Used only for logging and auditing purposes. Not involved in authorization.
   409    repeated string audit_tags = 7;
   410  }
   411  
   412  
   413  // MintServiceAccountTokenResponse is returned by MintServiceAccountToken.
   414  message MintServiceAccountTokenResponse {
   415    string token = 1;                     // the produced token
   416    google.protobuf.Timestamp expiry = 2; // when this token expires
   417  
   418    // Identifier of the service and its version that produced the token.
   419    //
   420    // Has the form "<app-id>/<module-version>". Used only for logging and
   421    // monitoring.
   422    string service_version = 3;
   423  }