Skip to content

Commit 408a4e4

Browse files
committed
- Make the port of the publickey api scan configurable
- Add logic with public key scan to the Docker-local part - Update Readme
1 parent a5c810e commit 408a4e4

File tree

3 files changed

+30
-8
lines changed

3 files changed

+30
-8
lines changed

Dockerfile

+2-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ ENV SSH_PERMIT_TARGET_HOST="*" \
7474
SSH_PERMIT_TARGET_PORT="*" \
7575
SSH_TARGET_KEY_PATH="~/.ssh/id_ed25519.pub" \
7676
MANUAL_AUTH_FILE="false" \
77-
SSHD_ENVIRONMENT_VARIABLES="${_RESOURCES_PATH}/sshd_environment"
77+
SSHD_ENVIRONMENT_VARIABLES="${_RESOURCES_PATH}/sshd_environment" \
78+
SSH_TARGET_PUBLICKEY_API_PORT=8080
7879

7980
RUN \
8081
chmod -R ug+rwx $_RESOURCES_PATH && \

README.md

+8-3
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ This SSH proxy can be deployed as a standalone docker container that allows to p
3737

3838
### Prerequisites
3939

40-
The target containers must run an SSH server and provide a valid public key that can be found under `$SSH_TARGET_KEY_PATH` (default: `~/.ssh/id_ed25519.pub`).
40+
The target containers must run an SSH server and provide a valid public key via a `/publickey` endpoint. If this does not exist, the ssh-proxy tries to exec into the target container and search for the publickey under under `$SSH_TARGET_KEY_PATH` (default: `~/.ssh/id_ed25519.pub`).
4141

4242
> ℹ️ _The SSH proxy accepts an incoming key, if it belongs to one of the targets key, in other words the proxy/bastion server authorizes all target public keys. It is still not possible to login to the proxy directly. The authorization happens only for creating and tunneling the final connection._
4343
@@ -106,15 +106,20 @@ The container can be configured with the following environment variables (`--env
106106
<td>Defines on which port the other containers can be reached via ssh. The ssh connection to the target can only be made via this port then. The default value '*' permits any port.</td>
107107
<td>*</td>
108108
</tr>
109+
<tr>
110+
<td>SSH_TARGET_PUBLICKEY_API_PORT</td>
111+
<td>Port where the target pod exposes the /publickey endpoint (if used).</td>
112+
<td>8080</td>
113+
</tr>
109114
<tr>
110115
<td>SSH_TARGET_KEY_PATH</td>
111116
<td>The path inside the target containers where the manager looks for a valid public key.
112-
Consider that `~` will be resolved to the target container's home.</td>
117+
Consider that `~` will be resolved to the target container's home. Only used when the target container does not return a public key via the /publickey endpoint.</td>
113118
<td>~/.ssh/id_ed25519.pub</td>
114119
</tr>
115120
<tr>
116121
<td>MANUAL_AUTH_FILE</td>
117-
<td>Disables the bastion's public key fetching method and you have to maintain the /etc/ssh/authorized_keys_cache file yourself (e.g. by mounting a respective file there)</td>
122+
<td>Disables the bastion's public key fetching method and you have to maintain the /etc/ssh/authorized_keys_cache file yourself (e.g. by mounting a respective file there). Only used when the target container does not return a public key via the /publickey endpoint.</td>
118123
<td>false</td>
119124
</tr>
120125
</table>

docker-res/ssh/update_authorized_keys.py

+20-4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
SSH_PERMIT_TARGET_HOST = os.getenv("SSH_PERMIT_TARGET_HOST", "*")
2222
SSH_TARGET_KEY_PATH = os.getenv("SSH_TARGET_KEY_PATH", "~/.ssh/id_ed25519.pub")
23+
SSH_TARGET_PUBLICKEY_API_PORT = os.getenv("SSH_TARGET_PUBLICKEY_API_PORT", 8080)
2324

2425
authorized_keys_cache_file = "/etc/ssh/authorized_keys_cache"
2526
authorized_keys_cache_file_lock = "cache_files.lock"
@@ -92,7 +93,7 @@ def get_authorized_keys_kubernetes(query_cache: list = []) -> (list, list):
9293

9394
key = None
9495
# Try to get the public key via an API call first
95-
publickey_url = "http://{}:8091/publickey".format(pod_ip)
96+
publickey_url = "http://{}:{}/publickey".format(pod_ip, str(SSH_TARGET_PUBLICKEY_API_PORT))
9697
timeout_seconds = 10
9798
try:
9899
request = requests.request("GET", publickey_url, timeout=timeout_seconds)
@@ -145,9 +146,24 @@ def get_authorized_keys_docker(query_cache: list = []) -> (list, list):
145146
new_query_cache.append(container.id)
146147
continue
147148

148-
exec_result = container.exec_run(PRINT_KEY_COMMAND)
149-
authorized_keys.append(exec_result[1].decode("utf-8"))
150-
new_query_cache.append(container.id)
149+
key = None
150+
# Try to get the public key via an API call first
151+
publickey_url = "http://{}:{}/publickey".format(container.id, str(SSH_TARGET_PUBLICKEY_API_PORT))
152+
timeout_seconds = 10
153+
try:
154+
request = requests.request("GET", publickey_url, timeout=timeout_seconds)
155+
if request.status_code == 200:
156+
key = request.text
157+
except requests.exceptions.ConnectTimeout:
158+
print("Connection to {ip} timed out after {timeout} seconds. Will try to exec into the pod to retrieve the key.".format(ip=pod_ip, timeout=str(timeout_seconds)))
159+
160+
if key is None:
161+
exec_result = container.exec_run(PRINT_KEY_COMMAND)
162+
key = exec_result[1].decode("utf-8")
163+
164+
if key is not None:
165+
authorized_keys.append(key)
166+
new_query_cache.append(container.id)
151167

152168
return authorized_keys, new_query_cache
153169

0 commit comments

Comments
 (0)