Erlang client set ssh key
Asked Answered
D

1

7

I'm using the :client API to connect to an external node and use code there remotely, the thing though is that I'm using Dokku for deployment and it would be really nice if I could specify a ssh key at runtime.

Right now my code looks something like this:

def start(host) do
  allow_boot to_char_list(host)
  {:ok, slave} = :slave.start(to_char_list(host), :slave, inet_loader_args)
  load_paths(slave)
  {:ok, slave}
end

inet_loader_args == ' -rsh ssh -loader inet -hosts #{master_node_ip} -setcookie #{:erlang.get_cookie}'

I've tried something like setting the -rsh argument to be "-rsh ssh -i /path/to/id_rsh" but it seems to ignore this entirely, I'm not exactly sure how it's implemented and the Erlang docs for :client are a little hard to understand for me (I can see it uses :ssh underneath somewhere, and that can take a "user_dir" argument which can contain a key file, but I'm not sure how to set that from :client)

Any ideas?

Despatch answered 29/11, 2015 at 18:52 Comment(7)
Sorry--is that "inet_loader_args ==" the literal code? If it is that's wrong. But I'm assuming you mean that's what it is equivalent to.Cholecystectomy
You're assuming right :)Despatch
Am I also correct in assuming that you're using single quotes around the value you're assigning to inet_loader_args? That's an important detail.Cholecystectomy
Yes, I'm transforming it with to_char_list/1Despatch
To be clear, the code works. The issue is that I'd like to set a custom path for the keyfile rather than the default ~/.ssh/id_rsaDespatch
Looking at slave.erl the -rsh argument is passed to :os.find_executable, which in your example would look for an executable ssh -i /path/to/id_rsh, which obviously doesn't exist. I think your best bet is to do something like -rsh /path/to/my/ssh-wrapper and have ssh-wrapper be a shell script that does exec ssh -i /path/to/id_rsh $@.Buckthorn
@MartinS. 👌 That didn't even occur to me, and totally fixes this issue. Thanks. If you want to make that into an answer I'll accept it :)Despatch
B
1

The -rsh option is intended to point to a different executable:

%% Alternative, if the master was started as
%% 'erl -sname xxx -rsh my_rsh...', then 'my_rsh' will be used instead
%% of 'rsh' (this is useful for systems where the rsh program is named
%% 'remsh').

These days people use ssh instead of rsh. (About 10 years ago the security team on a previous job required ssh even when both machines are on the same isolated network.) Since the command line interface is compatible, just pointing to a new executable generally works once you have the keys set up properly. So it makes sense to use the -rsh option to point to ssh instead.

It also seem logical that the argument could be used to pass other parameters to the ssh command as you attempted. However, the code assumes the string passed is the name of an executable in your PATH. It uses os:find_executable to look for an executable and ssh -i /path/to/id_rsh probably doesn't exist.

However, you can take advantage of this feature to point to any executable including a shell script. For instance, you could write a ssh-wrapper that looks something like:

#!/usr/bin/env ksh
exec ssh -i /path/to/id_rsh $@

Then use -rsh /path/to/my/ssh-wrapper so that :slave.start uses your wrapper with the proper ssh options specified. I've found the wrapper technique also makes future maintenance easier as the connection logic stays in one place.


Hat tip to this comment from Martin S.

Buckeen answered 27/11, 2019 at 17:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.