Skip to content

IKeyRingStore Interface

The shared place the server's minted keys live, so every pod serves one key set rather than its own. Entries are encrypted to the custodian's key-encryption key before they get here, so this store holds ciphertext and never a secret.

C#
public interface IKeyRingStore

Remarks

The port is three methods because the design needs no more. Key state is not stored, it is computed: given the entries and their creation times, every pod derives the same announced / active / retired projection by arithmetic, so there is nothing to update and no state machine to synchronise. The single operation that does need synchronising is creating the next key, since two pods would otherwise generate different material, and TryAddAsync(StoredKey, CancellationToken) carries that alone.

Because the entry is ciphertext we produced, the store's own protection is not what keeps the key safe: an implementation may be a database, a blob, a config map, or the custodian's own key-value engine, and the threat model does not change with the choice.

Methods

IKeyRingStore.LoadAsync(CancellationToken) Method

Reads every entry. The caller projects the key states from their creation times, so the store neither filters nor orders.

C#
System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Abblix.Jwt.ExternalKeys.StoredKey>> LoadAsync(System.Threading.CancellationToken cancellationToken);

Parameters

cancellationToken System.Threading.CancellationToken

Cancels the read.

Returns

System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<StoredKey>>
All entries currently in the ring.

IKeyRingStore.RemoveAsync(string, CancellationToken) Method

Removes an entry, idempotently: removing an absent id is not an error.

C#
System.Threading.Tasks.Task RemoveAsync(string id, System.Threading.CancellationToken cancellationToken);

Parameters

id System.String

The Id to remove.

cancellationToken System.Threading.CancellationToken

Cancels the write.

Returns

System.Threading.Tasks.Task

Remarks

Only ever called for a key already past every token it signed, so removal races are harmless: two pods removing the same expired entry is the same outcome as one.

IKeyRingStore.TryAddAsync(StoredKey, CancellationToken) Method

Inserts an entry if its Id is not taken, and reports whether this caller was the one that took it.

C#
System.Threading.Tasks.Task<bool> TryAddAsync(Abblix.Jwt.ExternalKeys.StoredKey key, System.Threading.CancellationToken cancellationToken);

Parameters

key StoredKey

The entry to insert.

cancellationToken System.Threading.CancellationToken

Cancels the write.

Returns

System.Threading.Tasks.Task<System.Boolean>
True when this caller inserted the entry; false when another pod had already claimed the id, in which case the caller re-reads the ring and uses the winner's key.

Remarks

This is the whole of the coordination, and it must be atomic in the backing store: a unique index, a conditional create, a compare-and-set on absence. Two pods minting the same period both attempt the same id, exactly one gets true, and the loser discards the key it generated. An implementation that cannot insert atomically cannot back this port.