Demo library › Chapter 3
3 Admins reach servers without standing credentials.
SSH to the apps server with a certificate Cloudflare issues for the session - no key on the laptop, no password on the account - and the database console behind the same group.
The problem
Horizon Inc's admins have SSH keys on their laptops, a shared account on the server, and no record of what was typed. The VPN gets them to port 22 and from there the company is trusting them. The database console is the same story with a browser.
Lands with: security and platform teams, and anyone who has had to rotate a leaked key
Before you start
- Lab only - this reaches the apps server at
192.168.10.10. - The Cloudflare One client enrolled as one of the two IT Admins:
or. A second device or profile as, who is not one. - A terminal with an ordinary
sshclient, andpsqlfor the database act. Nothing else installed and no key generated. - For the command log: Cloudflare's ssh-log-cli on the presenting machine, and the SSH key from the key page.
Run it
The account you may become lives in the policy
| Do | Say |
|---|---|
Zero Trust → Networks → Targets → apps-server. | The server is registered once, by address. |
| Access controls → Applications → SSH to the apps server → its policy. | Port 22 on that target, for two named people, and they may log in as one unix account:
sysadmin. Who may become sysadmin is decided here - not by whose key is in an
authorized_keys file on every server. |
SSH with nothing on the laptop
| Do | Say |
|---|---|
As Rickie, client on: ssh sysadmin@192.168.10.10. Sign in if a browser opens. | No key was used and none exists on this laptop. Cloudflare issued a certificate for this session, the server trusts Cloudflare's certificate authority, and the account has no password at all - so this is the only way in. |
In the session: cat README, then sudo docker ps. | A real shell, and deliberately not root. The demo is about getting on to a server without a standing credential, not about what you can do once there. |
| As Alice, the same command. | Refused. She is a valid employee with an enrolled device, and SSH to this server is not hers. |
Every command, on the record
| Do | Say |
|---|---|
Insights → Logs → SSH command logs, Rickie's session → Download.
Then ssh-log-cli decrypt -i <file> -k sshkey --replay. | The session plays back, keystroke by keystroke. It was encrypted with a public key this company uploaded, so Cloudflare recorded it and cannot read it - the private key never left the company. |
The database console, behind the same group
| Do | Say |
|---|---|
As Rickie, open http://pgadmin.corp.internal. | Access asks why. That sentence is the part of an audit log a human actually reads. |
| In pgAdmin choose Horizon Inc SSO. | pgAdmin is an off-the-shelf application with its own login, and it federates that login to Cloudflare Access. Two jobs, two objects: one decides who may reach it at all, the other tells it who they are. The second sign-in is silent because the first already happened. |
Expand Horizon Inc reporting → backlog → tickets. Query
SELECT reference, description FROM tickets; | Registered for them already, no password typed. And note what is in BKL-1043 - a customer's card number, pasted by a colleague. That is where data protection picks up. |
| As Alice, the same address. | Refused at Access. She never reaches pgAdmin's login page. |
The database port itself
| Do | Say |
|---|---|
| Traffic policies → Firewall policies → Network → Postgres: IT Admins only. | Not every protocol has a login page for Access to stand in front of. Postgres on port 5432 is closed by a network policy instead: everyone but the IT Admins is blocked in the path, before the server sees a packet. |
As Alice: psql -h 192.168.10.10 -U backlog backlog | Refused - the connection never reaches the database. She cannot even try a password. |
| As Rickie, the same command. | A password prompt. The network lets him through; the database still asks who he is. Two layers, each doing one job. |
What the audience should see
- An SSH shell as
sysadminfrom a laptop with no key in~/.ssh. - Alice refused for both SSH and pgAdmin.
- pgAdmin signed in through Access, with the database already listed.
- Rickie's SSH session replayed from the decrypted command log.
- Alice's
psqlrefused at the network; Rickie's reaching a password prompt.
Where the evidence is
Access authentication logs show the SSH and pgAdmin sign-ins, the justification Rickie typed, and Alice's
refusals. Gateway's network logs show Alice's blocked connection to port 5432, and the SSH command log holds
Rickie's session. On the server, /etc/ssh/sshd_config.d/60-cloudflare-access.conf is the single
line that makes it trust Cloudflare's certificates.
Known limitations
- The SSH policy and the Postgres policy name the two IT Admins by address. Infrastructure applications cannot use an Access group or an OIDC group claim, and Gateway's group selectors want groups synced by SCIM, so the IT Admins group cannot be named directly.
- SSH command logs cannot be read in the dashboard; they are downloaded and decrypted with
ssh-log-cli.
Part of: Replace the VPN · The full tour