64d9b89dcd
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.
53 lines
1.6 KiB
Go
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)
|
|
}
|
|
}
|