# Open Bastion
**Control SSH access and sudo privileges on your Linux servers from your SSO —
no more per-server keys or sudoers.**
Open Bastion integrates your servers with [LemonLDAP::NG](https://lemonldap-ng.org) (LLNG)
so you manage your Linux administrators as easily as you already manage your SSO
users. Administrators define access rules once in the portal; the PAM/NSS modules
enforce them on every server.
## What Open Bastion gives you
- **The SSO decides SSH access** — no SSH keys to install or rotate on each
server; group membership grants or revokes access fleet-wide.
- **The SSO decides `sudo` too** — no `sudoers` to maintain per host
_(local/dual management stays possible when you want it)_.
- **Recordings the user can't touch** — interactive sessions are streamed to a
root sink the recorded user cannot read, alter or delete, while `~/.ssh/config`
keeps access _visually_ direct. Recording is fail-closed: if the sink is
unreachable, the login is refused. Coverage has known edges — a service
account's native `ssh -J` forwarded channel is not recorded, and containment
hardening is opt-in — see [service accounts](doc/service-accounts.rst) and
[audit trace](doc/audit.rst).
- **Fleet deployment in one command** — `ob-builder --output-ansible ` (or
a self-extracting shell installer), then roll it out to every host.
- **A "backup" account with access everywhere** — with or without `sudo` — via
[service accounts](doc/service-accounts.rst).
- **Self-service onboarding** — a new admin signs their SSH key at the portal and
instantly has every right their groups grant.
- **One-click offboarding** — close the SSO account and access is gone.
- **Instant role changes** — change someone's groups and, within minutes, old
rights drop and new ones apply.
Two layers do this: the **SSO (LLNG) decides** policy centrally, the **PAM/NSS
modules enforce** it on each server. See [Access & Permissions](doc/permissions.rst)
for exactly which control lives where.
## Quick start
These quick-starts cover the ways to get going — try it, point it at your SSO,
then deploy:
| Quick-start | Use it to… |
| ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **[Try it in Docker](quick-start/README.md)** | Spin up a LemonLDAP::NG portal + a self-enrolling SSH server in ~2 minutes and log in with an LLNG token — the fastest way to see Open Bastion work. |
| **[Configure your SSO](doc/llng-configuration.rst)** | On your real LemonLDAP::NG: install the required plugins, and create the OIDC client(s) that carry your machines — the prerequisite before any deployment. |
| **[Deploy a fleet with Ansible](doc/ansible-quickstart.rst)** | Generate bastion + backend roles with `ob-builder`, declare your hosts and IPs, and apply with `ansible-playbook` — the path to a real deployment. |
| **[Deploy with a shell installer](doc/shell-quickstart.rst)** | Generate a self-extracting installer per role with `ob-builder --output-shell`, then `scp` + `sudo`-run it on each host — no Ansible control node. |
For the underlying concepts and per-step manual configuration, see
[PAM Authentication Modes](doc/pam-modes.rst), the
[Configuration Reference](doc/configuration.rst), and the
[Admin Guide](doc/admin-guide.rst).
## How it works
Each server is first **enrolled** by an administrator — installing the package and
registering the host with the SSO (`ob-enroll`, or the generated `ob-builder`
artefacts), which is also what assigns its server group. See the
[Admin Guide](doc/admin-guide.rst) (or the [quick-starts](doc/index.rst#start-here))
for the enrollment step. Once enrolled:
1. A user authenticates to a server — with an LLNG **token** _(used as the SSH
password)_ or an **SSO-signed SSH certificate** _(self-served via `ob-ssh-cert`)_.
2. `pam_openbastion` asks LLNG `/pam/authorize` whether this user may access this
server group, and `sudo` is gated the same way; an encrypted local cache keeps
this working during an SSO outage.
3. The **NSS** module resolves SSO users _(and key-only service accounts)_ so the
system sees them as real Unix accounts; provisioning creates the home on first
login.
4. To reach a **backend behind a bastion**, the bastion mints a short-lived,
LLNG-signed certificate and re-originates the connection with `ob-ssh` /
`ob-scp` / `ob-sftp` — no user key or agent on the bastion. Backends accept
only vouched bastions.[^1]
5. Sessions are **recorded** inside the bastion to a tamper-evident, root-owned
store for audit.
See [Bastion Architecture](doc/bastion-architecture.rst) and the
[documentation index](doc/index.rst) for the details.
## Features
- Token introspection via OIDC introspection endpoint
- Server authorization via `/pam/authorize` endpoint
- [Server groups](doc/llng-configuration.rst#server-groups) support for granular access control
- Token caching to reduce server load
- Secure communication with SSL/TLS support
- Easy server enrollment with `ob-enroll` script
- **[Offline mode](doc/offline-mode.rst)**:
- Encrypted authorization cache _(AES-256-GCM)_
- Continue SSH key authentication when LLNG server is unavailable
- Configurable cache TTL with shorter TTL for high-risk services (sudo, su)
- Cache brute-force protection with rate limiting
- **NSS module**:
- Resolve users from LLNG via `/pam/userinfo` endpoint
- Automatic UID generation from username hash
- Cross-process file cache for performance
- **Automatic user provisioning**:
- Auto-create Unix accounts on first login
- Configurable shell, home directory, UID/GID ranges
- Skeleton directory support
- **[Group synchronization](doc/llng-configuration.rst#group-synchronization)**:
- Sync Unix supplementary groups from LLNG on each login
- Automatic group creation if needed
- Local whitelist for defense-in-depth _(`allowed_managed_groups`)_
- Groups outside managed pool are never modified
- **[Service accounts](doc/service-accounts.rst)** _(ansible, backup, etc.)_:
- SSH key authentication without OIDC
- Per-server configuration file
- Fine-grained sudo permissions
- Automatic account creation
- **[Bastion-to-backend authentication](doc/bastion-architecture.rst)**:
- Certificate-based proof of connection origin _(LLNG-signed ephemeral SSH cert, ~120 s)_
- Backends only accept SSH from authorized bastions (`allowed_bastions` + `source-address` critical option)
- No agent forwarding or user key on the bastion required
- `ob-ssh` / `ob-scp` / `ob-sftp` scripts for seamless bastion connections and file transfers
- **[Session recording](doc/session-recording.rst)** _(optional)_:
- Record all terminal I/O for audit compliance
- Written by a root sink the recorded user cannot reach (`.typescript` +
`.json`; asciinema and ttyrec are planned, and currently fall back to
`script`)
- Session metadata with unique IDs
- **[Security hardening](doc/security.rst)**:
- Structured JSON audit logging with correlation IDs
- Rate limiting with exponential backoff
- AES-256-GCM encrypted secret storage
- Webhook notifications for security events
- Token binding (IP, fingerprint)
- [SSH key policy](doc/security.rst#ssh-key-policy) enforcement _(allowed types, minimum sizes)_
- **[CrowdSec integration](doc/crowdsec.rst)** (optional):
- Pre-authentication IP blocking via CrowdSec bouncer
- Post-authentication failure reporting via CrowdSec watcher
- Auto-ban after configurable failure threshold
- Compatible with [Crowdsieve](https://github.com/linagora/crowdsieve) for centralized alert management
- **Monitoring**:
- Server heartbeat via `ob-heartbeat`
- Statistics reporting to portal
Desktop SSO (LightDM workstation login) also exists but is **experimental
(alpha)** and is deliberately **not** listed among the features above — see the
clearly-separated **Desktop SSO** section near the end of this README.
## Installation
### From Package Repository
Pre-built packages are available for:
- **Debian/Ubuntu**: Debian 12, Debian 13, Ubuntu 24.04
- **RHEL/Rocky Linux**: Rocky Linux 9, Rocky Linux 10
See installation instructions at: **https://linagora.github.io/open-bastion/**
### Deploying to a fleet — `open-bastion-builder`
For administrators rolling Open Bastion out to several servers, a separate
`open-bastion-builder` package provides an interactive CLI (`ob-builder`)
that generates a self-extracting shell installer and/or an Ansible role
tailored to your SSO, scenario, and target role (bastion / standalone /
backend). Install it once on an admin workstation, run the questionnaire,
then push the resulting artefact to every target machine.
See [admin-builder/README.md](admin-builder/README.md) for the questionnaire,
configuration keys, and usage examples.
### From Source
```bash
# Install dependencies (Debian/Ubuntu)
sudo apt-get install libcurl4-openssl-dev libjson-c-dev libpam0g-dev libssl-dev libkeyutils-dev cmake curl jq
# Build
mkdir build && cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr ..
make
sudo make install
```
Set `CMAKE_INSTALL_PREFIX=/usr` rather than taking CMake's `/usr/local` default:
the paths written into the generated sshd and PAM configuration are absolute
(`/usr/sbin/ob-service-account-keys`, for one), so a `/usr/local` install leaves
them pointing at files that are not there.
## Documentation
The full, theme-organized index is in **[doc/index.rst](doc/index.rst)**. Highlights:
- **Get started** — [Docker demo](quick-start/README.md) · [Shell](doc/shell-quickstart.rst) / [Ansible](doc/ansible-quickstart.rst) quick-starts · [Admin guide](doc/admin-guide.rst)
- **Connections & architecture** — [Bastion architecture](doc/bastion-architecture.rst) · [PAM modes](doc/pam-modes.rst) · [LLNG configuration](doc/llng-configuration.rst)
- **Access & permissions** — [Access & Permissions](doc/permissions.rst) (SSO-side vs server-side) · [Service accounts](doc/service-accounts.rst)
- **Recording & audit** — [Session recording](doc/session-recording.rst) · [Audit trace](doc/audit.rst)
- **Offline & resilience** — [Offline mode](doc/offline-mode.rst) · [Cache administration](doc/offline-cache-admin.rst)
- **Security & hardening** — [Security features](doc/security.rst) · [Hardening](doc/hardening.rst) · [CrowdSec](doc/crowdsec.rst)
- **Reference** — [Canonical names & paths](doc/reference-paths.rst) · [Configuration](doc/configuration.rst) · [Troubleshooting](doc/troubleshooting.rst) · [Desktop SSO](doc/desktop-sso.rst) _(experimental/alpha)_ · [Competitors](doc/competitors.rst)
- **Security analysis (EBIOS RM)** — [full risk study](doc/security/index.rst) _(French)_ · [conditions of use before deploying](doc/security/08-dossier-homologation.rst#2-conditions-demploi)
`doc/` is a [Sphinx](https://www.sphinx-doc.org/) project, so the same pages
read offline as one HTML site:
```bash
# from the packages
sudo apt install open-bastion-doc # /usr/share/doc/open-bastion-doc/html/index.html
# or from a checkout
sphinx-build -b html doc build/doc/html
```
## Troubleshooting
Logs, debug mode, endpoint tests and common issues are collected in
**[doc/troubleshooting.rst](doc/troubleshooting.rst)**.
## Requirements
- A LemonLDAP::NG system >= 2.23.0 with some [additional plugins](https://linagora.github.io/lemonldap-ng-plugins/) installed and enabled
- libcurl, json-c, OpenSSL, libkeyutils, PAM development headers
- curl and jq (for enrollment script)
## Desktop SSO (LightDM) — experimental, alpha
> **⚠️ Experimental — not production-ready.** Unlike the server-side SSH/sudo
> features above (the validated, supported core of Open Bastion), the LightDM
> workstation-login greeter is an early **alpha** prototype. Its authentication
> path has **not** had a security review and there is **no test environment**
> for it yet. Do **not** rely on it to protect access to a workstation. It is
> documented here for experimentation only and is intentionally kept separate
> from the features list.
Open Bastion can authenticate desktop workstations via LemonLDAP::NG Single Sign-On
using LightDM.
### Quick Setup
```bash
# Install the greeter package
sudo apt install open-bastion-desktop
# Run the setup script
sudo ob-desktop-setup -p https://auth.example.com
# For offline mode support
sudo ob-desktop-setup -p https://auth.example.com --offline
```
### Features
- **SSO Authentication**: Users login with their LLNG credentials via embedded portal
- **Multi-Factor Authentication**: Supports TOTP, WebAuthn/FIDO2, SMS, and more
- **Offline Mode**: Cached credentials allow login when LLNG is unreachable
- **Session Selection**: Choose between multiple desktop environments
### Documentation
- [Desktop SSO Guide](doc/desktop-sso.rst) - Complete setup and configuration
- [Offline Mode](doc/offline-mode.rst) - Cached credential authentication
- [Security reference](doc/security-reference.rst#offline-credential-cache-security) - Security details
### Cache Management
```bash
# Show cache statistics
sudo ob-cache-admin stats
# List cached users
sudo ob-cache-admin list
# Invalidate a user's cache (after termination)
sudo ob-cache-admin invalidate username
```
## License
AGPL-3.0
## Author
Xavier Guimard
Copyright (C) [Linagora](https://linagora.com)
---
[^1]: This is optional, of course: you can keep non-Open-Bastion backends and manage them the old way, with SSH keys.