Skip to content

SSH via Bridge

Overview

This pattern combines the remote SSH access approach with Britive Bridge: the broker provisions a one-time ed25519 key on the target host, but instead of returning that key to the user, it registers a proxied session with Bridge. All traffic flows through the Bridge proxy where it is audited and recorded.

One checkout gives the user two ways in:

  • Their own SSH client, pointed at the Bridge’s native SSH listener
  • The browser, with no client at all

Either way the target’s credential stays server-side. The user authenticates to Bridge with the Bridge Password on their Britive profile — never with the one-time key.

What you’ll accomplish:

  • Provision a one-time SSH key on a remote Linux host at checkout
  • Register a Bridge session that accepts the user’s Bridge credentials
  • Remove the key, sudo grant, and session at checkin

This guide covers Bridge v2 only. v2 scripts call broker-bridge-api.sh and register the checkout with native_auth=bridge_credentials. The retired v1 scripts called bridge.sh and returned a tokenized browser URL. A v1 script on a v2 Bridge fails at the API call with nothing to indicate the version is the reason.

Before You Begin

  • Bridge v2 is deployed and reachable by users
  • The Bridge native SSH listener is enabled and reachable on NATIVE_PORT (default 2222)
  • A privileged provisioning account (default britivebroker) on each target host, reachable with the broker’s SSH key (root or passwordless sudo)
  • Broker host has ssh, ssh-keygen, base64, and jq — extend the Bridge image with a custom build if needed
  • broker-bridge-api.sh present at /opt/britive-broker/scripts/broker-bridge-api.sh
  • Each user has a Bridge Password set on their Britive profile (Manage Account → Bridge Attributes). Optionally a Bridge SSH Key

How It Works

checkout → derive username from BRITIVE_USER_EMAIL (local part, alphanumeric)
         → generate one-time ed25519 keypair tagged bridge:<TRX>
         → SSH as provisioning user: create user, install public key,
           optional sudoers entry /etc/sudoers.d/bridge-<TRX>
         → broker-bridge-api.sh checkout-create
             { protocol: ssh, private_key, record_session: true,
               native_auth: bridge_credentials, bridge_auth_password }
         → return { command, browser_session, bridge_username, ... }

checkin  → broker-bridge-api.sh checkout-delete <TRX>   ← session dies FIRST
         → SSH as provisioning user: remove key by bridge:<TRX> marker,
           delete sudoers entry, optionally delete the account

The one-time private key travels only from the broker to Bridge inside the checkout payload — the user never sees it. If Bridge registration fails, the checkout rolls the provisioned key back off the target.

The Identity Model

This is the part that most often trips people up.

The native SSH login is <email>%<target-host>, where <email> is the user’s Britive identity — the same value as the checkout owner. Bridge matches both the native SSH username (the part before %) and the browser SSO identity against the checkout’s username field, so they must be identical.

The profile’s Bridge Username field is not used for this matching. Setting it does not change the login name.

The username is passed with -l rather than as user@host because it contains both @ (the email) and % (the target separator), which would be ambiguous before a hostname.

Environment Variables

VariableRequiredDefaultNotes
BRITIVE_USER_EMAILYesInjected — OS username derived from the local part
TRXYesInjected — transaction ID; tags the key and sudoers entry
TARGET_HOSTYesSSH target host
BRIDGE_URLYesBridge hostname. One NLB serves both browser and native sessions
EXPIRATIONYesCheckout duration in seconds
BRIDGE_AUTH_PASSWORDYesInjected from the user’s profile. Bridge rejects a bridge_credentials checkout without it
BRIDGE_AUTH_PUBKEYNoUser’s Bridge SSH public key. When set, added as user_public_key so they may use their own key as well as the password
TARGET_PORTNo22SSH port on the target
NATIVE_PORTNo2222Bridge native SSH listener port
BRITIVE_SUDONo01 grants passwordless sudo for the session
PROVISION_USERNobritivebrokerPrivileged account used for provisioning
PROVISION_HOSTNoTARGET_HOSTSeparate provisioning host if needed
PROVISION_PORTNoTARGET_PORTSSH port for provisioning
PROVISION_KEYNo/home/bridge/.ssh/id_ed25519Broker’s provisioning private key (mode 600)
PROVISION_KEY_PEMNoInline PEM content, preferred over PROVISION_KEY
DELETE_USERNo0Checkin only — 1 also deletes the temp account
BROKER_APINo/opt/britive-broker/scripts/broker-bridge-api.shPath to the Bridge API helper

Checkout Routine

Full script: Linux/permissions/temp-user-bridge/checkout_ssh_bridge.sh

Key sections — provision the one-time key, then register the session against the user’s Bridge credentials:

# One-time keypair, tagged with the transaction ID for cleanup
ssh-keygen -t ed25519 -f "$KEYDIR/key" -N "" -C "bridge:${TRANSACTION_ID}" >/dev/null 2>&1

# Provision the user and public key on the target via the privileged account
run_provision sh -s -- "$TARGET_USERNAME" "$PUBKEY_B64" "$PROVISION_SUDO" "$TRANSACTION_ID" <<'REMOTE'
# ... creates the user if missing, appends the key to authorized_keys,
# ... writes /etc/sudoers.d/bridge-<TRX> when sudo is requested
REMOTE

