syntax = "proto3";
package spire.api.agent.delegatedidentity.v1;
option go_package = "github.com/spiffe/spire-api-sdk/proto/spire/api/agent/delegatedidentity/v1;delegatedidentityv1";

import "spire/api/types/selector.proto";
import "spire/api/types/x509svid.proto";
import "spire/api/types/jwtsvid.proto";

// The delegatedIdentity service provides an interface to get the SVIDs of other
// workloads on the host. This service is intended for use cases where a process
// (different than the workload one) should access the workload's SVID to
// perform actions on behalf of the workload. One example of is using a single
// node instance of Envoy that upgrades TCP connections for different processes
// running in such a node.
//
// The caller must be local and its identity must be listed in the allowed
// clients on the spire-agent configuration.
service DelegatedIdentity {
    // Subscribe to get X.509-SVIDs for workloads that match the given selectors.
    // The lifetime of the subscription aligns to the lifetime of the stream.
    rpc SubscribeToX509SVIDs(SubscribeToX509SVIDsRequest) returns (stream SubscribeToX509SVIDsResponse);

    // Subscribe to get local and all federated bundles.
    // The lifetime of the subscription aligns to the lifetime of the stream.
    rpc SubscribeToX509Bundles(SubscribeToX509BundlesRequest) returns (stream SubscribeToX509BundlesResponse);

    // Fetch JWT-SVIDs for workloads that match the given selectors, and
    // for the requested audience.
    rpc FetchJWTSVIDs(FetchJWTSVIDsRequest) returns (FetchJWTSVIDsResponse);

    // Subscribe to get local and all federated JWKS bundles.
    // The lifetime of the subscription aligns to the lifetime of the stream.
    rpc SubscribeToJWTBundles(SubscribeToJWTBundlesRequest) returns (stream SubscribeToJWTBundlesResponse);
}

// X.509 SPIFFE Verifiable Identity Document with the private key.
message X509SVIDWithKey {
    // The workload X509-SVID.
    spire.api.types.X509SVID x509_svid = 1;

    // Private key (encoding DER PKCS#8).
    bytes x509_svid_key = 2;
}

// SubscribeToX509SVIDsRequest is used by clients to subscribe the set of SVIDs that
// any given workload is entitled to. Clients subscribe to a workload's SVIDs by providing
// one-of
//  - a set of selectors describing the workload.
//  - a PID of a workload process.
// Specifying both at the same time is not allowed.
//
// Subscribers are expected to ensure that the PID they use is not recycled
// for the lifetime of the stream, and in the event that it is, are expected
// to immediately close the stream.
//
// TODO we should use `oneof` here but you currently cannot use `repeated`
// in a `oneof` without creating and nesting an intermediate `message` type, which would break
// back compat - so we accept both and check for mutual exclusion in the handler
message SubscribeToX509SVIDsRequest {
    // Selectors describing the workload to subscribe to. Mutually exclusive with `pid`.
    repeated spire.api.types.Selector selectors = 1;

    // PID for the workload to subscribe to. Mutually exclusive with `selectors`
    int32 pid = 2;
}

message SubscribeToX509SVIDsResponse {
    repeated X509SVIDWithKey x509_svids = 1;

    // Names of the trust domains that this workload should federates with.
    repeated string federates_with = 2;
}

message SubscribeToX509BundlesRequest {}

// SubscribeToX509BundlesResponse contains all bundles that the agent is tracking,
// including the local bundle. When an update occurs, or bundles are added or removed,
// a new response with the full set of bundles is sent.
message SubscribeToX509BundlesResponse {
    // A map keyed by trust domain name, with ASN.1 DER-encoded
    // X.509 CA certificates as the values
    map<string, bytes> ca_certificates = 1;
}

// FetchJWTSVIDsRequest is used by clients to fetch a JWT-SVID for a workload.
// Clients may provide one-of
//  - a set of selectors describing the workload.
//  - a PID of a workload process.
// Specifying both at the same time is not allowed.
//
// Callers are expected to ensure that the PID they use is not recycled
// until obtaining a response, and in the event that it is, are expected
// to discard the response of this call.
//
// TODO we should use `oneof` here but you currently cannot use `repeated`
// in a `oneof` without creating and nesting an intermediate `message` type, which would break
// back compat - so we accept both and check for mutual exclusion in the handler
message FetchJWTSVIDsRequest {
    // Required. The audience(s) the workload intends to authenticate against.
    repeated string audience = 1;

    // Selectors describing the workload to subscribe to. Mutually exclusive with `pid`
    repeated spire.api.types.Selector selectors = 2;

    // PID for the workload to subscribe to. Mutually exclusive with `selectors`.
    int32 pid = 3;
}

// The FetchJWTSVIDsResponse message conveys JWT-SVIDs.
message FetchJWTSVIDsResponse {
    // Required. The list of returned JWT-SVIDs.
    repeated spire.api.types.JWTSVID svids = 1;
}

// The SubscribeToJWTBundlesRequest message conveys parameters for requesting JWKS bundles.
// There are currently no such parameters.
message SubscribeToJWTBundlesRequest { 
}

// The SubscribeToJWTBundlesReponse conveys JWKS bundles.
message SubscribeToJWTBundlesResponse {
    // Required. JWK encoded JWT bundles, keyed by the SPIFFE ID of the trust
    // domain.
    map<string, bytes> bundles = 1;
}
