diff --git a/cmd/secrets/common/browser_flow.go b/cmd/secrets/common/browser_flow.go index 53d60667..4cd5ba55 100644 --- a/cmd/secrets/common/browser_flow.go +++ b/cmd/secrets/common/browser_flow.go @@ -37,12 +37,17 @@ const exchangeAuthCodeToTokenMutation = `mutation ExchangeAuthCodeToToken($reque }` // vaultPermissionForMethod returns the API permission name for the given vault operation. +// Names match the VaultPermission enum in platform GraphQL (createVaultAuthorizationUrl). func vaultPermissionForMethod(method string) (string, error) { switch method { case vaulttypes.MethodSecretsCreate: return "VAULT_PERMISSION_CREATE_SECRETS", nil case vaulttypes.MethodSecretsUpdate: return "VAULT_PERMISSION_UPDATE_SECRETS", nil + case vaulttypes.MethodSecretsDelete: + return "VAULT_PERMISSION_DELETE_SECRETS", nil + case vaulttypes.MethodSecretsList: + return "VAULT_PERMISSION_LIST_SECRETS", nil default: return "", fmt.Errorf("unsupported method: %s", method) } @@ -110,6 +115,16 @@ func (h *Handler) executeBrowserUpsert(ctx context.Context, inputs UpsertSecrets return fmt.Errorf("unsupported method %q (expected %q or %q)", method, vaulttypes.MethodSecretsCreate, vaulttypes.MethodSecretsUpdate) } + return h.ExecuteBrowserVaultAuthorization(ctx, method, digest) +} + +// ExecuteBrowserVaultAuthorization completes platform OAuth for a vault JSON-RPC digest (create/update/delete/list). +// It does not POST to the gateway; the short-lived vault JWT is for future DON submission. +func (h *Handler) ExecuteBrowserVaultAuthorization(ctx context.Context, method string, digest [32]byte) error { + if h.Credentials.AuthType == credentials.AuthTypeApiKey { + return fmt.Errorf("this sign-in flow requires an interactive login; API keys are not supported") + } + perm, err := vaultPermissionForMethod(method) if err != nil { return err diff --git a/cmd/secrets/common/browser_flow_test.go b/cmd/secrets/common/browser_flow_test.go index 5c391f63..66e147a9 100644 --- a/cmd/secrets/common/browser_flow_test.go +++ b/cmd/secrets/common/browser_flow_test.go @@ -22,7 +22,15 @@ func TestVaultPermissionForMethod(t *testing.T) { require.NoError(t, err) assert.Equal(t, "VAULT_PERMISSION_UPDATE_SECRETS", p) - _, err = vaultPermissionForMethod(vaulttypes.MethodSecretsDelete) + p, err = vaultPermissionForMethod(vaulttypes.MethodSecretsDelete) + require.NoError(t, err) + assert.Equal(t, "VAULT_PERMISSION_DELETE_SECRETS", p) + + p, err = vaultPermissionForMethod(vaulttypes.MethodSecretsList) + require.NoError(t, err) + assert.Equal(t, "VAULT_PERMISSION_LIST_SECRETS", p) + + _, err = vaultPermissionForMethod("vault/secrets/unknown") require.Error(t, err) } diff --git a/cmd/secrets/delete/delete.go b/cmd/secrets/delete/delete.go index 050b16e7..cb32854f 100644 --- a/cmd/secrets/delete/delete.go +++ b/cmd/secrets/delete/delete.go @@ -1,6 +1,7 @@ package delete import ( + "context" "encoding/hex" "encoding/json" "fmt" @@ -164,6 +165,11 @@ func Execute(h *common.Handler, inputs DeleteSecretsInputs, duration time.Durati return fmt.Errorf("failed to calculate request digest: %w", err) } + if common.IsBrowserFlow(secretsAuth) { + ui.Dim("Using your account to authorize vault access for this delete request...") + return h.ExecuteBrowserVaultAuthorization(context.Background(), vaulttypes.MethodSecretsDelete, digest) + } + gatewayPost := func() error { respBody, status, err := h.Gw.Post(requestBody) if err != nil { diff --git a/cmd/secrets/list/list.go b/cmd/secrets/list/list.go index e5504c3f..be2a5c12 100644 --- a/cmd/secrets/list/list.go +++ b/cmd/secrets/list/list.go @@ -1,6 +1,7 @@ package list import ( + "context" "encoding/hex" "encoding/json" "fmt" @@ -128,6 +129,11 @@ func Execute(h *common.Handler, namespace string, duration time.Duration, secret return fmt.Errorf("failed to marshal JSON-RPC request: %w", err) } + if common.IsBrowserFlow(secretsAuth) { + ui.Dim("Using your account to authorize vault access for this list request...") + return h.ExecuteBrowserVaultAuthorization(context.Background(), vaulttypes.MethodSecretsList, digest) + } + ownerAddr := ethcommon.HexToAddress(owner) allowlisted, err := h.Wrc.IsRequestAllowlisted(ownerAddr, digest)