blob: f1e40aebb51c599e02b8bc96bee19693ef37b728 [file] [log] [blame]
// 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;
}