Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ mix run --no-halt
}
```

The BEAM runtime keeps orchestration, leases, placement, reconnect, and manual recovery. OpenCV, ffmpeg, model runtimes, and similar heavy dependencies stay in the profile image or a prewarmed node cache.
The BEAM runtime keeps orchestration, leases, placement, reconnect, and manual recovery. OpenCV, ffmpeg, model runtimes, and similar heavy dependencies stay in the profile image or a prewarmed node cache. When a manifest selects an execution profile, the profile owns OpenShell security settings such as image, policy, remote access, SSH key, workspace reuse, upload path, pool, GPU, and capability settings; manifest values for those fields are ignored. Relative `policy` and `ssh_key` paths in a profile are expanded on the runtime node, not against a submitted payload bundle.

### Inspect Jobs and Events

Expand Down
26 changes: 23 additions & 3 deletions lib/mirror_neuron/execution/profile.ex
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ defmodule MirrorNeuron.Execution.Profile do
"video_codecs",
"required_capabilities"
]
@profile_local_cli_path_keys ["policy", "ssh_key"]

def apply_to_config(config) when is_map(config) do
case profile_name(config) do
Expand All @@ -38,9 +39,9 @@ defmodule MirrorNeuron.Execution.Profile do
name ->
case fetch(name) do
{:ok, profile} ->
profile
|> config_from_profile()
|> Map.merge(stringify_map(config))
config
|> manifest_config_for_profile()
|> Map.merge(config_from_profile(profile))
|> Map.put("execution_profile", name)

{:error, _reason} ->
Expand Down Expand Up @@ -158,6 +159,25 @@ defmodule MirrorNeuron.Execution.Profile do
|> stringify_map()
|> normalize_openshell_aliases()
|> Map.merge(openshell)
|> resolve_profile_local_cli_paths()
end

defp manifest_config_for_profile(config) do
config
|> stringify_map()
|> Map.drop(@openshell_keys)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Drop manifest-supplied sandbox CLI with profile

When an untrusted manifest selects an execution_profile and also sets sandbox_cli, this filtering keeps that key because it is not in @openshell_keys; OpenShell later uses Map.get(config, "sandbox_cli", ...) as the executable passed to System.cmd. That leaves the manifest able to choose the local OpenShell binary even though the profile is now supposed to own sandbox/security settings, so add this invocation control key to the profile-owned/drop set or otherwise prevent manifest override.

Useful? React with 👍 / 👎.

end

defp resolve_profile_local_cli_paths(config) do
Enum.reduce(@profile_local_cli_path_keys, config, fn key, acc ->
case Map.get(acc, key) do
value when is_binary(value) and value != "" ->
Map.put(acc, key, Path.expand(value))

_other ->
acc
end
end)
end

defp normalize_openshell_aliases(config) do
Expand Down
48 changes: 47 additions & 1 deletion tests/unit/execution_profile_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,57 @@ defmodule MirrorNeuron.Execution.ProfileTest do
assert config["pool"] == "opencv_gpu"
assert config["pool_slots"] == 1
assert config["gpu"] == true
assert config["policy"] == "policies/video-egress.yaml"
assert config["policy"] == Path.expand("policies/video-egress.yaml")
assert config["reuse_shared_sandbox"] == true
assert config["persistent_workspace"] == true
end

test "profile OpenShell settings override manifest supplied sandbox settings" do
Application.put_env(:mirror_neuron, :execution_profiles, %{
"privileged-video" => %{
"image" => "registry.local/video-guardian:stable",
"pool" => "opencv_gpu",
"pool_slots" => 2,
"policy" => "operator/policies/video.yaml",
"ssh_key" => "operator/keys/video.pem",
"remote" => %{"host" => "gpu-runtime.internal"},
"reuse_shared_sandbox" => true,
"persistent_workspace" => false,
"sandbox_upload_path" => "/srv/mirror-neuron/uploads"
}
})

config =
Profile.apply_to_config(%{
"execution_profile" => "privileged-video",
"from" => "attacker.local/unsafe:latest",
"image" => "attacker.local/unsafe-alias:latest",
"pool" => "default",
"pool_slots" => 99,
"policy" => "payloads/attacker-policy.yaml",
"ssh_key" => "payloads/attacker-key.pem",
"remote" => %{"host" => "attacker.example"},
"reuse_shared_sandbox" => false,
"persistent_workspace" => true,
"sandbox_upload_path" => "/tmp/attacker",
"runner_module" => ConfigEchoRunner,
"output_message_type" => nil
})

assert config["execution_profile"] == "privileged-video"
assert config["from"] == "registry.local/video-guardian:stable"
assert config["pool"] == "opencv_gpu"
assert config["pool_slots"] == 2
assert config["policy"] == Path.expand("operator/policies/video.yaml")
assert config["ssh_key"] == Path.expand("operator/keys/video.pem")
assert config["remote"] == %{"host" => "gpu-runtime.internal"}
assert config["reuse_shared_sandbox"] == true
assert config["persistent_workspace"] == false
assert config["sandbox_upload_path"] == "/srv/mirror-neuron/uploads"
assert config["runner_module"] == ConfigEchoRunner
assert Map.has_key?(config, "output_message_type")
end

test "capability matching accepts only healthy nodes that advertise the required profile" do
Application.put_env(:mirror_neuron, :execution_profiles, %{
"opencv-video-guardian" => %{
Expand Down
Loading