5.6. Hooks
suSSHi Gateway supports an optional administrator hook system that allows custom executable scripts or programs to be triggered automatically when specific gateway events occur. Hooks are useful for integrating suSSHi Gateway with external systems, sending notifications, or performing custom housekeeping tasks in response to session lifecycle events. The hook system is entirely optional: if no hooks directory is mounted, the gateway operates normally without any hooks.
5.6.1. Overview
Hook executables are placed in the /opt/wasabi/susshi/hooks/ directory inside the suSSHi Gateway container.
Each hook corresponds to a specific event and must be named exactly as listed in the Available Hooks section below.
The hook file must be executable.
Because all data inside a container is non-persistent, the hooks directory must be provided as a bind mount from the Docker host into the container. Hook scripts are therefore created and managed on the Docker host, outside the container.
When suSSHi Gateway starts, it scans the hooks directory and registers all hooks it finds. A container restart is required to pick up newly installed or removed hooks.
Hooks are executed asynchronously via a double-fork, so the gateway is never blocked or delayed by a slow or hanging hook script. The hook’s standard output and standard error are captured line by line and forwarded to syslog. The gateway’s own process environment is not inherited by the hook; instead, the hook receives a clean, minimal environment as described in Environment Variables.
5.6.2. Available Hooks
Hook name |
Triggered when |
|---|---|
|
The gateway daemon has finished initializing and is ready to accept connections. |
|
The gateway daemon is shutting down. |
|
A client has established a TCP connection to the gateway. |
|
A client has successfully authenticated at the gateway, the target login succeeded, and the session has started. |
|
A client failed to authenticate at the gateway (wrong credentials, wrong key, timed out, etc.). |
|
Gateway authentication succeeded but the target host could not be reached or refused the TCP connection. |
|
The TCP connection to the target host was established but authentication at the target failed. |
|
Fired for every session failure, regardless of cause. Use this as a catch-all alongside — or instead of — the more specific failure hooks above. |
|
A client connection has been closed after a successful session end. |
Only the hooks you place in the hooks directory are active. There is no requirement to provide all hooks — any combination or none at all is valid.
5.6.3. Environment Variables
Every hook receives a clean environment containing only the variables listed below.
Variables that have no value in the current context (for example, session-specific variables during
gateway-start) are omitted rather than set to an empty string.
Variable |
Description |
|---|---|
|
Safe minimal search path ( |
|
Name of the hook that is being executed (e.g. |
|
Version string of the suSSHi Gateway daemon (e.g. |
|
Operation mode of the gateway: |
|
Hostname of the gateway, if known. |
|
Unique session identifier, if in session context. |
|
Gateway username of the connecting user, if in session context. |
|
IP address of the connecting client, if in session context. |
|
TCP source port of the connecting client, if in session context. |
|
Bastion proxy realm name. Only present when |
|
Target username. Only present when |
|
Target hostname. Only present when |
|
Target port number. Only present when |
|
Resolved IP address of the target. Only present when |
|
Absolute path to the session log file for the current session, if available. |
|
Glob pattern matching all audit log files for the current session, if available. Useful for locating the session’s audit logs after the session ends. |
5.6.4. Installation
To install a hook, place an executable file with the exact hook name in a directory on the Docker host and mount
that directory into the container at /opt/wasabi/susshi/hooks/.
The file can be any executable: a shell script, a Python script, a compiled binary, etc.
Step 1 — Create the hook script on the Docker host
# Create the hooks directory on the host
mkdir -p /srv/susshi-gateway/hooks
# Create the hook script
cat > /srv/susshi-gateway/hooks/session-start << 'EOF'
#!/bin/sh
echo "$(date '+%Y-%m-%d %H:%M:%S') session-start: user=${SUSSHI_USER} client=${SUSSHI_CLIENT_IP} target=${SUSSHI_TARGET_USER}@${SUSSHI_TARGET_HOST}" \
>> /var/log/susshi/hooks.log
EOF
# Make it executable for the susshi user (UID 900) inside the container
chmod +x /srv/susshi-gateway/hooks/session-start
Step 2 — Mount the hooks directory into the container
Add a bind mount for the hooks directory to your container configuration:
services:
susshi-gateway:
image: hub.docker.com/wasabi-elements/susshi:26.05.0
environment:
- SUSSHI_CHEF_URL=https://susshi-chef.example.org/...
volumes:
- /var/log/susshi:/var/log/susshi
- /srv/susshi-gateway/hooks:/opt/wasabi/susshi/hooks:ro
Step 3 — Restart the container
After mounting the hooks directory, restart the container to activate the hooks. suSSHi Gateway logs a confirmation message to syslog for each registered hook at startup.
Note
Hook files are discovered once during container startup. Adding, removing, or modifying hook files has no effect until the container is restarted.
Note
All processes inside the suSSHi Gateway container run as the unprivileged user susshi (default UID 900, GID 900).
Ensure that the hook files on the Docker host are readable and executable by this UID.
If you have changed the container UID via the SUSSHI_UID environment variable, adjust the file permissions accordingly.
5.6.5. Execution Model
Hooks are executed using a double-fork pattern to fully decouple the hook process from the gateway:
The gateway forks an intermediate child process.
The intermediate child forks the actual hook process and captures its output.
The gateway immediately continues without waiting for the hook to finish.
The hook process receives:
stdin redirected from
/dev/null— hooks cannot read from the gateway’s terminal.stdout and stderr captured and forwarded line by line to syslog under the tag
hooks/<hook-name>.
All file descriptors inherited from the gateway are closed before the hook is executed.
If the hook exits with a non-zero exit code or is killed by a signal, a warning is written to syslog.
5.6.6. Example: Sending a Notification on Authentication Failure
The following example hook sends an alert via curl whenever a client fails to authenticate.
session-failed fires for every failure and is the simplest way to catch all problems in one place.
Use the more specific hooks — session-auth-failed, session-target-connect-failed, session-target-auth-failed — when you need to react differently depending on the failure cause.
#!/bin/sh
curl -s -X POST https://alerts.example.com/notify \
-d "event=session-auth-failed&user=${SUSSHI_USER}&client=${SUSSHI_CLIENT_IP}&gateway=${SUSSHI_GATEWAY_HOSTNAME}"
Note
The hook environment does not inherit the gateway’s PATH or any additional configuration.
Ensure that all required tools are available under the safe PATH provided, or use absolute paths.
In a container environment, tools like curl are available in the container’s default PATH, whereas
tools that depend on host-level services (such as mail) are generally not available.
5.6.7. Example: Archiving Audit Logs After Session End
The session-finished hook can be used to copy the session’s audit logs to a mounted archive volume
immediately after a session ends.
services:
susshi-gateway:
image: hub.docker.com/wasabi-elements/susshi:26.05.0
environment:
- SUSSHI_CHEF_URL=https://susshi-chef.example.org/...
volumes:
- /var/log/susshi:/var/log/susshi
- /srv/susshi-gateway/hooks:/opt/wasabi/susshi/hooks:ro
- /mnt/archive/susshi:/mnt/archive/susshi
#!/bin/sh
[ -z "${SUSSHI_AUDIT_LOG_PATTERN}" ] && exit 0
ARCHIVE_DIR="/mnt/archive/susshi"
mkdir -p "${ARCHIVE_DIR}"
cp ${SUSSHI_AUDIT_LOG_PATTERN} "${ARCHIVE_DIR}/"
logger -t susshi-hook "Archived audit logs for session ${SUSSHI_UNIQID}"