| // Copyright 2016 The LUCI Authors. All rights reserved. |
| // Use of this source code is governed under the Apache License, Version 2.0 |
| // that can be found in the LICENSE file. |
| |
| syntax = "proto3"; |
| |
| package tokenserver.minter; |
| |
| option go_package = "go.chromium.org/luci/tokenserver/api/minter/v1;minter"; |
| |
| import "google/protobuf/timestamp.proto"; |
| |
| import "go.chromium.org/luci/server/auth/delegation/messages/delegation.proto"; |
| import "go.chromium.org/luci/tokenserver/api/machine_token.proto"; |
| |
| |
| // Supported ways of singing the request. |
| enum SignatureAlgorithm { |
| UNKNOWN_ALGO = 0; // used if the field is not initialized |
| SHA256_RSA_ALGO = 1; // matches x509's sha256WithRSAEncryption |
| } |
| |
| |
| // Possible kinds of fatal errors. |
| // |
| // Non fatal errors are returned as grpc.Internal errors instead. |
| enum ErrorCode { |
| SUCCESS = 0; |
| UNSUPPORTED_SIGNATURE = 1; // used signature_algorithm is not supported |
| UNSUPPORTED_TOKEN_TYPE = 2; // requested token_type is not supported |
| BAD_TIMESTAMP = 3; // issued_at field is wrong |
| BAD_CERTIFICATE_FORMAT = 4; // malformed or unsupported certificate |
| BAD_SIGNATURE = 5; // signature doesn't match or can't be verified |
| UNTRUSTED_CERTIFICATE = 6; // invalid certificate or can't verify it yet |
| BAD_TOKEN_ARGUMENTS = 7; // FQDN or Scopes are invalid or not whitelisted |
| MACHINE_TOKEN_MINTING_ERROR = 8; // unspecified fatal error when minting a machine token |
| } |
| |
| |
| // Used by MintServiceAccountToken. |
| enum ServiceAccountTokenKind { |
| SERVICE_ACCOUNT_TOKEN_UNSPECIFIED = 0; |
| SERVICE_ACCOUNT_TOKEN_ACCESS_TOKEN = 1; // ask for an OAuth2 access token |
| SERVICE_ACCOUNT_TOKEN_ID_TOKEN = 2; // ask for an OpenID ID token |
| } |
| |
| |
| // TokenMinter implements main API of the token server. |
| // |
| // It provides an interface for generating: |
| // |
| // * Machine tokens: short lived stateless tokens used in Swarming bot |
| // authentication protocol. They are derived from PKI keys deployed on bots, |
| // and consumed primarily by Swarming. See MintMachineToken. |
| // * Delegation tokens: these are involved whenever a service calls other |
| // service on behalf of a user. They are passed via 'X-Delegation-Token-V1' |
| // HTTP header along with a credentials of the impersonating user. |
| // See MintDelegationToken. |
| // * OAuth2 access tokens of project-scoped accounts: these are OAuth2 access |
| // tokens that represents an identity associated with a LUCI project. See |
| // MintProjectToken. |
| // * Service accounts tokens: these are OAuth2 access tokens and ID tokens of |
| // service accounts "residing" within various LUCI projects. They are |
| // ultimately used by LUCI tasks as task service accounts. |
| // See MintServiceAccountToken. |
| // |
| // RPCs that were deprecated and removed: |
| // |
| // * MintOAuthTokenGrant and MintOAuthTokenViaGrant: were deprecated by |
| // MintServiceAccountToken. Used (also now removed) service_accounts.cfg |
| // config file. |
| service TokenMinter { |
| // MintMachineToken generates a new token for an authenticated machine. |
| // |
| // It checks that provided certificate was signed by some trusted CA, and it |
| // is still valid (non-expired and hasn't been revoked). It then checks that |
| // the request was signed by the corresponding private key. Finally it checks |
| // that the caller is authorized to generate requested kind of token. |
| // |
| // If everything checks out, it generates and returns a new machine token. |
| // |
| // On fatal error it returns detailed error response via same |
| // MintMachineTokenResponse. On transient errors it returns generic |
| // grpc.Internal error. |
| rpc MintMachineToken(MintMachineTokenRequest) returns (MintMachineTokenResponse); |
| |
| // MintDelegationToken generates a new bearer delegation token. |
| // |
| // Such token can be sent in 'X-Delegation-Token-V1' header (alongside regular |
| // credentials like OAuth2 access token) to convey that the caller should be |
| // authentication as 'delegated_identity' specified in the token. |
| // |
| // The delegation tokens are subject to multiple restrictions (embedded in |
| // the token): |
| // * They have expiration time. |
| // * They are usable only if presented with a credential of someone from |
| // the 'audience' list. |
| // * They are usable only on services specified in the 'services' list. |
| // |
| // The token server must be configured in advance with all expected |
| // combinations of (caller identity, delegated identity, audience, service) |
| // tuples. See DelegationRule in config.proto. |
| rpc MintDelegationToken(MintDelegationTokenRequest) returns (MintDelegationTokenResponse); |
| |
| // MintProjectToken mints an OAuth2 access token that represents an identity |
| // associated with a LUCI project. |
| // |
| // Project-scoped tokens prevent accidental cross-project identity confusion |
| // when LUCI services access project specific resources such as a source code |
| // repository. |
| rpc MintProjectToken(MintProjectTokenRequest) returns (MintProjectTokenResponse); |
| |
| // MintServiceAccountToken mints an OAuth2 access token or OpenID ID token |
| // that belongs to some service account using LUCI Realms for authorization. |
| // |
| // As an input it takes a service account email and a name of a LUCI Realm the |
| // caller is operating in. To authorize the call the token server checks the |
| // following conditions: |
| // 1. The caller has luci.serviceAccounts.mintToken permission in the |
| // realm, allowing them to "impersonate" all service accounts belonging |
| // to this realm. |
| // 2. The service account has luci.serviceAccounts.existInRealm permission |
| // in the realm. This makes the account "belong" to the realm. |
| // 3. Realm's LUCI project is allowed to impersonate this service account: |
| // a. Legacy approach being deprecated: realm's LUCI project is NOT listed |
| // in `use_project_scoped_account` set in project_owned_accounts.cfg |
| // global config file, but it has service accounts associated with it |
| // there via `mapping` field. In that case LUCI Token Server will check |
| // `mapping` and then use its own service account when minting tokens. |
| // b. New approach being rolled out: realm's LUCI project is listed in |
| // `use_project_scoped_account` set in project_owned_accounts.cfg |
| // global config file. In that case LUCI Token Server will use |
| // project-scoped account associated with this LUCI project when |
| // minting service account tokens. This essentially shifts mapping |
| // between LUCI projects and service accounts they can use into |
| // service account IAM policies. |
| // |
| // Check (3) makes sure different LUCI projects can't arbitrarily use each |
| // others accounts by adding them to their respective realms.cfg. See also |
| // comments for ServiceAccountsProjectMapping in api/admin/v1/config.proto. |
| rpc MintServiceAccountToken(MintServiceAccountTokenRequest) returns (MintServiceAccountTokenResponse); |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // Machine tokens. |
| |
| |
| // MintMachineTokenRequest wraps a serialized and signed MachineTokenRequest |
| // message. |
| message MintMachineTokenRequest { |
| // The protobuf-serialized MachineTokenRequest message, signed by the private |
| // key that matches MachineTokenRequest.certificate. |
| // |
| // We have to send it as a byte blob to avoid dealing with possible protobuf |
| // serialization inconsistencies when checking the signature. |
| bytes serialized_token_request = 1; |
| |
| // The signature of 'serialized_token_parameters' blob. |
| // |
| // See MachineTokenRequest.signature_algorithm for exact meaning. |
| bytes signature = 2; |
| } |
| |
| |
| // MachineTokenRequest contains the actual request parameters. |
| message MachineTokenRequest { |
| reserved 5; |
| |
| // The certificate that identifies a caller (as ASN1-serialized blob). |
| // |
| // It will be used to extract machine FQDN (it's CN of the cert) and CA name |
| // to use to check the cert. |
| bytes certificate = 1; |
| |
| // The signature algorithm used to sign this request. |
| // |
| // Defines what's in MintMachineTokenRequest.signature field. |
| SignatureAlgorithm signature_algorithm = 2; |
| |
| // Timestamp when this request was created, by the issuer clock. |
| google.protobuf.Timestamp issued_at = 3; |
| |
| // The token type being requested. |
| // |
| // Defines what fields of the response are set. |
| MachineTokenType token_type = 4; |
| } |
| |
| |
| // MintMachineTokenResponse is returned by MintMachineToken if the server |
| // processed the request. |
| // |
| // It's returned even if server refuses to mint a token. It contains the error |
| // details in that case. |
| message MintMachineTokenResponse { |
| // Possible kinds of fatal errors. |
| // |
| // Non fatal errors are returned as grpc.Internal errors instead. |
| ErrorCode error_code = 1; |
| |
| // Optional detailed error message. |
| string error_message = 2; |
| |
| // On success (SUCCESS error code) contains the produced token. |
| MachineTokenResponse token_response = 3; |
| |
| // Identifier of the service and its version that produced the response. |
| // |
| // Set for both successful responses and errors. On success, it is identical |
| // to token_response.service_version. |
| string service_version = 4; |
| } |
| |
| |
| // MachineTokenResponse contains a token requested by MachineTokenRequest. |
| message MachineTokenResponse { |
| reserved 1, 20; |
| |
| // Identifier of the service and its version that produced the token. |
| // |
| // Has the form "<app-id>/<module-version>". Reported to the monitoring by |
| // the client. This is _not_ a part of the token. |
| string service_version = 2; |
| |
| // The generated token. |
| // |
| // The exact field set here depends on a requested type of the token, see |
| // MachineTokenRequest.token_type. |
| oneof token_type { |
| LuciMachineToken luci_machine_token = 21; |
| } |
| } |
| |
| |
| // LuciMachineToken is short lived machine token. |
| // |
| // It is understood only by LUCI backends. It is a bearer token, that embeds |
| // machine hostname and details about the machine certificate it was issued for. |
| // It has short lifetime (usually 1h). |
| // |
| // It is expected to be sent to backends in 'X-Luci-Machine-Token' HTTP header. |
| // |
| // The token here is supposed to be treated as an opaque base64-encoded blob, |
| // but in reality it is serialized MachineTokenEnvelope, see machine_token.proto |
| // and read the comment there for more info about the token format. |
| message LuciMachineToken { |
| string machine_token = 1; // the actual token |
| google.protobuf.Timestamp expiry = 2; // when the token expires |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // Delegation tokens. |
| |
| |
| // MintDelegationTokenRequest is passed to MintDelegationToken. |
| message MintDelegationTokenRequest { |
| // Identity whose authority is delegated. |
| // |
| // A string of the form "user:<email>" or a special token "REQUESTOR" that |
| // means to delegate caller's own identity. The token server will check its |
| // ACLs to make sure the caller is authorized to impersonate this identity. |
| // |
| // Required. |
| string delegated_identity = 1; |
| |
| // How long the token should be considered valid (in seconds). |
| // |
| // Default is 3600 sec. |
| int64 validity_duration = 2; |
| |
| // Who will be able to use the new token. |
| // |
| // Each item can be an identity string (e.g. "user:<email>"), a "group:<name>" |
| // string, special "*" string which means "Any bearer can use the token", or |
| // "REQUESTOR" string which means "Whoever is making this call can use the |
| // token". |
| // |
| // This is semantically is a set, the order of elements doesn't matter. |
| // |
| // Required. |
| repeated string audience = 3; |
| |
| // What services should accept the new token. |
| // |
| // List of LUCI services (specified as service identities, e.g. |
| // "service:app-id" or as https:// root URLs e.g. "https://<host>") that |
| // should accept this token. May also contain special "*" string, which |
| // means "All LUCI services". |
| // |
| // This is semantically is a set, the order of elements doesn't matter. |
| // |
| // Required. |
| repeated string services = 4; |
| |
| // Optional reason why the token is created. |
| // |
| // Used only for logging and auditing purposes. Doesn't become part of the |
| // token. |
| string intent = 5; |
| |
| // Arbitrary key:value pairs embedded into the token by whoever requested it. |
| // Convey circumstance of why the token is created. |
| // |
| // Services that accept the token may use them for additional authorization |
| // decisions. Please use extremely carefully, only when you control both sides |
| // of the delegation link and can guarantee that services involved understand |
| // the tags. |
| repeated string tags = 6; |
| } |
| |
| |
| // MintDelegationTokenResponse is returned by MintDelegationToken on success. |
| // |
| // Errors are returned via standard gRPC codes. |
| message MintDelegationTokenResponse { |
| // The actual base64-encoded signed token. |
| string token = 1; |
| |
| // Same data as in 'token' in deserialized form, just for convenience. |
| // |
| // Mostly for JSON encoding users, since they may not understand proto-encoded |
| // tokens. |
| messages.Subtoken delegation_subtoken = 2; |
| |
| // Identifier of the service and its version that produced the token. |
| // |
| // Has the form "<app-id>/<module-version>". This is _not_ part of the token. |
| // Used only for logging and monitoring. |
| string service_version = 3; |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // Service account tokens. |
| |
| |
| // MintProjectTokenRequest is passed to MintProjectToken. |
| message MintProjectTokenRequest { |
| // Luci project to which this token will be bound. |
| string luci_project = 1; |
| |
| // Requested OAuth scopes for the token. |
| repeated string oauth_scope = 2; |
| |
| // Minimum token validity duration in seconds. |
| int64 min_validity_duration = 3; |
| |
| // Arbitrary key:value pairs describing circumstances of this call. |
| // |
| // Used only for logging and auditing purposes. Not involved in authorization. |
| repeated string audit_tags = 4; |
| } |
| |
| |
| // MintProjectTokenResponse is returned by MintProjectToken. |
| message MintProjectTokenResponse { |
| // Full service account email. |
| string service_account_email = 1; |
| |
| // OAuth access token. |
| string access_token = 2; |
| |
| // Token expiration timestamp. |
| google.protobuf.Timestamp expiry = 3; |
| |
| // Identifier of the service and its version that produced the token. |
| // |
| // Has the form "<app-id>/<module-version>". Used only for logging and |
| // monitoring. |
| string service_version = 4; |
| } |
| |
| |
| // MintServiceAccountTokenRequest is passed to MintServiceAccountToken. |
| message MintServiceAccountTokenRequest { |
| // What kind of a token is being requested. Required. |
| ServiceAccountTokenKind token_kind = 1; |
| // Email of a service account to grab the token for. Required. |
| string service_account = 2; |
| // A LUCI realm to use to authorize the call. Required. |
| string realm = 3; |
| |
| // A list of scopes the OAuth2 access token should have. |
| // |
| // Must be set if token_kind is SERVICE_ACCOUNT_TOKEN_ACCESS_TOKEN and must |
| // be empty otherwise. |
| repeated string oauth_scope = 4; |
| |
| // An audience the ID token should have. |
| // |
| // Must be set if token_kind is SERVICE_ACCOUNT_TOKEN_ID_TOKEN and must |
| // be empty otherwise. |
| string id_token_audience = 5; |
| |
| // Minimally accepted validity duration of the returned token (seconds). |
| // |
| // The server may return a token that lives longer than this. The maximum is |
| // 1h. An attempt to get a token that lives longer than 1h will result in |
| // an error. |
| // |
| // Default is 300 sec. |
| int64 min_validity_duration = 6; |
| |
| // Arbitrary key:value pairs describing circumstances of this call. |
| // |
| // Used only for logging and auditing purposes. Not involved in authorization. |
| repeated string audit_tags = 7; |
| } |
| |
| |
| // MintServiceAccountTokenResponse is returned by MintServiceAccountToken. |
| message MintServiceAccountTokenResponse { |
| string token = 1; // the produced token |
| google.protobuf.Timestamp expiry = 2; // when this token expires |
| |
| // Identifier of the service and its version that produced the token. |
| // |
| // Has the form "<app-id>/<module-version>". Used only for logging and |
| // monitoring. |
| string service_version = 3; |
| } |