Remove pre-1.0 audit and protected request scaffolding

This commit is contained in:
npc0-hue
2026-08-20 23:42:02 +08:00
parent 40b35b05c7
commit a7e2e4c6c0
130 changed files with 526 additions and 3767 deletions
+16 -133
View File
@@ -10,7 +10,7 @@ import (
)
const (
maxAuditSummaryLength = 512
maxSummaryLength = 512
maxContactNoteLength = 160
maxMarketplaceKeywordSize = 80
maxMarketplaceListSize = 500
@@ -500,7 +500,7 @@ func validateGameClientBridgeManifest(field string, bridge domain.GameClientBrid
commandTypes := map[string]struct{}{}
for index, command := range bridge.Commands {
prefix := fmt.Sprintf("%s.commands[%d]", field, index)
if !clientManagerIdentifierPattern.MatchString(command.Type) || command.ProtectedRequest == nil && unsafeGameClientBridgeCommandType(command.Type) {
if !clientManagerIdentifierPattern.MatchString(command.Type) || unsafeGameClientBridgeCommandType(command.Type) {
violations = append(violations, prefix+".type is invalid or unsafe")
}
if _, exists := commandTypes[command.Type]; exists {
@@ -525,7 +525,6 @@ func validateGameClientBridgeManifest(field string, bridge domain.GameClientBrid
if command.MaxPayloadBytes <= 0 || command.MaxPayloadBytes > maxGameClientBridgePayloadSize {
violations = append(violations, prefix+".maxPayloadBytes is invalid")
}
violations = append(violations, validateGameClientBridgeProtectedRequest(prefix+".protectedRequest", command.ProtectedRequest, transports)...)
}
snapshotTypes := map[string]struct{}{}
for index, snapshot := range bridge.Snapshots {
@@ -625,7 +624,7 @@ func validateGameClientBridgeManifest(field string, bridge domain.GameClientBrid
violations = append(violations, prefix+".key is duplicated")
}
logProjectionKeys[projection.Key] = struct{}{}
violations = append(violations, validateGameClientBridgeLogProjection(prefix, projection, bridge.Commands, runtimeProfiles.ClientManagers)...)
violations = append(violations, validateGameClientBridgeLogProjection(prefix, projection)...)
}
dataPackKeys := map[string]struct{}{}
for index, dataPack := range bridge.DataPacks {
@@ -640,9 +639,9 @@ func validateGameClientBridgeManifest(field string, bridge domain.GameClientBrid
if dataPack.DatabaseUserVersion < 1 || len(dataPack.LogParserRefs) == 0 || len(dataPack.ConfigMapRefs) == 0 {
violations = append(violations, prefix+" must declare a database version and parser/config assets")
}
refs := append(domain.CopyStringSlice(dataPack.LogParserRefs), dataPack.ConfigMapRefs...)
refs = append(refs, dataPack.DataRefs...)
for _, ref := range refs {
refs := append(domain.CopyStringSlice(dataPack.LogParserRefs), dataPack.ConfigMapRefs...)
refs = append(refs, dataPack.DataRefs...)
for _, ref := range refs {
if !safeRelativeJSONRef(ref) {
violations = append(violations, prefix+" asset reference is invalid")
}
@@ -664,8 +663,8 @@ func validateGameClientBridgeManifest(field string, bridge domain.GameClientBrid
if !containsString(permissions, template.Permission) {
violations = append(violations, prefix+".permission must be declared by the plugin")
}
if template.ApprovalLevel != domain.GameClientBridgeApprovalLevelOperator && template.ApprovalLevel != domain.GameClientBridgeApprovalLevelPlatformAdmin {
violations = append(violations, prefix+".approvalLevel must require operator or platform-admin approval")
if template.ApprovalLevel != domain.GameClientBridgeApprovalLevelNone && template.ApprovalLevel != domain.GameClientBridgeApprovalLevelOperator && template.ApprovalLevel != domain.GameClientBridgeApprovalLevelPlatformAdmin {
violations = append(violations, prefix+".approvalLevel is invalid")
}
if template.Kind != domain.GameClientBridgeOperationKindRCON && template.Kind != domain.GameClientBridgeOperationKindSQLiteMutation {
violations = append(violations, prefix+".kind is invalid")
@@ -689,8 +688,8 @@ func validateGameClientBridgeManifest(field string, bridge domain.GameClientBrid
}
switch template.Kind {
case domain.GameClientBridgeOperationKindRCON:
if transport.Kind != "rcon" || !containsString(transport.Capabilities, domain.JobCapabilityRemoteRunProtectedRCON) {
violations = append(violations, prefix+" transport must be rcon with remote.run.protected.rcon capability")
if transport.Kind != "rcon" || !containsString(transport.Capabilities, domain.JobCapabilityRemoteRunRCONCommand) {
violations = append(violations, prefix+" transport must be rcon with remote.run.rcon.command capability")
}
if template.MaxRowsAffected != 0 {
violations = append(violations, prefix+".maxRowsAffected is only valid for sqlite-mutation")
@@ -822,7 +821,7 @@ func validateGameClientBridgeManifest(field string, bridge domain.GameClientBrid
return violations
}
func validateGameClientBridgeLogProjection(prefix string, projection domain.GameClientBridgeLogProjectionDeclaration, commands []domain.GameClientBridgeCommandDeclaration, clientManagers []domain.RuntimeClientManagerProfile) []string {
func validateGameClientBridgeLogProjection(prefix string, projection domain.GameClientBridgeLogProjectionDeclaration) []string {
var violations []string
if len(projection.StreamKeys) < 1 || len(projection.StreamKeys) > 64 {
violations = append(violations, prefix+".streamKeys must contain between 1 and 64 streams")
@@ -887,43 +886,6 @@ func validateGameClientBridgeLogProjection(prefix string, projection domain.Game
if presence.ActivityTarget != nil {
violations = append(violations, validateGameClientBridgeLogProjectionTarget(prefix+".presence.activityTarget", *presence.ActivityTarget, captures)...)
}
announcement := presence.Announcement
if !clientManagerIdentifierPattern.MatchString(announcement.ProfileKey) {
violations = append(violations, prefix+".presence.announcement.profileKey is invalid")
} else {
profileFound := false
for _, profile := range clientManagers {
if profile.Key == announcement.ProfileKey && containsString(profile.Health.RequiredCapabilities, "game-client.bridge") {
profileFound = true
break
}
}
if !profileFound {
violations = append(violations, prefix+".presence.announcement.profileKey must reference a declared game-client bridge profile")
}
}
var command *domain.GameClientBridgeCommandDeclaration
for index := range commands {
if commands[index].Type == announcement.CommandType {
command = &commands[index]
break
}
}
if command == nil {
violations = append(violations, prefix+".presence.announcement.commandType must reference a declared command")
}
if !gameClientBridgeFieldPattern.MatchString(announcement.TextField) {
violations = append(violations, prefix+".presence.announcement.textField is invalid")
} else if command != nil && command.ProtectedRequest != nil && command.ProtectedRequest.TextField != announcement.TextField {
violations = append(violations, prefix+".presence.announcement.textField must match the command protected request")
}
if strings.TrimSpace(announcement.NewTextTemplate) == "" || len([]rune(announcement.NewTextTemplate)) > 4096 {
violations = append(violations, prefix+".presence.announcement.newTextTemplate is empty or too large")
}
if strings.TrimSpace(announcement.ReturningTextTemplate) == "" || len([]rune(announcement.ReturningTextTemplate)) > 4096 {
violations = append(violations, prefix+".presence.announcement.returningTextTemplate is empty or too large")
}
return violations
}
@@ -1032,50 +994,6 @@ func unsafeGameClientBridgeCommandType(value string) bool {
return has("shell", "powershell", "script", "terminal", "execute", "exec", "eval") || has("command", "cmd", "process", "system", "os", "executor") && has("run")
}
func validateGameClientBridgeProtectedRequest(prefix string, request *domain.GameClientBridgeProtectedRequestDeclaration, transports map[string]domain.RuntimeTransportProfile) []string {
if request == nil {
return nil
}
var violations []string
if !oneOf(request.Kind, "sql", "rcon", "program") {
violations = append(violations, prefix+".kind is invalid")
}
for field, value := range map[string]string{"transportKey": request.TransportKey, "targetKey": request.TargetKey, "textField": request.TextField} {
if !validDistributionLogicalKey(value) || unsafeGameClientBridgePayloadKey(value) {
violations = append(violations, prefix+"."+field+" is invalid")
}
}
if request.MaxTextBytes < 1 || request.MaxTextBytes > maxGameClientBridgePayloadString {
violations = append(violations, prefix+".maxTextBytes is invalid")
}
transport, exists := transports[request.TransportKey]
if !exists {
return append(violations, prefix+".transportKey must reference a declared runtime transport profile")
}
if transport.TargetKey != request.TargetKey {
violations = append(violations, prefix+".targetKey must match the declared runtime transport profile")
}
wantKind, wantCapability := "", ""
switch request.Kind {
case "sql":
wantCapability = domain.JobCapabilityRemoteRunProtectedSQL
case "rcon":
wantKind, wantCapability = "rcon", domain.JobCapabilityRemoteRunProtectedRCON
case "program":
wantKind, wantCapability = "program", domain.JobCapabilityRemoteRunProgram
}
if request.Kind == "sql" && transport.Kind != "mysql" && transport.Kind != "sqlite" {
violations = append(violations, prefix+".transportKey must use mysql or sqlite for sql requests")
}
if wantKind != "" && transport.Kind != wantKind {
violations = append(violations, prefix+".transportKey does not match protected request kind")
}
if wantCapability != "" && !containsString(transport.Capabilities, wantCapability) {
violations = append(violations, prefix+".transportKey is missing required protected transport capability")
}
return violations
}
func emptyGameClientBridgeOperationMutation(value domain.GameClientBridgeOperationMutationDeclaration) bool {
return value.FieldKey == "" && value.TableKey == "" && value.IdentityKey == "" && value.ValueKey == "" && value.ConfirmationQueryKey == "" && value.AllowedValueType == "" && value.MinValue == 0 && value.MaxValue == 0
}
@@ -1744,12 +1662,7 @@ func ValidateJob(job domain.Job) error {
if job.ExecutionInput.SourceRCON != nil {
violations = append(violations, validateRuntimeSourceRCONPlan("executionInput.sourceRcon", job.ExecutionInput.SourceRCON)...)
isSourceCommand := job.Capability == domain.JobCapabilityRemoteRunRCONCommand
isProtectedRCON := job.Capability == domain.JobCapabilityRemoteRunProtectedRCON
wantAdapterKind := "rcon"
if isProtectedRCON {
wantAdapterKind = "protected-rcon"
}
if (!isSourceCommand && !isProtectedRCON) || job.ExecutionInput.RemoteAdapterKind != wantAdapterKind {
if !isSourceCommand || job.ExecutionInput.RemoteAdapterKind != "rcon" {
violations = append(violations, "executionInput.sourceRcon is allowed only for rcon jobs")
}
if job.RetryPolicy.MaxAttempts != 1 {
@@ -1766,8 +1679,8 @@ func ValidateJob(job domain.Job) error {
if len([]byte(job.ExecutionResult.Content)) > maxJobExecutionContentSize {
violations = append(violations, "executionResult.content is too large")
}
if len(job.ExecutionResult.AuditSummary) > maxAuditSummaryLength {
violations = append(violations, "executionResult.auditSummary is too long")
if len(job.ExecutionResult.Summary) > maxSummaryLength {
violations = append(violations, "executionResult.summary is too long")
}
if job.Capability == domain.JobCapabilityConfigWrite || job.Capability == domain.JobCapabilityFilesRead || job.Capability == domain.JobCapabilityFilesWrite {
if job.ServerInstanceID == "" {
@@ -1875,26 +1788,6 @@ func ValidateLogStream(stream domain.LogStream) error {
return finish(violations)
}
func ValidateAuditEvent(event domain.AuditEvent) error {
var violations []string
violations = appendRequired(violations, "id", event.ID)
violations = appendRequired(violations, "actorId", event.ActorID)
violations = appendRequired(violations, "action", event.Action)
violations = appendRequired(violations, "resourceKind", event.ResourceKind)
violations = appendRequired(violations, "resourceId", event.ResourceID)
violations = appendRequired(violations, "summary", event.Summary)
if !validAuditResult(event.Result) {
violations = append(violations, "result is invalid")
}
if len(event.Summary) > maxAuditSummaryLength {
violations = append(violations, "summary is too long")
}
if looksLikeRawSecret(event.Summary) {
violations = append(violations, "summary must be redacted")
}
return finish(violations)
}
func MissingCapabilities(actual []string, required []string) []string {
actualSet := make(map[string]struct{}, len(actual))
for _, capability := range actual {
@@ -2446,7 +2339,7 @@ func validPluginRunCapability(capability string) bool {
domain.JobCapabilityRemoteRunProcessStart, domain.JobCapabilityRemoteRunProcessStop,
domain.JobCapabilityRemoteRunDBMySQLQuery, domain.JobCapabilityRemoteRunDBSQLiteQuery,
domain.JobCapabilityRemoteRunLogsTransfer, domain.JobCapabilityRemoteRunRCONCommand,
domain.JobCapabilityRemoteRunProtectedSQL, domain.JobCapabilityRemoteRunProtectedRCON, domain.JobCapabilityRemoteRunProgram,
domain.JobCapabilityRemoteRunProtectedSQL, domain.JobCapabilityRemoteRunProgram,
domain.JobCapabilityRunSelfUpdate, domain.JobCapabilityDependenciesCheck, domain.JobCapabilityDependenciesInstall,
domain.JobCapabilityDeploymentPlan, domain.JobCapabilityDeploymentShellPosix, domain.JobCapabilityDeploymentShellPowerShell, domain.JobCapabilityDeploymentShellCmd,
domain.JobCapabilityClientManagerDeploy, domain.JobCapabilityClientManagerControl, domain.JobCapabilityClientManagerUpdate,
@@ -2479,8 +2372,7 @@ func remoteCapabilityRequiresInputRef(capability string) bool {
domain.JobCapabilityRemoteRunFilesWrite,
domain.JobCapabilityRemoteRunDBMySQLQuery,
domain.JobCapabilityRemoteRunDBSQLiteQuery,
domain.JobCapabilityRemoteRunRCONCommand, domain.JobCapabilityRemoteRunProtectedSQL,
domain.JobCapabilityRemoteRunProtectedRCON, domain.JobCapabilityRemoteRunProgram:
domain.JobCapabilityRemoteRunRCONCommand, domain.JobCapabilityRemoteRunProtectedSQL, domain.JobCapabilityRemoteRunProgram:
return true
default:
return false
@@ -2781,12 +2673,3 @@ func validLogStorageBackend(backend domain.LogStorageBackend) bool {
return false
}
}
func validAuditResult(result domain.AuditResult) bool {
switch result {
case domain.AuditResultSuccess, domain.AuditResultDenied, domain.AuditResultFailed, domain.AuditResultQueued:
return true
default:
return false
}
}