[erlang-patches] EEP Light: Option to override private key lookup when using Erlang ssh client
Hans Nilsson R
hans.r.nilsson@REDACTED
Mon Nov 9 18:10:14 CET 2015
On 11/08/2015 04:01 PM, Vipin Nair wrote:
> EEP Light: Option to override private key lookup when using Erlang ssh client
>
>
> * Why do we need this new feature?
>
> Currently, ssh:connect/3,4 gets the user's private key from either the
> default directory (~/.ssh) of the user or from the directory specified in the
> 'user_dir' ssh connect option. The files names are always assumed to be
> openssh default file names, for example, `id_rsa` or `id_dsa`. This makes the
> API inflexible as we are required to create a directory and write the key
> data to the file system when we are connecting to a SSH server as a third
> party. An API to specify the private key is immensely useful when the
> private keys are stored in, say, a database.
You seem unaware of that both the client and the server get the keys
from callbacks defined by the ssh_client_key_api and the
ssh_server_key_api. The option key_cb defines the module to use for
ssh:connect or ssh:daemon.
The default callback module is ssh_file, which implements reading and
writing of keys to and from files compatible with OpenSSH.
You can write plugins to fetch keys from a database, fetch from files
with names of your choice or even hard code them using those behaviours.
See
http://www.erlang.org/doc/man/ssh_client_key_api.html
http://www.erlang.org/doc/man/ssh_server_key_api.html
-Hans
>
>
> * How did you solve it?
>
> - Implementation description
>
> To address the above problem, new ssh connect options `rsa_priv_key` and
> `dsa_priv_key` are proposed. The connect API will look like:
>
> ssh:connect("localhost", 22, [{user, "[USERNAME]"},
> {rsa_priv_key,
> <<"[BINARY_KEY_DATA]">>}]).
>
> If `rsa_priv_key` is specified and RSA is used for ssh negotiation,
> instead of reading the key from the `id_rsa` file, we use the key
> specified above. (This key could be protected by a passphrase and it is
> the system's responsibility to decrypt it.) `dsa_priv_key` will work
> similarly. See below for handling of ECDSA keys and known_hosts file.
>
> A pull request with a partial implementation of this proposal along with
> tests is on github[1].
>
> - Why you choose to implement it the way you did?
>
> The above solution is in the similar vein as some of the existing API's.
> For example, when password authentication is used to connect to a server,
> the ssh connect option `password` is used to specify the password.
> Similarly, for encrypted private keys, the passphrase is specified using
> ssh connect options `rsa_pass_phrase` and `dsa_pass_phrase`.
>
> - Other possible implementations considered
>
> Binary(iodata) key data can be passed onto file:open with `ram` mode
> specified which lets us treat an object in memory as a file. We can build
> a solution around this feature.
>
> SSH connect option only lets specify the user directory using the
> `user_dir` option and *not* the individual files. File names are assumed
> to be openssh defaults. We could change user dir to also accept a
> proplist of individual file names/iodata.
>
> Current definition -> user_dir() :: string()
>
> Proposed definition -> user_dir() :: string() |
> [{key_file() :: string() | iodata()}]
>
> Where
>
> key_file() :: id_rsa | id_dsa | id_ecdsa |
> known_hosts
>
> Considering we can pass either the file name or iodata with key contents,
> we'll have to limit file API usage to the ones that work with both of
> them. For example, ssh_file:read_ssh_file/1 uses file:read_file/1 which
> is not compatible with iodata() input.
>
> I haven't given enough thought to this solution so it is possible that I
> could be missing something obvious. In my opinion, the first solution
> proposed above is cleaner way to solve this problem.
>
>
> * Risks or uncertain artifacts?
>
> - Describe known incompatibilities
>
> Introducing the new connect options does not introduce an
> incompatibility, is fully backward compatible and does not affect
> consumers of the existing API in any way.
>
> - Describe uncertainties that are not fully understood or unclear.
>
> ECDSA keys can be handled by introducing similar options above. The
> proposed options names are `ecdsa_sha2_nistp256_priv_key`,
> `ecdsa_sha2_nistp384_priv_key` and `ecdsa_sha2_nistp521_priv_key`.
>
> A new option `known_hosts` can be introduced for specifying known_hosts
> as an API. The value corresponding to this key would be a list of known
> server public keys.
>
> </proposal>
>
> Some background: I am implementing a ssh multiplexer[2] and as a consumer of
> this API, I wasn't very happy. I thought about what a better API (IMO) could
> look like and took a stab at implementing it.
>
> [1]: https://github.com/erlang/otp/pull/884
> [2]: https://github.com/swvist/hss
>
>
More information about the erlang-patches
mailing list