Is it possible to use inet_tls distribution _optionally_?

Hi, folks :wave:

I have a few Erlang nodes in my system and I have a few escripts that sometimes connect to them remotely. Imagine something like…

#!/usr/bin/env escript
%%! -sname external@localhost -setcookie cookie

main([NodeName]) ->
  Node = list_to_atom(NodeName ++ "@localhost"),
  io:format("~p ping? ~p\n", [Node, net_adm:ping(Node)]).

Sometimes those modules run on TLS distribution, so for the script to work, it must look like…

#!/usr/bin/env escript
%%! -sname external@localhost -setcookie cookie  -proto_dist inet_tls -ssl_dist_opt client_verify verify_peer server_verify verify_peer -ssl_dist_opt server_certfile server_cert.pem client_certfile server_cert.pem -ssl_dist_opt server_keyfile server_key.pem client_keyfile server_key.pem -ssl_dist_opt server_cacertfile ca_cert.pem client_cacertfile ca_cert.pem

%% (Yeah, I don't know how to use multiple lines for `%%!` either, but that's a different topic)

main([NodeName]) ->
  Node = list_to_atom(NodeName ++ "@localhost"),
  io:format("Is ~p up? ~p\n", [Node, net_adm:ping(Node)]).

In other words, they must be started with the inet_tls distribution protocol and all its parameters. But then, those scripts can’t ping the non-tls nodes.

The question is: Is there any way to write the scripts so that they can communicate with some nodes over inet_tls but with others over regular inet_tcp?

Furthermore, something like this…

#!/usr/bin/env escript

main([NodeName]) ->
  net_kernel:start('external@localhost', #{name_domain => shortnames}),
  erlang:set_cookie(cookie),
  Node = list_to_atom(NodeName ++ "@localhost"),
  io:format("Is ~p up? ~p\n", [Node, net_adm:ping(Node)]).

…does work for non-tls nodes, but I don’t seem to be able to tell net_kernel that I want to start it using inet_tls as the proto_dist param. For what I can find, net_kernel and friends pick that value from init:get_argument(proto_dist) and so far I could not find a way to set that once the VM is already started.

The obvious low-tech solution would be to have one script (bash or escript) invoke the TLS-enabled escript if needed.

Yeah… I ended up with something like this…

my_script.hrl

main([NodeName]) ->
  Node = list_to_atom(NodeName ++ "@localhost"),
  io:format("Is ~p up? ~p\n", [Node, net_adm:ping(Node)]).

my_script_tcp

#!/usr/bin/env escript
%%! -sname external@localhost -setcookie cookie
-include("my_script.hrl").

my_script_tls

#!/usr/bin/env escript
%%! -sname external@localhost -setcookie cookie  -proto_dist inet_tls -ssl_dist_opt client_verify verify_peer server_verify verify_peer -ssl_dist_opt server_certfile server_cert.pem client_certfile server_cert.pem -ssl_dist_opt server_keyfile server_key.pem client_keyfile server_key.pem -ssl_dist_opt server_cacertfile ca_cert.pem client_cacertfile ca_cert.pem
-include("my_script.hrl").

my_script

#!/usr/bin/bash

# I had not written this one yet,
# but the idea would be to use a parameter to figure out
# which one of the other two scripts to call and then call it.

But I don’t like this solution at all.

Rather than have two separate escripts, a bash script that sets ERL_AFLAGS appropriately before running the single escript would work, no?

1 Like

Oh, yeah! That looks like a great idea!
I’ll try it and, if it works, I’ll report here.
Thanks, @rlipscombe :fist_right::fist_left:

EDIT: It worked as a charm!! :star2:

1 Like