Compare commits
2 Commits
6944ff05e0
...
bdacd9905e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bdacd9905e | ||
|
|
85bf788307 |
@@ -1,4 +1,4 @@
|
|||||||
import Config
|
import Config
|
||||||
|
|
||||||
config :frajtano,
|
config :frajtano,
|
||||||
initial_peers: []
|
initial_backing_agents: []
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
;;
|
;;
|
||||||
spawn)
|
spawn)
|
||||||
shift
|
shift
|
||||||
run rpc ":ok = Frajtano.Agent.spawn_peer({\"/usr/bin/env\", [$(list "$@")]})"
|
run rpc ":ok = Frajtano.Agent.spawn_backing_agent({\"/usr/bin/env\", [$(list "$@")]})"
|
||||||
;;
|
;;
|
||||||
socket)
|
socket)
|
||||||
echo $FRAJTANO_DIR/agent.sock
|
echo $FRAJTANO_DIR/agent.sock
|
||||||
|
|||||||
@@ -42,18 +42,18 @@
|
|||||||
default = "${config.home.homeDirectory}/.ssh/frajtano";
|
default = "${config.home.homeDirectory}/.ssh/frajtano";
|
||||||
type = lib.types.path;
|
type = lib.types.path;
|
||||||
};
|
};
|
||||||
initialPeers = lib.mkOption {
|
initialBackingAgents = lib.mkOption {
|
||||||
description = "initially spawned peers - will be passed to /usr/bin/env";
|
description = "initially spawned backing_agents - will be passed to /usr/bin/env";
|
||||||
type = with lib.types; listOf (listOf str);
|
type = with lib.types; listOf (listOf str);
|
||||||
default = [];
|
default = [];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = let
|
config = let
|
||||||
peers = lib.strings.concatMapStringsSep ", " (args: ''{:spawn, {"${pkgs.coreutils}/bin/env", [${lib.concatMapStringsSep ", " (s: ''~S{${s}}'') args}]}}'') cfg.initialPeers;
|
backing_agents = lib.strings.concatMapStringsSep ", " (args: ''{:spawn, {"${pkgs.coreutils}/bin/env", [${lib.concatMapStringsSep ", " (s: ''~S{${s}}'') args}]}}'') cfg.initialBackingAgents;
|
||||||
configFile = pkgs.writeText "config.exs" ''
|
configFile = pkgs.writeText "config.exs" ''
|
||||||
import Config
|
import Config
|
||||||
config :frajtano, initial_peers: [${peers}]
|
config :frajtano, initial_backing_agents: [${backing_agents}]
|
||||||
'';
|
'';
|
||||||
in lib.mkIf cfg.enable {
|
in lib.mkIf cfg.enable {
|
||||||
home.sessionVariables.FRAJTANO_DIR = cfg.dir;
|
home.sessionVariables.FRAJTANO_DIR = cfg.dir;
|
||||||
|
|||||||
40
lib/agent.ex
40
lib/agent.ex
@@ -1,5 +1,5 @@
|
|||||||
defmodule Frajtano.Agent do
|
defmodule Frajtano.Agent do
|
||||||
alias Frajtano.Peer
|
alias Frajtano.BackingAgent
|
||||||
use GenServer
|
use GenServer
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
@@ -15,49 +15,49 @@ defmodule Frajtano.Agent do
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def initial_peers() do
|
def initial_backing_agents() do
|
||||||
initial_peers = Application.fetch_env!(:frajtano, :initial_peers)
|
initial_backing_agents = Application.fetch_env!(:frajtano, :initial_backing_agents)
|
||||||
|> Enum.map(&GenServer.call(__MODULE__, {:add_peer, &1}))
|
|> Enum.map(&GenServer.call(__MODULE__, {:add_backing_agent, &1}))
|
||||||
Logger.info("Started initial peers: #{inspect initial_peers}")
|
Logger.info("Started initial backing_agents: #{inspect initial_backing_agents}")
|
||||||
end
|
end
|
||||||
|
|
||||||
# select: list of specs, where specs are a tuple of match, guards, and outputs
|
# select: list of specs, where specs are a tuple of match, guards, and outputs
|
||||||
# match is {key, pid, value}, :"$1" is a match variable
|
# match is {key, pid, value}, :"$1" is a match variable
|
||||||
def peer_paths() do
|
def backing_agent_paths() do
|
||||||
Registry.select(Frajtano.Peers, [{{:"$1", :_, :_}, [], [:"$1"]}])
|
Registry.select(Frajtano.BackingAgents, [{{:"$1", :_, :_}, [], [:"$1"]}])
|
||||||
end
|
end
|
||||||
|
|
||||||
def peer_pids() do
|
def backing_agent_pids() do
|
||||||
Registry.select(Frajtano.Peers, [{{:_, :"$1", :_}, [], [:"$1"]}])
|
Registry.select(Frajtano.BackingAgents, [{{:_, :"$1", :_}, [], [:"$1"]}])
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def handle_call({:identities}, _from, _state) do
|
def handle_call({:identities}, _from, _state) do
|
||||||
idents =
|
idents =
|
||||||
Task.async_stream(
|
Task.async_stream(
|
||||||
peer_pids(),
|
backing_agent_pids(),
|
||||||
&{&1, Peer.identities(&1)},
|
&{&1, BackingAgent.identities(&1)},
|
||||||
ordered: false,
|
ordered: false,
|
||||||
on_timeout: :kill_task
|
on_timeout: :kill_task
|
||||||
)
|
)
|
||||||
|
|
||||||
idents = for {:ok, {peer, {:ok, idents}}} <- idents, do: {idents, peer}
|
idents = for {:ok, {backing_agent, {:ok, idents}}} <- idents, do: {idents, backing_agent}
|
||||||
|
|
||||||
{
|
{
|
||||||
:reply,
|
:reply,
|
||||||
{:ok, Enum.flat_map(idents, &elem(&1, 0))},
|
{:ok, idents |> Enum.flat_map(&elem(&1, 0)) |> Enum.uniq},
|
||||||
for({idents, peer} <- idents, {key, _comment} <- idents, into: %{}, do: {key, peer})
|
for({idents, backing_agent} <- idents, {key, _comment} <- idents, into: %{}, do: {key, backing_agent})
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def handle_call({:sign, {key, _, _} = req}, _from, state) do
|
def handle_call({:sign, {key, _, _} = req}, _from, state) do
|
||||||
{:reply, Peer.sign(state[key], req), state}
|
{:reply, BackingAgent.sign(state[key], req), state}
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def handle_call({:add_peer, spec}, _from, state) do
|
def handle_call({:add_backing_agent, spec}, _from, state) do
|
||||||
case Peer.start(spec) do
|
case BackingAgent.start(spec) do
|
||||||
{:ok, _} -> {:reply, :ok, state}
|
{:ok, _} -> {:reply, :ok, state}
|
||||||
{:error, error} -> {:reply, {:error, error}, state}
|
{:error, error} -> {:reply, {:error, error}, state}
|
||||||
end
|
end
|
||||||
@@ -73,10 +73,10 @@ defmodule Frajtano.Agent do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def assimilate(path) do
|
def assimilate(path) do
|
||||||
GenServer.call(__MODULE__, {:add_peer, {:socket, path}})
|
GenServer.call(__MODULE__, {:add_backing_agent, {:socket, path}})
|
||||||
end
|
end
|
||||||
|
|
||||||
def spawn_peer(spec) do
|
def spawn_backing_agent(spec) do
|
||||||
GenServer.call(__MODULE__, {:add_peer, {:spawn, spec}})
|
GenServer.call(__MODULE__, {:add_backing_agent, {:spawn, spec}})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -17,12 +17,12 @@ defmodule Frajtano.Supervisor do
|
|||||||
@impl true
|
@impl true
|
||||||
def init(:ok) do
|
def init(:ok) do
|
||||||
children = [
|
children = [
|
||||||
{DynamicSupervisor, name: Frajtano.PeerSupervisor},
|
{DynamicSupervisor, name: Frajtano.BackingAgentSupervisor},
|
||||||
{Registry, keys: :unique, name: Frajtano.Peers},
|
{Registry, keys: :unique, name: Frajtano.BackingAgents},
|
||||||
Frajtano.Agent,
|
Frajtano.Agent,
|
||||||
{Task.Supervisor, name: Frajtano.ClientSupervisor},
|
{Task.Supervisor, name: Frajtano.ClientSupervisor},
|
||||||
{Frajtano.Listener, [Application.fetch_env!(:frajtano, :listen_path)]},
|
{Frajtano.Listener, [Application.fetch_env!(:frajtano, :listen_path)]},
|
||||||
{Task, &Frajtano.Agent.initial_peers/0},
|
{Task, &Frajtano.Agent.initial_backing_agents/0},
|
||||||
:systemd.ready(),
|
:systemd.ready(),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
22
lib/peer.ex
22
lib/peer.ex
@@ -1,4 +1,4 @@
|
|||||||
defmodule Frajtano.Peer do
|
defmodule Frajtano.BackingAgent do
|
||||||
alias Frajtano.Proto
|
alias Frajtano.Proto
|
||||||
require Logger
|
require Logger
|
||||||
use GenServer, restart: :temporary
|
use GenServer, restart: :temporary
|
||||||
@@ -17,7 +17,7 @@ defmodule Frajtano.Peer do
|
|||||||
|
|
||||||
children = [
|
children = [
|
||||||
Supervisor.child_spec({MuonTrap.Daemon, [executable, args ++ [path]]}, restart: :temporary, significant: true),
|
Supervisor.child_spec({MuonTrap.Daemon, [executable, args ++ [path]]}, restart: :temporary, significant: true),
|
||||||
Supervisor.child_spec({Frajtano.Peer, {path, :spawned, {executable, args}}}, restart: :permanent)
|
Supervisor.child_spec({Frajtano.BackingAgent, {path, :spawned, {executable, args}}}, restart: :permanent)
|
||||||
]
|
]
|
||||||
|
|
||||||
Supervisor.init(children, strategy: :one_for_all, auto_shutdown: :any_significant)
|
Supervisor.init(children, strategy: :one_for_all, auto_shutdown: :any_significant)
|
||||||
@@ -25,19 +25,19 @@ defmodule Frajtano.Peer do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def start({:socket, path}) do
|
def start({:socket, path}) do
|
||||||
DynamicSupervisor.start_child(Frajtano.PeerSupervisor, {__MODULE__, {path}})
|
DynamicSupervisor.start_child(Frajtano.BackingAgentSupervisor, {__MODULE__, {path}})
|
||||||
end
|
end
|
||||||
|
|
||||||
def start({:spawn, spec}) do
|
def start({:spawn, spec}) do
|
||||||
Logger.info("Spawning #{inspect spec}")
|
Logger.info("Spawning #{inspect spec}")
|
||||||
DynamicSupervisor.start_child(Frajtano.PeerSupervisor, {Spawner, spec})
|
DynamicSupervisor.start_child(Frajtano.BackingAgentSupervisor, {Spawner, spec})
|
||||||
end
|
end
|
||||||
|
|
||||||
def start_link({path}) do
|
def start_link({path}) do
|
||||||
GenServer.start_link(__MODULE__, {path}, name: {:via, Registry, {Frajtano.Peers, path}})
|
GenServer.start_link(__MODULE__, {path}, name: {:via, Registry, {Frajtano.BackingAgents, path}})
|
||||||
end
|
end
|
||||||
def start_link({_, _, _} = spec) do
|
def start_link({_, _, _} = spec) do
|
||||||
GenServer.start_link(__MODULE__, spec, name: {:via, Registry, {Frajtano.Peers, spec}})
|
GenServer.start_link(__MODULE__, spec, name: {:via, Registry, {Frajtano.BackingAgents, spec}})
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
@@ -112,12 +112,12 @@ defmodule Frajtano.Peer do
|
|||||||
{:stop, {:error, e}, %{}}
|
{:stop, {:error, e}, %{}}
|
||||||
end
|
end
|
||||||
|
|
||||||
def identities(peer) do
|
def identities(backing_agent) do
|
||||||
ref = make_ref()
|
ref = make_ref()
|
||||||
send(peer, {:send, {:agentc_request_identities, nil}, {self(), ref}})
|
send(backing_agent, {:send, {:agentc_request_identities, nil}, {self(), ref}})
|
||||||
# Needs to be less than the timeout in Frajtano.Agent.identities on the Task.async_stream call
|
# Needs to be less than the timeout in Frajtano.Agent.identities on the Task.async_stream call
|
||||||
# That's 5000 by default
|
# That's 5000 by default
|
||||||
timer = Process.send_after(peer, :timeout, 4500)
|
timer = Process.send_after(backing_agent, :timeout, 4500)
|
||||||
|
|
||||||
receive do
|
receive do
|
||||||
{^ref, msg} ->
|
{^ref, msg} ->
|
||||||
@@ -132,13 +132,13 @@ defmodule Frajtano.Peer do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def sign(peer, request) do
|
def sign(backing_agent, request) do
|
||||||
# Signing may take some time, as a password may need to be entered or similar
|
# Signing may take some time, as a password may need to be entered or similar
|
||||||
# There is therefore no timeout
|
# There is therefore no timeout
|
||||||
# If something requests identities afterwards, it will timeout, which also kills this signature request
|
# If something requests identities afterwards, it will timeout, which also kills this signature request
|
||||||
# The SSH agent protocol strict ordering leaves fun problems with timeouts, as it turns out
|
# The SSH agent protocol strict ordering leaves fun problems with timeouts, as it turns out
|
||||||
ref = make_ref()
|
ref = make_ref()
|
||||||
send(peer, {:send, {:agentc_sign_request, request}, {self(), ref}})
|
send(backing_agent, {:send, {:agentc_sign_request, request}, {self(), ref}})
|
||||||
|
|
||||||
receive do
|
receive do
|
||||||
{^ref, msg} -> msg
|
{^ref, msg} -> msg
|
||||||
|
|||||||
Reference in New Issue
Block a user