Complete browser extension gRPC flow
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"net"
|
||||
"os"
|
||||
"slices"
|
||||
@@ -121,6 +122,78 @@ func TestVaultServiceAllowsSessionStatusWithoutManageVault(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestVaultServiceSessionStatusIncludesPendingApprovalsForCurrentToken(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
token, secret, err := apitokens.Issue("Browser Token", "browser-extension", nil, time.Date(2026, 4, 11, 12, 0, 0, 0, time.UTC))
|
||||
if err != nil {
|
||||
t.Fatalf("Issue() error = %v", err)
|
||||
}
|
||||
token.SecretHash = hashSecretForTest(secret)
|
||||
otherToken, otherSecret, err := apitokens.Issue("Other Token", "automation-client", nil, time.Date(2026, 4, 11, 12, 1, 0, 0, time.UTC))
|
||||
if err != nil {
|
||||
t.Fatalf("Issue() other error = %v", err)
|
||||
}
|
||||
otherToken.SecretHash = hashSecretForTest(otherSecret)
|
||||
|
||||
client, _, service, cleanup := newTestHarnessForModel(t, vault.Model{
|
||||
Entries: []vault.Entry{
|
||||
token.Entry([]string{"Root", "API Tokens"}),
|
||||
otherToken.Entry([]string{"Root", "API Tokens"}),
|
||||
},
|
||||
})
|
||||
defer cleanup()
|
||||
|
||||
service.approvals = apiapproval.NewBroker(time.Minute)
|
||||
ctx, cancel := context.WithCancel(tokenContext(secret))
|
||||
defer cancel()
|
||||
waiting := make(chan error, 1)
|
||||
go func() {
|
||||
_, err := service.approvals.Request(ctx, token, apitokens.OperationCopyPassword, apitokens.Resource{
|
||||
Kind: apitokens.ResourceEntry,
|
||||
EntryID: "vault-console",
|
||||
Path: []string{"Root", "Internet"},
|
||||
})
|
||||
waiting <- err
|
||||
}()
|
||||
|
||||
otherCtx, otherCancel := context.WithCancel(tokenContext(otherSecret))
|
||||
defer otherCancel()
|
||||
otherWaiting := make(chan error, 1)
|
||||
go func() {
|
||||
_, err := service.approvals.Request(otherCtx, otherToken, apitokens.OperationListEntries, apitokens.Resource{
|
||||
Kind: apitokens.ResourceGroup,
|
||||
Path: []string{"Root", "Shared"},
|
||||
})
|
||||
otherWaiting <- err
|
||||
}()
|
||||
|
||||
waitForServerPendingApproval(t, service, 2)
|
||||
|
||||
resp, err := client.GetSessionStatus(tokenContext(secret), &keepassgov1.GetSessionStatusRequest{})
|
||||
if err != nil {
|
||||
t.Fatalf("GetSessionStatus() error = %v", err)
|
||||
}
|
||||
if got := resp.GetPendingApprovalCount(); got != 2 {
|
||||
t.Fatalf("GetSessionStatus().PendingApprovalCount = %d, want 2", got)
|
||||
}
|
||||
if got := resp.GetTokenPendingApprovalCount(); got != 1 {
|
||||
t.Fatalf("GetSessionStatus().TokenPendingApprovalCount = %d, want 1", got)
|
||||
}
|
||||
|
||||
for _, pending := range waitForServerPendingApproval(t, service, 2) {
|
||||
if _, _, err := service.ResolveApproval(pending.ID, apiapproval.OutcomeCancel); err != nil {
|
||||
t.Fatalf("ResolveApproval(%q) error = %v", pending.ID, err)
|
||||
}
|
||||
}
|
||||
if err := <-waiting; !errors.Is(err, apiapproval.ErrRequestCanceled) {
|
||||
t.Fatalf("Request(token) error = %v, want %v", err, apiapproval.ErrRequestCanceled)
|
||||
}
|
||||
if err := <-otherWaiting; !errors.Is(err, apiapproval.ErrRequestCanceled) {
|
||||
t.Fatalf("Request(otherToken) error = %v, want %v", err, apiapproval.ErrRequestCanceled)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVaultServiceRejectsUnauthorizedTemplateMutation(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user