Files
browser/platform/validator/plugin_operations.go
T

76 lines
3.2 KiB
Go

package validator
import (
"strings"
"browser.local/platform/domain"
)
func ValidatePluginLifecycleInstallation(installation domain.PluginLifecycleInstallation) error {
var violations []string
violations = appendRequired(violations, "id", installation.ID)
violations = appendRequired(violations, "pluginId", installation.PluginID)
violations = appendRequired(violations, "serverInstanceId", installation.ServerInstanceID)
if !validPluginLifecycleState(installation.DesiredState) {
violations = append(violations, "desiredState is invalid")
}
if !validPluginLifecycleState(installation.CurrentState) {
violations = append(violations, "currentState is invalid")
}
if installation.LastOperation != "" && !validPluginLifecycleOperation(installation.LastOperation) {
violations = append(violations, "lastOperation is invalid")
}
for _, value := range []fieldString{{field: "compatibility", value: installation.Compatibility}, {field: "failureReason", value: installation.FailureReason}} {
if len(value.value) > maxProductionMessageLength || unsafeProductionText(value.value) {
violations = append(violations, value.field+" is unsafe")
}
}
return finish(violations)
}
func ValidatePluginLifecycleRequest(request domain.PluginLifecycleRequest) error {
var violations []string
violations = appendRequired(violations, "pluginId", request.PluginID)
violations = appendRequired(violations, "serverInstanceId", request.ServerInstanceID)
violations = appendRequired(violations, "idempotencyKey", request.IdempotencyKey)
if !validPluginLifecycleOperation(request.Operation) {
violations = append(violations, "operation is invalid")
}
for _, value := range []fieldString{{field: "targetVersion", value: request.TargetVersion}, {field: "idempotencyKey", value: request.IdempotencyKey}} {
if unsafeProductionText(value.value) {
violations = append(violations, value.field+" is unsafe")
}
}
return finish(violations)
}
func validPluginLifecycleState(state domain.PluginLifecycleState) bool {
switch state {
case domain.PluginLifecycleStatePending, domain.PluginLifecycleStateInstalled, domain.PluginLifecycleStateEnabled, domain.PluginLifecycleStateDisabled, domain.PluginLifecycleStateUpgrading, domain.PluginLifecycleStateRollingBack, domain.PluginLifecycleStateRetired, domain.PluginLifecycleStateFailed:
return true
default:
return false
}
}
func validPluginLifecycleOperation(operation domain.PluginLifecycleOperation) bool {
switch operation {
case domain.PluginLifecycleOperationInstall, domain.PluginLifecycleOperationEnable, domain.PluginLifecycleOperationDisable, domain.PluginLifecycleOperationUpgrade, domain.PluginLifecycleOperationRollback, domain.PluginLifecycleOperationRetire, domain.PluginLifecycleOperationDependencyCheck:
return true
default:
return false
}
}
func unsafeProductionText(value string) bool {
lower := strings.ToLower(value)
return containsUnsafeRuntimeSecret(value) ||
looksLikeRawHostPath(value) ||
strings.Contains(lower, "api key") ||
strings.Contains(lower, "apikey") ||
strings.Contains(lower, "provider base url") ||
strings.Contains(lower, "direct run") ||
strings.Contains(lower, "rcon password") ||
strings.Contains(lower, "dsn=")
}