# The bridge password is always registered — Bridge rejects the checkout
# without it. A Bridge SSH key, when present, is added alongside it.
if [ -n "$BRIDGE_AUTH_PUBKEY" ]; then
  AUTH_METHOD="pubkey"
  AUTH_FIELDS="$(jq -n --arg p "$BRIDGE_AUTH_PASSWORD" --arg k "$BRIDGE_AUTH_PUBKEY" \
    '{native_auth:"bridge_credentials", bridge_auth_password:$p, user_public_key:$k}')"
else
  AUTH_METHOD="password"
  AUTH_FIELDS="$(jq -n --arg p "$BRIDGE_AUTH_PASSWORD" \
    '{native_auth:"bridge_credentials", bridge_auth_password:$p}')"
fi

jq -n --arg transaction_id "$TRANSACTION_ID" --arg username "$USER_EMAIL" \
      --argjson private_key "$PRIVATE_KEY_JSON" --argjson auth "$AUTH_FIELDS" \
  '{transaction_id: $transaction_id, protocol: "ssh",
    username: $username, private_key: $private_key,
    record_session: true} + $auth' > "$PAYLOAD_FILE"

if ! "${BROKER_API}" checkout-create --file "$PAYLOAD_FILE" >/dev/null; then
  rollback            # take the injected key back off the target
  fail "Bridge checkout registration failed"
fi

The response carries both routes in:

{
  "BRIDGE_URL": "bridge.example.com",
  "command": "ssh -p 2222 -l 'alice@corp%server.internal' bridge.example.com",
  "auth_method": "password",
  "bridge_username": "alice@corp%server.internal",
  "bridge_port": "2222",
  "target_username": "alicecorp",
  "browser_session": "https://bridge.example.com/ssh/#transaction_id=<TRX>"
}

Checkin Routine

Full script: Linux/permissions/temp-user-bridge/checkin_ssh_bridge.sh

# Session dies FIRST — revokes the proxy credential and cuts any live session
"${BROKER_API}" checkout-delete "${TRANSACTION_ID}"

# Then deprovision: remove the key (matched by the bridge:<TRX> comment)
# and delete /etc/sudoers.d/bridge-<TRX>
run_provision sh -s -- "$TARGET_USERNAME" "$TRANSACTION_ID" "$DELETE_USER" <<'REMOTE'
# ... grep -vF "bridge:<TRX>" authorized_keys, rm sudoers entry,
# ... and userdel when DELETE_USER=1
REMOTE

The order matters: revoking the Bridge checkout first means an active session is cut immediately, rather than lingering while the key is removed.

Configure in Britive

Create the permission

Resource Manager → Resource Type Permissions → New Permission. Language = Shell. Paste the checkout and checkin routines. Declare TARGET_HOST, BRIDGE_URL, EXPIRATION, and any provisioning overrides; BRITIVE_USER_EMAIL, TRX, and the BRIDGE_AUTH_* values are system-defined.

Attach a response template

Surface {{command}} and {{bridge_username}} for native clients, and {{browser_session}} for the browser. The same template works for the Windows RDP and database bridge patterns — they return the same keys.

Create a profile and policy

Create a profile (e.g. 1h), add the permission, associate it with the Linux resources, and add a policy assigning members by tag.

Verify

Check out

Check out the profile. The response contains a ready-to-paste command and a browser_session URL.

Connect with your own client

ssh -p 2222 -l 'alice@corp%server.internal' bridge.example.com

At the password prompt, enter the Bridge Password from your Britive profile — not the target account’s password. On the target, ~/.ssh/authorized_keys contains a key commented bridge:<TRX>.

Or open the browser session

The browser_session URL opens the same session with no client installed.

Check in

Check in. Any live session is cut, the key line is gone from authorized_keys, and /etc/sudoers.d/bridge-<TRX> is removed.

Troubleshoot

SymptomLikely CauseFix
required env var missing: BRIDGE_AUTH_PASSWORDUser has no Bridge Password on their profileSet one under Manage Account → Bridge Attributes
Checkout registration failsScript is v1, or Bridge is v1v2 scripts call broker-bridge-api.sh; confirm both ends are v2
provisioning user requires root or passwordless sudoProvisioning account lacks privilegesGrant britivebroker passwordless sudo or use root
Checkout fails at the SSH stepWrong PROVISION_KEY path or key not authorizedConfirm the broker’s key (mode 600) is in the provisioning user’s authorized_keys
SSH to the Bridge is refusedNative listener not enabled or not exposedEnable the native SSH listener and expose NATIVE_PORT (2222) on the load balancer
Bridge rejects the login nameUsername not in <email>%<target-host> form, or profile Bridge Username assumedUse -l with the full bridge_username from the response
Session opens but sudo deniedBRITIVE_SUDO not setSet BRITIVE_SUDO=1 on the permission
Key remains after checkinCheckin failed mid-runKeys are TRX-tagged — re-run checkin or remove lines matching bridge:<TRX>

Next Steps

Last updated on