Files
vault-plugin-secrets-ghp/scopes_test.go
T
unkin-agent 64d9b89dcd
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Scaffold ghp secrets engine modelled on vault-plugin-secrets-gitea
Mints ephemeral, scoped ghp access tokens via ghp's admin token API
(POST /api/tokens), bound to a Vault lease and revoked on lease
expiry (DELETE /api/tokens/{id}).

- config: base_url + write-only admin_token (ghpsvc_ service token),
  TLS settings; verifies the token is a ghp admin on write. No
  rotate-root: the service token is static and operator-managed.
- roles: token_type (agent/proxy), installation_id, app_record_id,
  repositories, scopes (permission:level), session_prefix, ttl/max_ttl.
- creds: mint a lease-bound token; ghp-side duration bounded by the
  lease ceiling as defence in depth.
- secret ghp_token: idempotent revoke + lease renew.
- Unit tests (config/role/creds/client/scopes/revocation), mock-ghp
  e2e on Vault + OpenBao, Woodpecker pre-commit/build/test/release,
  Makefile patch/minor/major, nfpm RPM packaging.
2026-08-15 19:13:44 +10:00

53 lines
1.6 KiB
Go

package ghp
import (
"strings"
"testing"
)
func TestNormalizeScopes(t *testing.T) {
cases := []struct {
name string
in []string
want []string
wantErr bool
}{
{"single", []string{"contents:read"}, []string{"contents:read"}, false},
{"trim+level-case", []string{" pull_requests:Write "}, []string{"pull_requests:write"}, false},
{"dedupe-identical", []string{"contents:read", "contents:read"}, []string{"contents:read"}, false},
{"multi", []string{"contents:read", "issues:write"}, []string{"contents:read", "issues:write"}, false},
{"empty-input", nil, []string{}, false},
{"blank-entries", []string{"", " "}, []string{}, false},
{"no-level", []string{"contents"}, nil, true},
{"bad-level", []string{"contents:admin"}, nil, true},
{"empty-perm", []string{":read"}, nil, true},
{"conflict", []string{"contents:read", "contents:write"}, nil, true},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
got, err := normalizeScopes(c.in)
if c.wantErr {
if err == nil {
t.Fatalf("expected error, got %v", got)
}
return
}
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if strings.Join(got, ",") != strings.Join(c.want, ",") {
t.Errorf("normalizeScopes(%v) = %v, want %v", c.in, got, c.want)
}
})
}
}
func TestScopeString(t *testing.T) {
if got := scopeString(nil); got != "" {
t.Errorf("scopeString(nil) = %q, want empty", got)
}
if got := scopeString([]string{"contents:read", "issues:write"}); got != "contents:read,issues:write" {
t.Errorf("scopeString = %q", got)
}
}