// SPDX-License-Identifier: AGPL-3.0-only package deploy import ( "context" "reflect" "strings" "testing" ) type recordingRunner struct { name string args []string } func (r *recordingRunner) Run(_ context.Context, _ string, _ map[string]string, name string, args ...string) ([]byte, error) { r.name = name r.args = append([]string(nil), args...) return nil, nil } func TestStartCandidateUsesArgumentVectorAndHardenedUnit(t *testing.T) { runner := &recordingRunner{} operator := SystemOperator{Runner: runner} env := map[string]string{"Z_ENV": "safe value", "A_ENV": "first"} if err := operator.StartCandidate(context.Background(), "example-tend-candidate.service", "/opt/example/releases/sha256-a/app", "/etc/tend/environment/example.env", env); err != nil { t.Fatal(err) } if runner.name != "systemd-run" { t.Fatalf("command=%q", runner.name) } required := []string{"--property=DynamicUser=yes", "--property=NoNewPrivileges=yes", "--property=ProtectSystem=strict", "--property=MemoryDenyWriteExecute=yes", "--property=CapabilityBoundingSet=", "--property=EnvironmentFile=/etc/tend/environment/example.env", "--setenv", "A_ENV=first", "--setenv", "Z_ENV=safe value", "--", "/opt/example/releases/sha256-a/app"} cursor := 0 for _, arg := range runner.args { if cursor < len(required) && arg == required[cursor] { cursor++ } } if cursor != len(required) { t.Fatalf("arguments omitted ordered security boundary: %#v", runner.args) } if reflect.DeepEqual(runner.args, []string{"sh", "-c"}) { t.Fatal("candidate command used a shell") } if strings.Contains(strings.Join(runner.args, "\n"), "SUPER_SECRET") { t.Fatal("candidate arguments exposed a secret value") } }