Skip to content

Commit 499cc07

Browse files
Pedro Piñera Buendíaclaude
authored andcommitted
Consolidate SSH auth into a single :auth option
Replace separate :password, :key, :key_path, :user_dir options with a single :auth tuple: {:password, "..."}, {:key, pem}, {:key_path, path}, or {:user_dir, dir}. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e7c25f6 commit 499cc07

2 files changed

Lines changed: 23 additions & 34 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ config :terrarium,
5656
server: {Terrarium.Providers.SSH,
5757
host: "dev.example.com",
5858
user: "deploy",
59-
key: System.fetch_env!("SSH_PRIVATE_KEY")
59+
auth: {:key, System.fetch_env!("SSH_PRIVATE_KEY")}
6060
}
6161
]
6262
```

lib/terrarium/providers/ssh.ex

Lines changed: 22 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ defmodule Terrarium.Providers.SSH do
1313
server: {Terrarium.Providers.SSH,
1414
host: "dev.example.com",
1515
user: "deploy",
16-
port: 22,
17-
user_dir: "~/.ssh"
16+
auth: {:key_path, "~/.ssh/id_ed25519"}
1817
}
1918
]
2019
@@ -23,31 +22,31 @@ defmodule Terrarium.Providers.SSH do
2322
- `:host` — (required) hostname or IP address
2423
- `:user` — (required) SSH username
2524
- `:port` — SSH port (default: `22`)
26-
- `:password` — password for authentication
27-
- `:user_dir` — directory containing SSH keys (default: `~/.ssh`)
28-
- `:key` — private key as a PEM string (e.g., from an env var)
29-
- `:key_path` — path to a specific private key file
25+
- `:auth` — authentication method (see below)
3026
- `:connect_timeout` — connection timeout in milliseconds (default: `10_000`)
3127
- `:cwd` — default working directory on the remote host (default: `"/"`)
3228
3329
## Authentication
3430
35-
Supports three authentication methods:
31+
The `:auth` option accepts a tuple specifying the method:
3632
37-
- **Password** — `:password` option
38-
- **Key directory** — `:user_dir` option, auto-discovers keys in the directory
39-
- **Specific key** — `:key` (PEM string) or `:key_path` (file path)
33+
- `{:password, "secret"}` — password authentication
34+
- `{:key, pem_string}` — private key as a PEM string (e.g., from an env var)
35+
- `{:key_path, "~/.ssh/id_ed25519"}` — path to a specific private key file
36+
- `{:user_dir, "~/.ssh"}` — directory containing SSH keys (auto-discovers)
37+
38+
If `:auth` is not provided, Erlang's `:ssh` will attempt default key discovery.
4039
4140
### Examples
4241
4342
# Password auth
44-
{Terrarium.Providers.SSH, host: "example.com", user: "deploy", password: "secret"}
43+
{Terrarium.Providers.SSH, host: "example.com", user: "deploy", auth: {:password, "secret"}}
4544
4645
# Key from a file
47-
{Terrarium.Providers.SSH, host: "example.com", user: "deploy", key_path: "~/.ssh/id_ed25519"}
46+
{Terrarium.Providers.SSH, host: "example.com", user: "deploy", auth: {:key_path, "~/.ssh/id_ed25519"}}
4847
4948
# Key from an environment variable
50-
{Terrarium.Providers.SSH, host: "example.com", user: "deploy", key: System.fetch_env!("SSH_PRIVATE_KEY")}
49+
{Terrarium.Providers.SSH, host: "example.com", user: "deploy", auth: {:key, System.fetch_env!("SSH_PRIVATE_KEY")}}
5150
"""
5251

5352
use Terrarium.Provider
@@ -70,8 +69,7 @@ defmodule Terrarium.Providers.SSH do
7069
silently_accept_hosts: true,
7170
user_interaction: false
7271
]
73-
|> maybe_add(:password, opts)
74-
|> maybe_add_key_opts(opts)
72+
|> add_auth_opts(Keyword.get(opts, :auth))
7573

7674
case :ssh.connect(to_charlist(host), port, ssh_opts, connect_timeout) do
7775
{:ok, conn} ->
@@ -237,26 +235,17 @@ defmodule Terrarium.Providers.SSH do
237235

238236
defp escape(str), do: "'#{String.replace(str, "'", "'\\''")}'"
239237

240-
defp maybe_add(ssh_opts, :password, opts) do
241-
case Keyword.fetch(opts, :password) do
242-
{:ok, password} -> Keyword.put(ssh_opts, :password, to_charlist(password))
243-
:error -> ssh_opts
244-
end
245-
end
238+
defp add_auth_opts(ssh_opts, nil), do: ssh_opts
246239

247-
defp maybe_add_key_opts(ssh_opts, opts) do
248-
cond do
249-
Keyword.has_key?(opts, :key) ->
250-
Keyword.put(ssh_opts, :key_cb, {Terrarium.Providers.SSH.KeyCb, key: opts[:key]})
240+
defp add_auth_opts(ssh_opts, {:password, password}),
241+
do: Keyword.put(ssh_opts, :password, to_charlist(password))
251242

252-
Keyword.has_key?(opts, :key_path) ->
253-
Keyword.put(ssh_opts, :key_cb, {Terrarium.Providers.SSH.KeyCb, key_path: opts[:key_path]})
243+
defp add_auth_opts(ssh_opts, {:key, pem}),
244+
do: Keyword.put(ssh_opts, :key_cb, {Terrarium.Providers.SSH.KeyCb, key: pem})
254245

255-
Keyword.has_key?(opts, :user_dir) ->
256-
Keyword.put(ssh_opts, :user_dir, to_charlist(Path.expand(opts[:user_dir])))
246+
defp add_auth_opts(ssh_opts, {:key_path, path}),
247+
do: Keyword.put(ssh_opts, :key_cb, {Terrarium.Providers.SSH.KeyCb, key_path: path})
257248

258-
true ->
259-
ssh_opts
260-
end
261-
end
249+
defp add_auth_opts(ssh_opts, {:user_dir, dir}),
250+
do: Keyword.put(ssh_opts, :user_dir, to_charlist(Path.expand(dir)))
262251
end

0 commit comments

Comments
 (0)