mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-15 09:01:31 +00:00
0a1d837f40
* feat(bedrock): gate Ochre models behind per-account access grants Self-host models were invokable by any authenticated account: tieredCatalog returned them unconditionally and no runtime router checked the caller. GetFoundationModel also described models the caller could not use. Add a bedrock-model-access JetStream KV bucket holding presence-only grants, resolved through a new AccessResolver. Access is deny-by-default: a gateway with no store configured falls back to DenyAllAccessResolver, so an unconfigured deployment serves nothing rather than everything. The system account bypasses grants, matching how quotas exempt it. All four runtime routers share one grantedCatalogEntry gate so they cannot drift on who may invoke what. List and describe agree: an ungranted model is absent from ListFoundationModels and reported as ResourceNotFoundException by GetFoundationModel, so the error cannot confirm a model exists. Administration lands on two surfaces: Grant/Revoke/ListModelAccess actions on the spinifex gateway service for the UI, and `spx admin ochre access` for operators and provisioning, which opens the bucket over NATS directly rather than requiring a SigV4 client the CLI does not have. * feat(bedrock): seed the admin account's model grants at gateway start Deny-by-default left a fresh install with a catalog nobody could see, and the first cut filled that gap from ansible — which is a dev tool, so any install that never ran it came up unusable. Seed from the product instead: on start awsgw grants the platform admin account the full catalog, once, behind a marker key in the same bucket. The marker makes it a bootstrap step rather than a policy: tenant accounts still begin with no access, and an operator who revokes a grant does not have it restored by the next restart. Grants are written before the marker so a crash midway repeats the idempotent grants rather than leaving a half-seeded account, and the marker is a conditional create so only the first node to reach it need win. Seeding is best-effort: a KV failure logs and leaves the gateway serving, and the next start retries because the marker is written only on success. * test(bedrock): cover the model-access CLI and gateway admin actions Route the access CLI runners through the same loadConfigAndConnectFn / ochreExit seam the weights runners use, so grant, revoke and list can be driven against an embedded JetStream server, and add gateway tests for the grant admin actions including the non-admin denial.
69 lines
2.0 KiB
Go
69 lines
2.0 KiB
Go
//go:build e2e
|
|
|
|
// Package bedrock is the Ochre (AWS-Bedrock) E2E suite. Hermetic API-shape and
|
|
// provider-translation parity (Anthropic Messages / vLLM OpenAI wire formats)
|
|
// is covered by the gateway_bedrock unit tests; this suite exercises
|
|
// ListFoundationModels/GetFoundationModel against any running cluster and
|
|
// gates real Converse calls on backend availability (self-host GPU or a live
|
|
// Anthropic key), so CI parity holds without requiring either to be present.
|
|
//
|
|
// Model access is deny-by-default, so the cluster's test account must hold
|
|
// grants or every assertion here reduces to "empty catalog, access denied".
|
|
// awsgw seeds the platform admin account with the full catalog on first
|
|
// start, so a suite running as that account needs no setup; running as a
|
|
// tenant account needs
|
|
// `spx admin ochre access grant --account-id <id> --all-models` first.
|
|
package bedrock
|
|
|
|
import (
|
|
"os"
|
|
"sync"
|
|
"testing"
|
|
|
|
"github.com/mulgadc/spinifex/tests/e2e/harness"
|
|
)
|
|
|
|
// Package-scoped singleton fixture, built lazily by requireBedrockFixture and
|
|
// torn down by TestMain after the run.
|
|
var (
|
|
pkgFixOnce sync.Once
|
|
pkgFix *Fixture
|
|
pkgFixErr error
|
|
)
|
|
|
|
// Fixture carries per-process state shared across every Test* in this package.
|
|
type Fixture struct {
|
|
Env *harness.Env
|
|
AWS *harness.AWSClient
|
|
Account string
|
|
}
|
|
|
|
func TestMain(m *testing.M) {
|
|
os.Exit(m.Run())
|
|
}
|
|
|
|
// requireBedrockFixture returns the package-scoped Fixture, building it on
|
|
// first call. Skips the calling test if SPINIFEX_E2E is unset.
|
|
func requireBedrockFixture(t *testing.T) *Fixture {
|
|
t.Helper()
|
|
pkgFixOnce.Do(func() {
|
|
if os.Getenv("SPINIFEX_E2E") == "" {
|
|
return
|
|
}
|
|
env := harness.LoadEnv(t)
|
|
awsCli := harness.NewAWSClient(t, env)
|
|
pkgFix = &Fixture{
|
|
Env: env,
|
|
AWS: awsCli,
|
|
Account: harness.IAMAccountID(t, awsCli),
|
|
}
|
|
})
|
|
if pkgFixErr != nil {
|
|
t.Fatalf("bedrock fixture init failed: %v", pkgFixErr)
|
|
}
|
|
if pkgFix == nil {
|
|
t.Skip("bedrock fixture unavailable (SPINIFEX_E2E unset)")
|
|
}
|
|
return pkgFix
|
|
}
|