Complete platform management workflows

This commit is contained in:
npc0-hue
2026-07-14 16:39:37 +08:00
parent 7e05d0a4e7
commit 4f33f761a3
106 changed files with 11313 additions and 460 deletions
+398
View File
@@ -0,0 +1,398 @@
package service
import (
"encoding/json"
"errors"
"strings"
"testing"
"browser.local/platform/domain"
)
func TestCoreServiceGeneratesRunDistributionWithEncryptedSingletonKey(t *testing.T) {
svc, session, instance := newDistributionTestFixture(t)
distribution, err := svc.GenerateRunDistributionForSession(session, domain.RunDistributionGenerateRequest{
ServerInstanceID: instance.ID,
TargetOS: "linux",
TargetArch: "amd64",
IdempotencyKey: "idem-run-generate",
})
if err != nil {
t.Fatalf("generate run distribution: %v", err)
}
if distribution.KeyGeneration != 1 || distribution.SecretRef == "" || distribution.Status != domain.DistributionStatusAvailable {
t.Fatalf("unexpected run distribution: %+v", distribution)
}
keys, err := svc.store.EncryptedComponentKeys().List(domain.EncryptedComponentKeyFilter{
ServerInstanceID: instance.ID,
ComponentKind: domain.DistributionComponentRun,
Status: domain.ComponentKeyStatusActive,
})
if err != nil {
t.Fatalf("list component keys: %v", err)
}
if len(keys) != 1 || keys[0].Generation != 1 || !strings.HasPrefix(keys[0].EncryptedKey, "enc:v1:") {
t.Fatalf("expected one active encrypted run key, got %+v", keys)
}
config := readGeneratedPackageConfig(t, svc, session, distribution.ArtifactID)
if config.AuthKey == "" || config.AuthKey == keys[0].EncryptedKey || strings.Contains(distribution.SecretRef, config.AuthKey) {
t.Fatalf("run package key leaked through metadata or was not encrypted, config=%+v key=%+v distribution=%+v", config, keys[0], distribution)
}
auth, err := svc.AuthenticateComponent(domain.ComponentAuthenticationRequest{
ServerInstanceID: instance.ID,
ComponentKind: domain.DistributionComponentRun,
Generation: config.KeyGeneration,
Key: config.AuthKey,
})
if err != nil {
t.Fatalf("authenticate run: %v", err)
}
if !auth.Allowed {
t.Fatalf("expected current run key to authenticate, got %+v", auth)
}
second, err := svc.GenerateRunDistributionForSession(session, domain.RunDistributionGenerateRequest{
ServerInstanceID: instance.ID,
TargetOS: "linux",
TargetArch: "amd64",
IdempotencyKey: "idem-run-generate-second",
})
if err != nil {
t.Fatalf("generate second run distribution: %v", err)
}
if second.KeyGeneration != 1 || second.SecretRef != distribution.SecretRef {
t.Fatalf("expected second package to reuse current singleton key, got first=%+v second=%+v", distribution, second)
}
keys, err = svc.store.EncryptedComponentKeys().List(domain.EncryptedComponentKeyFilter{
ServerInstanceID: instance.ID,
ComponentKind: domain.DistributionComponentRun,
Status: domain.ComponentKeyStatusActive,
})
if err != nil || len(keys) != 1 {
t.Fatalf("expected one active key after second generation, keys=%+v err=%v", keys, err)
}
}
func TestCoreServiceResetRunKeyRevokesOldPackagesAndRequiresRegeneration(t *testing.T) {
svc, session, instance := newDistributionTestFixture(t)
distribution, err := svc.GenerateRunDistributionForSession(session, domain.RunDistributionGenerateRequest{
ServerInstanceID: instance.ID,
TargetOS: "linux",
TargetArch: "amd64",
IdempotencyKey: "idem-run-before-reset",
})
if err != nil {
t.Fatalf("generate run distribution: %v", err)
}
oldConfig := readGeneratedPackageConfig(t, svc, session, distribution.ArtifactID)
reset, err := svc.ResetComponentKeyForSession(session, domain.ComponentKeyResetRequest{
ServerInstanceID: instance.ID,
ComponentKind: domain.DistributionComponentRun,
})
if err != nil {
t.Fatalf("reset run key: %v", err)
}
if reset.Generation != 2 || reset.Status != domain.ComponentKeyStatusActive {
t.Fatalf("expected reset key generation 2, got %+v", reset)
}
oldDistribution, err := svc.store.RunDistributions().Get(distribution.ID)
if err != nil {
t.Fatalf("get old distribution: %v", err)
}
if oldDistribution.Status != domain.DistributionStatusRevoked {
t.Fatalf("expected old distribution revoked, got %+v", oldDistribution)
}
if _, err := svc.OpenArtifactDownloadForSession(session, domain.ArtifactDownloadReferenceRequest{ArtifactID: distribution.ArtifactID}); err == nil || !strings.Contains(err.Error(), "available") {
t.Fatalf("expected old artifact download to be unavailable, got %v", err)
}
auth, err := svc.AuthenticateComponent(domain.ComponentAuthenticationRequest{
ServerInstanceID: instance.ID,
ComponentKind: domain.DistributionComponentRun,
Generation: oldConfig.KeyGeneration,
Key: oldConfig.AuthKey,
})
if err != nil {
t.Fatalf("authenticate old key: %v", err)
}
if auth.Allowed || !strings.Contains(auth.Reason, "generation") {
t.Fatalf("expected old package authentication denial, got %+v", auth)
}
newDistribution, err := svc.GenerateRunDistributionForSession(session, domain.RunDistributionGenerateRequest{
ServerInstanceID: instance.ID,
TargetOS: "linux",
TargetArch: "amd64",
IdempotencyKey: "idem-run-after-reset",
})
if err != nil {
t.Fatalf("generate run distribution after reset: %v", err)
}
newConfig := readGeneratedPackageConfig(t, svc, session, newDistribution.ArtifactID)
if newDistribution.KeyGeneration != 2 || newConfig.AuthKey == oldConfig.AuthKey {
t.Fatalf("expected regenerated package with new generation/key, old=%+v new=%+v", oldConfig, newConfig)
}
auth, err = svc.AuthenticateComponent(domain.ComponentAuthenticationRequest{
ServerInstanceID: instance.ID,
ComponentKind: domain.DistributionComponentRun,
Generation: newConfig.KeyGeneration,
Key: newConfig.AuthKey,
})
if err != nil {
t.Fatalf("authenticate new key: %v", err)
}
if !auth.Allowed {
t.Fatalf("expected regenerated package to authenticate, got %+v", auth)
}
}
func TestCoreServiceBuildsClientManagerWithDistinctKeyAndAuditsSensitiveOperations(t *testing.T) {
svc, session, instance := newDistributionTestFixture(t)
runDistribution, err := svc.GenerateRunDistributionForSession(session, domain.RunDistributionGenerateRequest{
ServerInstanceID: instance.ID,
TargetOS: "linux",
TargetArch: "amd64",
IdempotencyKey: "idem-run-for-client",
})
if err != nil {
t.Fatalf("generate run distribution: %v", err)
}
if _, err := svc.OpenArtifactDownloadForSession(session, domain.ArtifactDownloadReferenceRequest{ArtifactID: runDistribution.ArtifactID}); err != nil {
t.Fatalf("open run download: %v", err)
}
runConfig := readGeneratedPackageConfig(t, svc, session, runDistribution.ArtifactID)
clientDistribution, err := svc.GenerateClientManagerDistributionForSession(session, domain.ClientManagerBuildRequest{
ServerInstanceID: instance.ID,
ProfileKey: "scum-client-manager",
TargetOS: "windows",
TargetArch: "amd64",
RepositoryURL: "https://github.com/F88888/scum_client.git",
SourceRevision: "main",
IdempotencyKey: "idem-client-manager",
})
if err != nil {
t.Fatalf("generate client-manager distribution: %v", err)
}
clientConfig := readGeneratedPackageConfig(t, svc, session, clientDistribution.ArtifactID)
if clientDistribution.KeyGeneration != 1 || clientDistribution.BuildJobID == "" || clientDistribution.Status != domain.DistributionStatusAvailable {
t.Fatalf("unexpected client-manager distribution: %+v", clientDistribution)
}
if clientConfig.AuthKey == runConfig.AuthKey || clientDistribution.SecretRef == runDistribution.SecretRef {
t.Fatalf("client-manager must use a distinct key/ref, run=%+v client=%+v", runConfig, clientConfig)
}
build, err := svc.store.ClientManagerBuildJobs().Get(clientDistribution.BuildJobID)
if err != nil {
t.Fatalf("get build job: %v", err)
}
if build.Status != domain.DistributionJobStatusSucceeded || build.RepositoryURL != "https://github.com/F88888/scum_client.git" || build.SourceRevision != "main" {
t.Fatalf("unexpected build job: %+v", build)
}
if build.LogsRef == "" || !strings.HasPrefix(build.LogsRef, "artifact://") {
t.Fatalf("expected redacted build log artifact ref, got %+v", build)
}
packagePayload := readClientManagerPackage(t, svc, session, clientDistribution.ArtifactID)
if packagePayload.Checkout.CheckoutRef != "branch/main" || packagePayload.Config.AuthKey != clientConfig.AuthKey || packagePayload.KeyFingerprint == "" {
t.Fatalf("expected package checkout metadata and injected config, got %+v", packagePayload)
}
if len(packagePayload.OutputArtifacts) == 0 || packagePayload.BuildLogRef != build.LogsRef {
t.Fatalf("expected output artifacts and build log ref, got %+v build=%+v", packagePayload, build)
}
buildLog := readArtifactString(t, svc, session, strings.TrimPrefix(build.LogsRef, "artifact://"))
for _, expected := range []string{"client-manager checkout prepared", "checkoutRef=branch/main", "dependencyCheck=typed build profile accepted", "configInjection=secret ref"} {
if !strings.Contains(buildLog, expected) {
t.Fatalf("expected build log to contain %q, got %q", expected, buildLog)
}
}
for _, forbidden := range []string{runConfig.AuthKey, clientConfig.AuthKey, "password=", "unix://", "tcp://", "/Users/", "mysql://", "sqlite://"} {
if strings.Contains(buildLog, forbidden) {
t.Fatalf("build log leaked forbidden fragment %q: %s", forbidden, buildLog)
}
}
_, err = svc.GenerateClientManagerDistributionForSession(session, domain.ClientManagerBuildRequest{
ServerInstanceID: instance.ID,
ProfileKey: "scum-client-manager",
TargetOS: "darwin",
TargetArch: "amd64",
RepositoryURL: "https://github.com/F88888/scum_client.git",
IdempotencyKey: "idem-client-manager-denied",
})
if err == nil || !strings.Contains(err.Error(), "targetOs") {
t.Fatalf("expected unsupported target denial, got %v", err)
}
if _, err := svc.ResetComponentKeyForSession(session, domain.ComponentKeyResetRequest{
ServerInstanceID: instance.ID,
ComponentKind: domain.DistributionComponentClientManager,
ComponentKey: "scum-client-manager",
}); err != nil {
t.Fatalf("reset client-manager key: %v", err)
}
auth, err := svc.AuthenticateComponent(domain.ComponentAuthenticationRequest{
ServerInstanceID: instance.ID,
ComponentKind: domain.DistributionComponentClientManager,
ComponentKey: "scum-client-manager",
Generation: clientConfig.KeyGeneration,
Key: clientConfig.AuthKey,
})
if err != nil {
t.Fatalf("authenticate old client key: %v", err)
}
if auth.Allowed {
t.Fatalf("expected old client-manager key to be denied after reset, got %+v", auth)
}
audits, err := svc.ListAuditEvents(domain.AuditEventFilter{ResourceID: instance.ID})
if err != nil {
t.Fatalf("list audits: %v", err)
}
actions := map[string]bool{}
for _, audit := range audits {
actions[audit.Action] = true
for _, forbidden := range []string{runConfig.AuthKey, clientConfig.AuthKey, "password=", "unix://", "/Users/"} {
if strings.Contains(audit.Summary, forbidden) {
t.Fatalf("audit leaked forbidden fragment %q in %+v", forbidden, audit)
}
}
}
for _, action := range []string{"run.generate", "run.download", "client-manager.build", "client-manager.build.denied", "runtime-key.reset"} {
if !actions[action] {
t.Fatalf("expected audit action %q in %+v", action, audits)
}
}
}
func newDistributionTestFixture(t *testing.T) (*CoreService, string, domain.ServerInstance) {
t.Helper()
svc := newTestCoreService()
plugin, endpoint := createPluginAndRunEndpoint(t, svc)
plugin.SupportedOS = []string{"linux", "windows"}
plugin.DeclaredPermissions = append(plugin.DeclaredPermissions,
"server.run.distribution",
"server.client-manager.manage",
"server.dependencies.manage",
)
plugin.RequiredRunCapabilities = append(plugin.RequiredRunCapabilities,
domain.JobCapabilityRunSelfUpdate,
domain.JobCapabilityDependenciesCheck,
domain.JobCapabilityDependenciesInstall,
domain.JobCapabilityLogsBackfill,
)
plugin.BridgeActions = append(plugin.BridgeActions,
string(domain.PluginBridgeActionRunDistribution),
string(domain.PluginBridgeActionClientManager),
string(domain.PluginBridgeActionDependenciesRequest),
string(domain.PluginBridgeActionLogsBackfillRequest),
)
if err := svc.store.GamePlugins().Update(plugin); err != nil {
t.Fatalf("update plugin fixture: %v", err)
}
endpoint.Capabilities = append(endpoint.Capabilities,
domain.JobCapabilityRunSelfUpdate,
domain.JobCapabilityDependenciesCheck,
domain.JobCapabilityDependenciesInstall,
domain.JobCapabilityLogsBackfill,
)
if err := svc.store.RunEndpoints().Update(endpoint); err != nil {
t.Fatalf("update endpoint fixture: %v", err)
}
session := createServiceUserAndLogin(t, svc, domain.User{
ID: "user-distribution-owner",
DisplayName: "Distribution Owner",
Email: "distribution-owner@example.test",
Roles: []string{"server-owner"},
PasswordHash: "secret-password",
})
instance, err := svc.CreateServerInstanceForSession(session, domain.ServerInstance{
ID: "server-distribution",
PluginID: plugin.ID,
RunEndpointID: endpoint.ID,
Name: "Distribution Server",
State: domain.ServerInstanceStateReady,
})
if err != nil {
t.Fatalf("create distribution server: %v", err)
}
return svc, session, instance
}
func readGeneratedPackageConfig(t *testing.T, svc *CoreService, session string, artifactID string) generatedPackageConfig {
t.Helper()
content, err := svc.ReadArtifactContentForSession(session, domain.ArtifactContentRequest{ArtifactID: artifactID})
if err != nil {
t.Fatalf("read artifact content: %v", err)
}
var config generatedPackageConfig
if err := json.Unmarshal(content.Payload, &config); err != nil {
t.Fatalf("unmarshal generated config: %v", err)
}
if config.AuthKey == "" {
var packagePayload generatedClientManagerPackage
if err := json.Unmarshal(content.Payload, &packagePayload); err != nil {
t.Fatalf("unmarshal generated client-manager package: %v", err)
}
config = packagePayload.Config
}
if config.AuthKey == "" || config.SecretRef == "" || config.KeyGeneration <= 0 {
t.Fatalf("generated package config is incomplete: %+v", config)
}
return config
}
func readClientManagerPackage(t *testing.T, svc *CoreService, session string, artifactID string) generatedClientManagerPackage {
t.Helper()
content, err := svc.ReadArtifactContentForSession(session, domain.ArtifactContentRequest{ArtifactID: artifactID})
if err != nil {
t.Fatalf("read client-manager package content: %v", err)
}
var packagePayload generatedClientManagerPackage
if err := json.Unmarshal(content.Payload, &packagePayload); err != nil {
t.Fatalf("unmarshal generated client-manager package: %v", err)
}
return packagePayload
}
func readArtifactString(t *testing.T, svc *CoreService, session string, artifactID string) string {
t.Helper()
content, err := svc.ReadArtifactContentForSession(session, domain.ArtifactContentRequest{ArtifactID: artifactID})
if err != nil {
t.Fatalf("read artifact content: %v", err)
}
return string(content.Payload)
}
func TestCoreServiceDeniesRunDistributionWithoutPluginDeclaration(t *testing.T) {
svc := newTestCoreService()
plugin, endpoint := createPluginAndRunEndpoint(t, svc)
session := createServiceUserAndLogin(t, svc, domain.User{
ID: "user-distribution-denied",
DisplayName: "Distribution Denied",
Email: "distribution-denied@example.test",
Roles: []string{"server-owner"},
PasswordHash: "secret-password",
})
instance, err := svc.CreateServerInstanceForSession(session, domain.ServerInstance{
ID: "server-distribution-denied",
PluginID: plugin.ID,
RunEndpointID: endpoint.ID,
Name: "Distribution Denied Server",
State: domain.ServerInstanceStateReady,
})
if err != nil {
t.Fatalf("create denied server: %v", err)
}
_, err = svc.GenerateRunDistributionForSession(session, domain.RunDistributionGenerateRequest{
ServerInstanceID: instance.ID,
TargetOS: "linux",
TargetArch: "amd64",
IdempotencyKey: "idem-run-denied",
})
if !errors.Is(err, ErrForbidden) {
t.Fatalf("expected plugin declaration denial, got %v", err)
}
}