Auth Hooks
The hook system for access control beyond the allowlist.
Overview
ctrl-exec has no built-in ACL system. All access control beyond the allowlist is implemented in auth hooks — executable scripts or programs that receive request context and return an exit code.
There are two independent hook points:
- ctrl-exec-side hook
-
Configured in
ctrl-exec.confviaauth_hook. Called before everyrun,ping,capabilities, and API request. Runs on the control host before any agent connection is made. - Agent-side hook
-
Configured in
agent.confviaauth_hook. Called on the agent after allowlist validation, before script execution. Coversrunrequests only.
Both hooks can be active simultaneously. They operate independently.
Hook Invocation
The hook is called as a subprocess. It receives request context as environment variables and the same context as a JSON object on stdin. It must exit within the configured timeout (default: 10 seconds) or the request is denied.
stdout and stderr are discarded. Use syslog for audit logging from within the hook.
Environment Variables
ENVEXEC_ACTION run | ping | api
ENVEXEC_SCRIPT script name requested (empty for ping)
ENVEXEC_HOSTS comma-separated list of target hosts
ENVEXEC_ARGS space-joined arguments — unreliable, see note below
ENVEXEC_ARGS_JSON arguments as a JSON array string
ENVEXEC_USERNAME username from the request (caller-supplied, not verified by ctrl-exec)
ENVEXEC_TOKEN auth token from the request
ENVEXEC_SOURCE_IP 127.0.0.1 for CLI callers; caller IP for API callers
ENVEXEC_TIMESTAMP ISO 8601 UTC timestamp
Exit Codes
0 authorised — proceed
1 denied (generic)
2 denied — bad credentials
3 denied — insufficient privilege
Any non-zero exit aborts the request. The specific code is logged at ACTION=auth and returned to the caller. The API includes the code in the error response body.
Token Forwarding
Tokens are forwarded from ctrl-exec through to agent hooks and to script stdin. A token validated at the ctrl-exec side is the same token available to the agent-side hook and to the script itself.
Tokens are never logged by ctrl-exec or the agent. To prevent tokens appearing in ps output, pass them via the environment rather than --token:
ENVEXEC_TOKEN=mytoken ced run host-a backup-mysql
Writing a Hook
A hook can be any executable: shell script, Perl, Python, compiled binary. It must:
- Read
ENVEXEC_*variables and/or stdin for request context. - Exit with one of the codes above.
- Complete within the timeout.
Example: per-token script restriction
#!/bin/bash
case "$ENVEXEC_TOKEN" in
backup-token)
[[ "$ENVEXEC_SCRIPT" == backup-* ]] || exit 3
exit 0 ;;
ops-token)
exit 0 ;;
*)
exit 2 ;;
esac
Example: argument inspection
Inspect a specific argument value using ENVEXEC_ARGS_JSON and jq:
#!/bin/bash
TARGET=$(echo "$ENVEXEC_ARGS_JSON" | jq -r '.[0] // empty')
case "$TARGET" in
/var/log/*|/tmp/*) exit 0 ;;
*) exit 3 ;;
esac
Example: LDAP group membership check
#!/bin/bash
if [ -z "$ENVEXEC_USERNAME" ]; then
exit 2
fi
ldapsearch -x -H ldap://ldap.example.com \
-b "ou=groups,dc=example,dc=com" \
"(&(objectClass=groupOfNames)(cn=ctrl-exec-ops)(member=uid=${ENVEXEC_USERNAME},ou=people,dc=example,dc=com))" \
dn 2>/dev/null | grep -q '^dn:' || exit 3
exit 0
Example: time-of-day restriction
#!/bin/bash
HOUR=$(date -u +%H)
# Allow only between 06:00 and 22:00 UTC
if [ "$HOUR" -lt 6 ] || [ "$HOUR" -ge 22 ]; then
exit 3
fi
exit 0
Hook Configuration
In ctrl-exec.conf:
auth_hook = /etc/ctrl-exec/hooks/auth.sh
In agent.conf:
auth_hook = /etc/ctrl-exec-agent/hooks/auth.sh
The hook must be executable by the user running ctrl-exec or the agent:
chmod 750 /etc/ctrl-exec/hooks/auth.sh
API Auth Default
When the API server has no hook configured, the api_auth_default setting governs behaviour:
deny(default)- All API requests are denied without a hook. This prevents accidental open access when deploying the API server for the first time.
allow- All API requests are permitted. Only appropriate on a privately networked API server with no exposure to untrusted callers.
Security Notes
ENVEXEC_USERNAMEis a caller-supplied string. ctrl-exec does not verify it. Validate usernames only via a token or an external authentication service.- Do not log environment variables wholesale from within a hook — tokens will be written to your audit log. Log only the specific fields that are needed.
- The hook's working directory is not guaranteed. Use absolute paths for all file references.
- A hook that exits non-zero causes all requests to fail. Test hooks against the expected inputs before deploying to production.