syntax = "proto3"; package spire.api.server.entry.v1; option go_package = "github.com/spiffe/spire-api-sdk/proto/spire/api/server/entry/v1;entryv1"; import "spire/api/types/entry.proto"; import "spire/api/types/federateswith.proto"; import "spire/api/types/selector.proto"; import "spire/api/types/spiffeid.proto"; import "spire/api/types/status.proto"; import "google/protobuf/wrappers.proto"; // Manages registration entries stored by the SPIRE Server. service Entry { // Count entries. // // The caller must be local or present an admin X509-SVID. rpc CountEntries(CountEntriesRequest) returns (CountEntriesResponse); // Lists entries. // // The caller must be local or present an admin X509-SVID. rpc ListEntries(ListEntriesRequest) returns (ListEntriesResponse); // Gets an entry. If the entry does not exist, NOT_FOUND is returned. // // The caller must be local or present an admin X509-SVID. rpc GetEntry(GetEntryRequest) returns (spire.api.types.Entry); // Batch creates one or more entries. // // The caller must be local or present an admin X509-SVID. rpc BatchCreateEntry(BatchCreateEntryRequest) returns (BatchCreateEntryResponse); // Batch updates one or more entries. // // The caller must be local or present an admin X509-SVID. rpc BatchUpdateEntry(BatchUpdateEntryRequest) returns (BatchUpdateEntryResponse); // Batch deletes one or more entries. // // The caller must be local or present an admin X509-SVID. rpc BatchDeleteEntry(BatchDeleteEntryRequest) returns (BatchDeleteEntryResponse); // Gets the entries the caller is authorized for. // // The caller must present an active agent X509-SVID. See the Agent // AttestAgent/RenewAgent RPCs. rpc GetAuthorizedEntries(GetAuthorizedEntriesRequest) returns (GetAuthorizedEntriesResponse); // Syncs authorized entries down to the caller. The caller controls which // entries the server sends down full details for. The flow is as follows: // 1. Caller opens up sync stream // 2. Server determines authorized entries for caller: // - If there are less entries than a server-determined page size, go to (5). // - Otherwise, go to (3). // 3. Server pages entry revisions to the caller (contains the entry ID and // revision number). The "more" flag set for all pages but the last so // that the caller knows when the server is done. // 4. Client determines which entries are new or updated (based on revision // number) and asks for them by sending a request with the IDs. // 5. Server pages down entries to the caller for each ID identified in (4) // or every entry in (2) if the number of entries was less than the // server-determined page size. The "more" flag set for all pages but // the last so that the caller knows when the server is done. // 6. Steps (4) and (5) are repeated until the caller has synced down the // details for all new/updated entries and closes the stream. rpc SyncAuthorizedEntries(stream SyncAuthorizedEntriesRequest) returns (stream SyncAuthorizedEntriesResponse); } message CountEntriesRequest { message Filter { spire.api.types.SPIFFEID by_spiffe_id = 1; spire.api.types.SPIFFEID by_parent_id = 2; spire.api.types.SelectorMatch by_selectors = 3; spire.api.types.FederatesWithMatch by_federates_with = 4; google.protobuf.StringValue by_hint = 5; google.protobuf.BoolValue by_downstream = 6; } // Filters the entries returned in the response. Filter filter = 1; } message CountEntriesResponse { int32 count = 1; } message ListEntriesRequest { message Filter { spire.api.types.SPIFFEID by_spiffe_id = 1; spire.api.types.SPIFFEID by_parent_id = 2; spire.api.types.SelectorMatch by_selectors = 3; spire.api.types.FederatesWithMatch by_federates_with = 4; google.protobuf.StringValue by_hint = 5; google.protobuf.BoolValue by_downstream = 6; } // Filters the entries returned in the response. Filter filter = 1; // An output mask indicating the entry fields set in the response. spire.api.types.EntryMask output_mask = 2; // The maximum number of results to return. The server may further // constrain this value, or if zero, choose its own. int32 page_size = 3; // The next_page_token value returned from a previous request, if any. string page_token = 4; } message ListEntriesResponse { // The list of entries. repeated spire.api.types.Entry entries = 1; // The page token for the next request. Empty if there are no more results. // This field should be checked by clients even when a page_size was not // requested, since the server may choose its own (see page_size). string next_page_token = 2; } message GetEntryRequest { // Required. ID of the entry to get. string id = 1; // An output mask indicating the entry fields set in the response. spire.api.types.EntryMask output_mask = 2; } message BatchCreateEntryRequest { // The entries to be created. If no entry ID is provided, one will be // generated. repeated spire.api.types.Entry entries = 1; // An output mask indicating the entry fields set in the response. spire.api.types.EntryMask output_mask = 2; } message BatchCreateEntryResponse { message Result { // The status of creating the entry. If status code will be // ALREADY_EXISTS if a similar entry already exists. An entry is // similar if it has the same spiffe_id, parent_id, and selectors. spire.api.types.Status status = 1; // The entry that was created (.e.g status code is OK) or that already // exists (i.e. status code is ALREADY_EXISTS). // // If the status code is any other value, this field will not be set. spire.api.types.Entry entry = 2; } // Result for each entry in the request (order is maintained). repeated Result results = 1; } message BatchUpdateEntryRequest { // The entries to be updated. repeated spire.api.types.Entry entries = 1; // An input mask indicating what entry fields should be updated. spire.api.types.EntryMask input_mask = 2; // An output mask indicating what entry fields are set in the response. spire.api.types.EntryMask output_mask = 3; } message BatchUpdateEntryResponse { message Result { // The status of creating the entry. spire.api.types.Status status = 1; // The entry that was updated. If the status is OK, it will be the // entry that was updated. If the status is any other value, this field // will not be set. spire.api.types.Entry entry = 2; } // Result for each entry in the request (order is maintained). repeated Result results = 1; } message BatchDeleteEntryRequest { // IDs of the entries to delete. repeated string ids = 1; } message BatchDeleteEntryResponse { message Result { // The status of creating the entry. spire.api.types.Status status = 1; // The ID of the entry that was deleted. string id = 2; } // Result for each entry ID in the request (order is maintained). repeated Result results = 1; } message GetAuthorizedEntriesRequest { // An output mask indicating which fields are set in the response. spire.api.types.EntryMask output_mask = 1; } message GetAuthorizedEntriesResponse { // The authorized entries. repeated spire.api.types.Entry entries = 1; } message SyncAuthorizedEntriesRequest { // An output mask indicating which fields are set in the response. spire.api.types.EntryMask output_mask = 1; // IDs of the entries to fetch in full. Sent by the client in response to // a sparse entry. repeated string ids = 2; } message SyncAuthorizedEntriesResponse { // The revisions of the authorized entries. This field is set when the // authorized entry list meets or exceeds the server-determined page size. // Callers use it to determine which entries are new/updated that they then // request on the stream. // See SyncAuthorizedEntries for details. repeated EntryRevision entry_revisions = 1; // The authorized entries. This field is set either 1) on the initial // response if the number of authorized entries is less than the page size // or 2) in response to the caller requesting the entries after determining // they need to details based on entry revisions provided in a previous // response. // See SyncAuthorizedEntries for details. repeated spire.api.types.Entry entries = 2; // Whether there are more entries to sync down in this response phase. bool more = 3; } message EntryRevision { // The entry ID. string id = 1; // The entry revision number. int64 revision_number = 2; }