Skip to content
Permalink
Browse files Browse the repository at this point in the history
Merge pull request from GHSA-2cmx-rr54-88g5
Signed-off-by: Brooks Townsend <brooks@cosmonic.com>

resolved code warning

Signed-off-by: Brooks Townsend <brooks@cosmonic.com>
  • Loading branch information
brooksmtownsend committed Jan 21, 2022
1 parent 1d06e0e commit fd07262
Show file tree
Hide file tree
Showing 21 changed files with 3,290 additions and 17 deletions.
33 changes: 29 additions & 4 deletions host_core/lib/host_core/actors/actor_module.ex
Expand Up @@ -189,7 +189,12 @@ defmodule HostCore.Actors.ActorModule do
}, inv}

_ ->
case perform_invocation(agent, inv["operation"], inv["msg"]) do
case validate_invocation(
agent,
inv["origin"]["link_name"],
inv["origin"]["contract_id"]
)
|> perform_invocation(inv["operation"], inv["msg"]) do
{:ok, response} ->
{%{
msg: response,
Expand Down Expand Up @@ -253,7 +258,22 @@ defmodule HostCore.Actors.ActorModule do
|> prepare_module(agent, oci)
end

defp perform_invocation(agent, operation, payload) do
# Actor-to-actor calls are always allowed
defp validate_invocation(agent, "", "") do
{agent, true}
end

# Actor-to-actor calls are always allowed
defp validate_invocation(agent, nil, nil) do
{agent, true}
end

defp validate_invocation(agent, _link_name, contract_id) do
caps = Agent.get(agent, fn contents -> contents.claims.caps end)
{agent, Enum.member?(caps, contract_id)}
end

defp perform_invocation({agent, true}, operation, payload) do
Logger.debug("performing invocation #{operation}")
raw_state = Agent.get(agent, fn content -> content end)

Expand All @@ -280,6 +300,11 @@ defmodule HostCore.Actors.ActorModule do
|> to_guest_call_result(agent)
end

defp perform_invocation({_agent, false}, _operation, _payload) do
Logger.error("Actor does not have proper capabilities to receive this invocation")
{:error, "actor is missing capability claims"}
end

defp to_guest_call_result({:ok, [res]}, agent) do
state = Agent.get(agent, fn content -> content end)

Expand All @@ -298,7 +323,7 @@ defmodule HostCore.Actors.ActorModule do

res =
try do
perform_invocation(agent, @op_health_check, payload)
perform_invocation({agent, true}, @op_health_check, payload)
rescue
_e -> {:error, "Failed to invoke actor module"}
end
Expand Down Expand Up @@ -359,7 +384,7 @@ defmodule HostCore.Actors.ActorModule do
target = inv["target"]

evt_type =
if Map.get(inv_r, "error") == nil do
if Map.get(inv_r, :error) == nil do
"invocation_succeeded"
else
"invocation_failed"
Expand Down
2 changes: 1 addition & 1 deletion host_core/mix.exs
@@ -1,7 +1,7 @@
defmodule HostCore.MixProject do
use Mix.Project

@app_vsn "0.52.1"
@app_vsn "0.52.2"

def project do
[
Expand Down
59 changes: 59 additions & 0 deletions host_core/test/e2e/echo_test.exs
Expand Up @@ -12,6 +12,8 @@ defmodule HostCore.E2E.EchoTest do

@echo_key HostCoreTest.Constants.echo_key()
@echo_path HostCoreTest.Constants.echo_path()
@echo_unpriv_key HostCoreTest.Constants.echo_unpriv_key()
@echo_unpriv_path HostCoreTest.Constants.echo_unpriv_path()
@httpserver_link HostCoreTest.Constants.default_link()
@httpserver_path HostCoreTest.Constants.httpserver_path()

Expand Down Expand Up @@ -70,4 +72,61 @@ defmodule HostCore.E2E.EchoTest do
HTTPoison.start()
{:ok, _resp} = HTTPoison.get("http://localhost:8080/foo/bar")
end

test "unprivileged actor cannot receive undeclared invocations", %{:evt_watcher => evt_watcher} do
on_exit(fn -> HostCore.Host.purge() end)

{:ok, bytes} = File.read(@echo_unpriv_path)
{:ok, _pid} = HostCore.Actors.ActorSupervisor.start_actor(bytes)
:ok = HostCoreTest.EventWatcher.wait_for_actor_start(evt_watcher, @echo_unpriv_key)

actor_count =
Map.get(HostCore.Actors.ActorSupervisor.all_actors(), @echo_unpriv_key)
|> length

assert actor_count == 1

{:ok, bytes} = File.read(@httpserver_path)
{:ok, par} = HostCore.WasmCloud.Native.par_from_bytes(bytes |> IO.iodata_to_binary())
httpserver_key = par.claims.public_key
httpserver_contract = par.contract_id

# OK to put link definition with no claims information
assert HostCore.Linkdefs.Manager.put_link_definition(
@echo_key,
httpserver_contract,
@httpserver_link,
httpserver_key,
%{PORT: "8083"}
) == :ok

{:ok, _pid} =
HostCore.Providers.ProviderSupervisor.start_provider_from_file(
@httpserver_path,
@httpserver_link
)

:ok =
HostCoreTest.EventWatcher.wait_for_provider_start(
evt_watcher,
httpserver_contract,
@httpserver_link,
httpserver_key
)

# For now, okay to put a link definition without proper claims
assert HostCore.Linkdefs.Manager.put_link_definition(
@echo_unpriv_key,
httpserver_contract,
@httpserver_link,
httpserver_key,
%{PORT: "8084"}
) == :ok

HTTPoison.start()
{:ok, resp} = HTTPoison.get("http://localhost:8084/foobar")

assert resp.body == ""
assert resp.status_code == 500
end
end
2 changes: 0 additions & 2 deletions host_core/test/e2e/kvcounter_test.exs
Expand Up @@ -214,8 +214,6 @@ defmodule HostCore.E2E.KVCounterTest do

{:ok, resp} = HTTPoison.get("http://localhost:8082/foobar")

IO.inspect(resp)

assert resp.body ==
"{\"error\":\"Host send error Invocation not authorized: missing claim for wasmcloud:keyvalue\"}"

Expand Down
2 changes: 2 additions & 0 deletions host_core/test/fixtures/actors/echo_unpriv/.cargo/config.toml
@@ -0,0 +1,2 @@
[build]
target = "wasm32-unknown-unknown"
2 changes: 2 additions & 0 deletions host_core/test/fixtures/actors/echo_unpriv/.gitignore
@@ -0,0 +1,2 @@
target
build
@@ -0,0 +1 @@
SAADV6UE6ILDAJ5TW2LCD2M6MNCMOLLCLQ5OLD53BZA2GTWJKWELBMWA3U
1 change: 1 addition & 0 deletions host_core/test/fixtures/actors/echo_unpriv/.keys/module.nk
@@ -0,0 +1 @@
SMAMZ6LKVEXGCLWVF3A37IRWF6JDV6CI27TB2K3YFX3FO47AEA3QVVZ4JA

0 comments on commit fd07262

Please sign in to comment.