An operator delivers a pair credential, and the mesh never replaces it

secret accept grows --provider: the value is sealed to the consumer's node, the
provider's node and the operator's key, and the pair records origin 'accepted'.
An accepted pair is not remade when a key changes (the mesh does not hold the
value; the read is refused naming the remedy) and rotate refuses it (accepting a
new value is the rotation). The vault's third species has its entry
(novox/hq 04-ISSUES/070, ADR 0092).
This commit is contained in:
2026-09-21 17:50:41 +02:00
parent 537ad544d3
commit 396e05bb65
4 changed files with 188 additions and 4 deletions
+66
View File
@@ -558,3 +558,69 @@ func TestRotatingGivesBothEndsTheSameNewCredential(t *testing.T) {
t.Fatal("rotating one machine's credential changed another machine's")
}
}
// **A person can deliver a pair credential** (novox/hq 04-ISSUES/070, ADR 0092): the vault's
// third species, a value for something outside the mesh. It is sealed to both ends like a made
// one; what differs is that the mesh will neither replace it with one of its own nor rotate it,
// because it cannot make the replacement.
func TestAnAcceptedPairCredentialIsKeptAndNeverRemade(t *testing.T) {
inv, ctx := twoNodesWithKeys(t)
if err := inv.AcceptSecretForPair(ctx, "secret", "consumer", "gitea", "provider", "hunter2"); err != nil {
t.Fatal(err)
}
got, err := inv.SecretFor(ctx, "secret", "consumer", "gitea", "provider")
if err != nil {
t.Fatal(err)
}
if got.Origin != OriginAccepted {
t.Fatalf("an accepted credential reads back as %q", got.Origin)
}
again, err := inv.SecretFor(ctx, "secret", "consumer", "gitea", "provider")
if err != nil {
t.Fatal(err)
}
if again.ForConsumer != got.ForConsumer || again.ForProvider != got.ForProvider {
t.Fatal("reading an accepted credential twice produced two different values")
}
// Rotation is refused, and says what to do instead.
err = inv.RotateSecret(ctx, "secret", "consumer", "gitea", "provider")
if err == nil || !strings.Contains(err.Error(), "secret accept") {
t.Fatalf("rotating an accepted credential was not refused with the remedy: %v", err)
}
// And a made one still rotates.
if _, err := inv.SecretFor(ctx, "postgres-database", "consumer", "gitea", "provider"); err != nil {
t.Fatal(err)
}
if err := inv.RotateSecret(ctx, "postgres-database", "consumer", "gitea", "provider"); err != nil {
t.Fatalf("a made credential no longer rotates: %v", err)
}
}
// A key that changed at either end makes the accepted value unreadable there, and the mesh cannot
// re-seal what it does not hold: refused aloud, never quietly replaced by a minted one.
func TestAnAcceptedPairCredentialIsNotRemadeWhenAKeyChanges(t *testing.T) {
inv, ctx := twoNodesWithKeys(t)
if err := inv.AcceptSecretForPair(ctx, "secret", "consumer", "gitea", "provider", "hunter2"); err != nil {
t.Fatal(err)
}
node, err := inv.NodeByName(ctx, "consumer")
if err != nil {
t.Fatal(err)
}
fresh, _ := aSealingKey(t)
if err := inv.RecordSealingKey(ctx, node.ID, fresh); err != nil {
t.Fatal(err)
}
_, err = inv.SecretFor(ctx, "secret", "consumer", "gitea", "provider")
if err == nil || !strings.Contains(err.Error(), "accept it again") {
t.Fatalf("an accepted credential was remade, or refused without the remedy: %v", err)
}
// Accepting it again is the remedy, and it works.
if err := inv.AcceptSecretForPair(ctx, "secret", "consumer", "gitea", "provider", "hunter3"); err != nil {
t.Fatal(err)
}
if _, err := inv.SecretFor(ctx, "secret", "consumer", "gitea", "provider"); err != nil {
t.Fatal(err)
}
}