Table of Contents
Why I Stopped JIT’ing Users and Started JIT’ing Permissions
By Cole Horsman
Field CTO, Sonrai Security
I first tried to “shift left” cloud identity in early 2020.
We were building a greenfield AWS environment with a strong cloud team and leadership support to do things properly. The idea was familiar: push security decisions earlier, give developers autonomy, and avoid becoming the bottleneck later.
We accepted early that perfect least privilege was unrealistic. The goal was not precision. The goal was to reduce risk without slowing teams down.
In practice, shift left for identity turned into IaC scanning, service control policies, and cleanup controls meant to catch whatever slipped through.
The failure was consistent.
Trying to anticipate permissions ahead of time did not work. After two or three rounds of back-and-forth, policies almost always ended up with a wildcard. Developers were not careless. They were being asked to predict access needs months in advance while still shipping.
Once access worked, it stayed. The people deploying permissions were not accountable for their long-term risk. No one came back later to clean it up. Fixing excess access required months of negotiation.
And when access actually mattered, during incidents or production issues, the permission that was needed was usually missing. AWS permission sets like “Developer” or “DBA” rarely fit real situations. IAM became the bottleneck, not the guardrail.
Shift left filtered out obvious mistakes. It did not solve the identity problem.
JIT Sounded Right, But Failed Anyway
Just-in-time access felt like the logical next step. Grant access when needed. Remove it afterward.
This is where legacy PAM broke down.
We tried to treat everything as code. That never held. Environments drifted constantly. Months later, a stack update would break production because someone had manually changed a security group outside the pipeline.
We built a shared account checkout workflow spanning Active Directory, a secrets manager, Entra ID, AWS Identity Center, and permission sets. It looked clean on a diagram. It was painful to operate.
Shared accounts forced MFA exceptions that were difficult to defend. Custom integrations took months. And once it finally worked, access did not always expire.
That is not just-in-time access. That is standing privilege with extra steps.
Why Building It Ourselves Didn’t Scale
When vendors failed, I tried to build it myself.
Automation made JIT possible, technically. Operationally, it fell apart.
Ownership was unclear. IAM teams owned identity providers, not automation platforms. Failures bounced between teams. Group-based access still depended on directory sync timing. Audit trails were scattered across systems.
The integrations were fragile. One API change or token issue and the workflow failed at exactly the wrong moment.
Homegrown JIT worked as a proof of concept. It did not survive enterprise pressure.
At that point, it was clear the problem was not execution. It was the model.
Where JIT Actually Fails in the Cloud
Traditional JIT approaches break down because they operate at the wrong layer.
In practice, cloud JIT fails when it relies on:
- Standing permissions behind role switching or group membership
- Directory sync timing as a control
- Ticket queues that turn access into a waiting problem
- Shared or break-glass accounts that quietly persist
- Workflows that grant access without enforced expiration
None of these remove standing privilege. They just move it around.
Why Legacy PAM Doesn’t Work for Cloud
Shift left failed because it pushed IAM decisions to developers who should not own them.
Legacy PAM failed because it was built for static servers and a small number of human admins. It understands vaults and sessions. It does not understand cloud identity.
AWS identity is built on policies, permissions, roles, resource boundaries, services, and tags. Legacy PAM was never designed to:
- Monitor API-level activity across thousands of cloud identities
- Detect privilege escalation hidden in IAM role chaining
- Enforce policy-based restrictions without breaking production
- Govern machine identities that outnumber humans by orders of magnitude
Legacy PAM JITs users. Cloud environments require permissions on demand.
When attackers gain valid credentials with excessive permissions, legacy PAM records the activity. It does not prevent it.
The Model That Finally Worked
After three years of trying to make JIT work, I was close to accepting that least privilege would always be more aspirational than real.
Then I saw Sonrai Security talking about JIT with ChatOps.
What stood out was not a feature. It was what disappeared.
- No vaults
- No shared accounts
- No directory sync dependencies
- No credential sharing
- No MFA exceptions to justify
- Access in seconds, not hours
Everything was built on native cloud constructs like tags, customer-managed IAM policies, and service control policies.
That change mattered. Developers stopped routing around access controls because access was no longer the slowest part of the workflow.
This approach is enforced through Sonrai’s Cloud Permissions Firewall, which operates directly at the cloud permission layer rather than brokering sessions or credentials.
From Skeptic to Customer
I deployed the Cloud Permissions Firewall in two very different environments: A regulated insurance enterprise and a top private equity firm.
In both cases, we deployed the control plane in minutes and enforced guardrails across the organization the same day.
For the first time, JIT actually worked.
Later, Sonrai partnered with Software Secured to validate the approach against real AWS attack paths. Sixteen real-world privilege escalation and persistence scenarios were tested. All sixteen were blocked. The difference between observing risk and controlling it was proven.
What Teams Mean When They Say “We Already Have JIT”
Almost every team tells me they already have JIT.
What they usually have is role switching with standing permissions, directory group changes, ticket-based approvals, or break-glass accounts. Sometimes there is automation, but the access never expires.
None of that JITs the permissions themselves.
This is why real just-in-time access in the cloud has to operate at the permission layer, not the account layer.
What Actually Matters in JIT
The question isn’t whether you have JIT.
It’s what you’re JIT’ing.
If the answer is user accounts or group membership, you’re solving the wrong problem.
The answer should be: Permissions on demand.
Governing the Permission Stack
Cloud identity risk should be owned by whoever controls organization-level policies. Permissions should remain explicit. IAM should not be hidden behind abstractions.
Modern cloud PAM has to govern the full permission stack:
| Layer | What’s Controlled |
| Account | External access and blast radius |
| Role | Privileged access sessions |
| Service | Which cloud services can be used |
| Permission | Sensitive API actions |
This is what Cloud Privileged Access Management actually means in practice.
AWS alone has more than 18,000 permissions. Most identities that hold powerful permissions never use them. That is standing privilege, not misconfiguration.
The Bottom Line
I spent years trying to make the wrong models work.
Shift left assumed developers could predict identity needs far in advance. They can’t. Legacy PAM assumed cloud privilege looked like users and sessions. It doesn’t. Homegrown automation assumed identity was a workflow problem. It isn’t.
In the cloud, privilege access management is a permissions problem. And permissions only become safe when they are enforced continuously, at the native control plane, without turning access into a bottleneck.
When permissions are granted only when they are needed, revoked automatically, and governed centrally, something important happens. Teams stop fighting security controls. Incidents stop turning into access drills. Standing privilege stops being the default.
That is what finally worked for me in production. Everything else was friction, drift, or false confidence.
