Keep run logs opaque and streamline transfers
This commit is contained in:
@@ -89,7 +89,7 @@ func TestLoadUsesPackagedIdentityOverEnvironment(t *testing.T) {
|
||||
t.Setenv("RUN_REGISTRATION_TOKEN", "stale-token")
|
||||
t.Setenv("RUN_SERVER_INSTANCE_ID", "stale-server")
|
||||
t.Setenv("RUN_PLUGIN_ID", "stale-plugin")
|
||||
t.Setenv("RUN_COMPONENT_KIND", "client-manager")
|
||||
t.Setenv("RUN_COMPONENT_KIND", "stale-kind")
|
||||
t.Setenv("RUN_COMPONENT_KEY", "stale-profile")
|
||||
t.Setenv("RUN_KEY_GENERATION", "7")
|
||||
t.Setenv("RUN_VERSION", "stale-version")
|
||||
|
||||
@@ -11,8 +11,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
PackageComponentRun = "run"
|
||||
PackageComponentClientManager = "client-manager"
|
||||
PackageComponentRun = "run"
|
||||
|
||||
PackageConfigEnv = "RUN_PACKAGE_CONFIG"
|
||||
)
|
||||
@@ -94,7 +93,7 @@ func LoadPackageConfigBesideExecutable() (PackageConfig, bool, error) {
|
||||
|
||||
func ValidatePackageConfig(cfg PackageConfig) error {
|
||||
var violations []string
|
||||
if cfg.Kind != PackageComponentRun && cfg.Kind != PackageComponentClientManager {
|
||||
if cfg.Kind != PackageComponentRun {
|
||||
violations = append(violations, "kind is invalid")
|
||||
}
|
||||
if !safeIdentifier(cfg.ServerInstanceID) {
|
||||
@@ -109,13 +108,10 @@ func ValidatePackageConfig(cfg PackageConfig) error {
|
||||
if cfg.ProfileKey != "" && !safeLogicalKey(cfg.ProfileKey) {
|
||||
violations = append(violations, "profileKey is invalid")
|
||||
}
|
||||
if cfg.Kind == PackageComponentClientManager && cfg.ProfileKey == "" {
|
||||
violations = append(violations, "profileKey is required for client-manager packages")
|
||||
}
|
||||
if !safeRuntimeTarget(cfg.TargetOS, cfg.TargetArch) {
|
||||
violations = append(violations, "target platform is invalid")
|
||||
}
|
||||
if !strings.HasPrefix(cfg.SecretRef, "secret://runtime-keys/") || containsUnsafeDiagnosticText(cfg.SecretRef) {
|
||||
if !strings.HasPrefix(cfg.SecretRef, "secret://runtime-keys/") || strings.ContainsAny(cfg.SecretRef, " \t\r\n") {
|
||||
violations = append(violations, "secretRef is invalid")
|
||||
}
|
||||
if cfg.KeyGeneration <= 0 {
|
||||
@@ -124,9 +120,6 @@ func ValidatePackageConfig(cfg PackageConfig) error {
|
||||
if strings.TrimSpace(cfg.AuthKey) == "" {
|
||||
violations = append(violations, "authKey is required")
|
||||
}
|
||||
if containsUnsafeDiagnosticText(cfg.AuthKey) {
|
||||
violations = append(violations, "authKey contains unsafe content")
|
||||
}
|
||||
if len(violations) > 0 {
|
||||
return fmt.Errorf("invalid run package config: %s", strings.Join(violations, "; "))
|
||||
}
|
||||
@@ -165,7 +158,7 @@ func (cfg PackageConfig) Identity() PackageIdentity {
|
||||
}
|
||||
}
|
||||
|
||||
func (cfg PackageConfig) RedactedDiagnostics() map[string]string {
|
||||
func (cfg PackageConfig) IdentityDiagnostics() map[string]string {
|
||||
identity := cfg.Identity()
|
||||
return map[string]string{
|
||||
"kind": identity.Kind,
|
||||
@@ -188,7 +181,7 @@ func AuthenticatePackageGeneration(pkg PackageConfig, auth ComponentAuthResult)
|
||||
return fmt.Errorf("component authentication scope does not match package")
|
||||
}
|
||||
if !auth.Allowed {
|
||||
return fmt.Errorf("component authentication rejected: %s", redactedReason(auth.Reason))
|
||||
return fmt.Errorf("component authentication rejected: %s", auth.Reason)
|
||||
}
|
||||
if auth.KeyGeneration != pkg.KeyGeneration {
|
||||
return fmt.Errorf("component key generation is no longer current")
|
||||
@@ -196,11 +189,8 @@ func AuthenticatePackageGeneration(pkg PackageConfig, auth ComponentAuthResult)
|
||||
return nil
|
||||
}
|
||||
|
||||
func packageComponentKey(pkg PackageConfig) string {
|
||||
if pkg.Kind == PackageComponentRun {
|
||||
return ""
|
||||
}
|
||||
return strings.TrimSpace(pkg.ProfileKey)
|
||||
func packageComponentKey(PackageConfig) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func fingerprint(value string) string {
|
||||
@@ -210,7 +200,7 @@ func fingerprint(value string) string {
|
||||
|
||||
func safeIdentifier(value string) bool {
|
||||
value = strings.TrimSpace(value)
|
||||
if value == "" || len(value) > 120 || containsUnsafeDiagnosticText(value) {
|
||||
if value == "" || len(value) > 120 {
|
||||
return false
|
||||
}
|
||||
for _, char := range value {
|
||||
@@ -228,7 +218,7 @@ func safePluginID(value string) bool {
|
||||
|
||||
func safeLogicalKey(value string) bool {
|
||||
value = strings.TrimSpace(value)
|
||||
if value == "" || len(value) > 120 || strings.HasPrefix(value, "/") || strings.Contains(value, "..") || strings.Contains(value, `\`) || containsUnsafeDiagnosticText(value) {
|
||||
if value == "" || len(value) > 120 || strings.HasPrefix(value, "/") || strings.Contains(value, "..") || strings.Contains(value, `\`) {
|
||||
return false
|
||||
}
|
||||
for _, char := range value {
|
||||
@@ -253,20 +243,3 @@ func safeRuntimeTarget(osName string, arch string) bool {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func containsUnsafeDiagnosticText(value string) bool {
|
||||
normalized := strings.ToLower(value)
|
||||
for _, marker := range []string{"/users/", "/.ssh/", "password=", "apikey", "api_key", "bearer ", "sk-", "unix://", "tcp://", "mysql://", "sqlite://"} {
|
||||
if strings.Contains(normalized, marker) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func redactedReason(value string) string {
|
||||
if containsUnsafeDiagnosticText(value) {
|
||||
return "[redacted]"
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
@@ -30,14 +30,14 @@ func TestLoadPackageConfigAppliesServerScopedIdentity(t *testing.T) {
|
||||
if cfg.RegistrationToken != "opaque-runtime-key" || cfg.RunEndpointID != "run-server-1" || cfg.ServerInstanceID != "server-1" || cfg.ComponentKey != "" || cfg.KeyGeneration != 3 {
|
||||
t.Fatalf("expected package identity to be applied, got %+v", cfg)
|
||||
}
|
||||
diagnostics := pkg.RedactedDiagnostics()
|
||||
diagnostics := pkg.IdentityDiagnostics()
|
||||
for _, value := range diagnostics {
|
||||
if strings.Contains(value, "opaque-runtime-key") || strings.Contains(value, "/Users/") || strings.Contains(value, "password=") {
|
||||
t.Fatalf("diagnostics exposed sensitive value: %+v", diagnostics)
|
||||
}
|
||||
}
|
||||
if diagnostics["keyFingerprint"] == "" || diagnostics["secretRef"] != "secret://runtime-keys/server-1/run/current" {
|
||||
t.Fatalf("expected redacted key fingerprint and secret ref, got %+v", diagnostics)
|
||||
t.Fatalf("expected key fingerprint and logical secret ref, got %+v", diagnostics)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,8 +56,7 @@ func TestLoadPackageConfigRejectsUnsafeOrIncompletePackages(t *testing.T) {
|
||||
"old zero generation": func(cfg PackageConfig) PackageConfig { cfg.KeyGeneration = 0; return cfg },
|
||||
"raw path": func(cfg PackageConfig) PackageConfig { cfg.ServerInstanceID = "/Users/tasia/server"; return cfg },
|
||||
"socket": func(cfg PackageConfig) PackageConfig { cfg.SecretRef = "unix:///tmp/run.sock"; return cfg },
|
||||
"secret auth": func(cfg PackageConfig) PackageConfig { cfg.AuthKey = "password=raw"; return cfg },
|
||||
"client missing key": func(cfg PackageConfig) PackageConfig { cfg.Kind = PackageComponentClientManager; return cfg },
|
||||
"legacy component": func(cfg PackageConfig) PackageConfig { cfg.Kind = "client-manager"; return cfg },
|
||||
}
|
||||
for name, mutate := range cases {
|
||||
if err := ValidatePackageConfig(mutate(valid)); err == nil {
|
||||
@@ -66,6 +65,22 @@ func TestLoadPackageConfigRejectsUnsafeOrIncompletePackages(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPackageConfigTreatsAuthKeyAsOpaqueValue(t *testing.T) {
|
||||
cfg := PackageConfig{
|
||||
Kind: PackageComponentRun,
|
||||
ServerInstanceID: "server-1",
|
||||
PluginID: "game.scum",
|
||||
TargetOS: "windows",
|
||||
TargetArch: "amd64",
|
||||
SecretRef: "secret://runtime-keys/server-1/run/current",
|
||||
KeyGeneration: 1,
|
||||
AuthKey: "password=raw sk-test-value bearer literal",
|
||||
}
|
||||
if err := ValidatePackageConfig(cfg); err != nil {
|
||||
t.Fatalf("authKey must be treated as opaque package data, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthenticatePackageGenerationRejectsStalePackages(t *testing.T) {
|
||||
pkg := PackageConfig{
|
||||
Kind: PackageComponentRun,
|
||||
@@ -102,15 +117,16 @@ func TestAuthenticatePackageGenerationRejectsStalePackages(t *testing.T) {
|
||||
|
||||
func TestLoadPackageConfigFromEnv(t *testing.T) {
|
||||
path := writePackageConfig(t, PackageConfig{
|
||||
Kind: PackageComponentClientManager,
|
||||
Kind: PackageComponentRun,
|
||||
ServerInstanceID: "server-1",
|
||||
PluginID: "game.scum",
|
||||
ProfileKey: "scum-client-manager",
|
||||
RunEndpointID: "run-server-1",
|
||||
ProfileKey: "run-local",
|
||||
TargetOS: "windows",
|
||||
TargetArch: "amd64",
|
||||
SecretRef: "secret://runtime-keys/server-1/client-manager/scum-client-manager/current",
|
||||
SecretRef: "secret://runtime-keys/server-1/run/current",
|
||||
KeyGeneration: 4,
|
||||
AuthKey: "opaque-client-key",
|
||||
AuthKey: "opaque-run-key",
|
||||
})
|
||||
t.Setenv(PackageConfigEnv, path)
|
||||
|
||||
@@ -118,7 +134,7 @@ func TestLoadPackageConfigFromEnv(t *testing.T) {
|
||||
if err != nil || !ok {
|
||||
t.Fatalf("expected env package config, ok=%v err=%v", ok, err)
|
||||
}
|
||||
if cfg.Kind != PackageComponentClientManager || cfg.ProfileKey != "scum-client-manager" {
|
||||
if cfg.Kind != PackageComponentRun || cfg.ProfileKey != "run-local" {
|
||||
t.Fatalf("unexpected package config: %+v", cfg)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user