refactor(scum): declare protected run requests
This commit is contained in:
@@ -420,10 +420,14 @@ func validateGameClientBridgeManifest(field string, bridge domain.GameClientBrid
|
||||
violations = append(violations, prefix+".profileKey must reference a declared Client Manager profile")
|
||||
}
|
||||
}
|
||||
transports := map[string]domain.RuntimeTransportProfile{}
|
||||
for _, transport := range runtimeProfiles.TransportProfiles {
|
||||
transports[transport.Key] = transport
|
||||
}
|
||||
commandTypes := map[string]struct{}{}
|
||||
for index, command := range bridge.Commands {
|
||||
prefix := fmt.Sprintf("%s.commands[%d]", field, index)
|
||||
if !clientManagerIdentifierPattern.MatchString(command.Type) || unsafeGameClientBridgeCommandType(command.Type) {
|
||||
if !clientManagerIdentifierPattern.MatchString(command.Type) || command.ProtectedRequest == nil && unsafeGameClientBridgeCommandType(command.Type) {
|
||||
violations = append(violations, prefix+".type is invalid or unsafe")
|
||||
}
|
||||
if _, exists := commandTypes[command.Type]; exists {
|
||||
@@ -448,6 +452,7 @@ 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 {
|
||||
@@ -468,10 +473,6 @@ func validateGameClientBridgeManifest(field string, bridge domain.GameClientBrid
|
||||
}
|
||||
}
|
||||
queryTemplates := map[string]domain.GameClientBridgeQueryTemplateDeclaration{}
|
||||
transports := map[string]domain.RuntimeTransportProfile{}
|
||||
for _, transport := range runtimeProfiles.TransportProfiles {
|
||||
transports[transport.Key] = transport
|
||||
}
|
||||
for index, template := range bridge.QueryTemplates {
|
||||
prefix := fmt.Sprintf("%s.queryTemplates[%d]", field, index)
|
||||
if !clientManagerIdentifierPattern.MatchString(template.Key) {
|
||||
@@ -649,6 +650,50 @@ 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 ValidatePluginBridgeAuthorizeRequest(request domain.PluginBridgeAuthorizeRequest) error {
|
||||
var violations []string
|
||||
violations = appendRequired(violations, "pluginId", request.PluginID)
|
||||
@@ -1902,6 +1947,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.JobCapabilityRunSelfUpdate, domain.JobCapabilityDependenciesCheck, domain.JobCapabilityDependenciesInstall,
|
||||
domain.JobCapabilityDeploymentPlan, domain.JobCapabilitySCUMDeploymentPlan, domain.JobCapabilityDeploymentShellPosix, domain.JobCapabilityDeploymentShellPowerShell, domain.JobCapabilityDeploymentShellCmd,
|
||||
domain.JobCapabilityClientManagerDeploy, domain.JobCapabilityClientManagerControl, domain.JobCapabilityClientManagerUpdate,
|
||||
@@ -1934,7 +1980,8 @@ func remoteCapabilityRequiresInputRef(capability string) bool {
|
||||
domain.JobCapabilityRemoteRunFilesWrite,
|
||||
domain.JobCapabilityRemoteRunDBMySQLQuery,
|
||||
domain.JobCapabilityRemoteRunDBSQLiteQuery,
|
||||
domain.JobCapabilityRemoteRunRCONCommand:
|
||||
domain.JobCapabilityRemoteRunRCONCommand, domain.JobCapabilityRemoteRunProtectedSQL,
|
||||
domain.JobCapabilityRemoteRunProtectedRCON, domain.JobCapabilityRemoteRunProgram:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user