Add per-role HTTP method scoping to minted tokens
Every token this engine mints is as powerful as the apps it can reach: a read-only integration can still write to the *arr. arrproxy v0.5.0 accepts a method scope at mint time, so let a role pin its tokens to it. - Add an optional role field methods, uppercase-normalized, de-duplicated and validated against the known HTTP methods at role write. - Forward the role's scope as methods on the arrproxy mint request and echo it in the creds response alongside apps/subject. - Omit the field entirely when a role has no scope, so an arrproxy predating method scoping sees an unchanged request. - Cover normalization, rejection, pass-through and the unscoped case.
This commit is contained in:
@@ -2,6 +2,7 @@ package arrstack
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -35,6 +36,38 @@ func TestClient_MintToken(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_MintToken_ForwardsMethods(t *testing.T) {
|
||||
m := newMockArrproxy(t)
|
||||
client, _ := newClient(&arrstackConfig{BaseURL: m.server.URL, AdminToken: m.adminToken})
|
||||
|
||||
if _, err := client.MintToken(context.Background(), mintTokenRequest{
|
||||
Subject: "vault:arrstack:readonly",
|
||||
Apps: []string{"sonarr"},
|
||||
Methods: []string{"GET", "HEAD"},
|
||||
TTLSeconds: 60,
|
||||
}); err != nil {
|
||||
t.Fatalf("MintToken: %v", err)
|
||||
}
|
||||
if strings.Join(m.lastRequest.Methods, ",") != "GET,HEAD" {
|
||||
t.Fatalf("expected methods forwarded, got %v", m.lastRequest.Methods)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_MintToken_RejectsUnknownMethod(t *testing.T) {
|
||||
m := newMockArrproxy(t)
|
||||
client, _ := newClient(&arrstackConfig{BaseURL: m.server.URL, AdminToken: m.adminToken})
|
||||
|
||||
_, err := client.MintToken(context.Background(), mintTokenRequest{
|
||||
Subject: "vault:arrstack:readonly",
|
||||
Apps: []string{"sonarr"},
|
||||
Methods: []string{"FETCH"},
|
||||
TTLSeconds: 60,
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatal("expected arrproxy to reject an unknown HTTP method")
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_MintToken_RejectsBadSubject(t *testing.T) {
|
||||
m := newMockArrproxy(t)
|
||||
client, _ := newClient(&arrstackConfig{BaseURL: m.server.URL, AdminToken: m.adminToken})
|
||||
|
||||
Reference in New Issue
Block a user