Designing credctl's team broker (v1 RFC)
Every team broker in the credential management space sits between the developer and the cloud. credctl’s team broker, in its v1 design, deliberately doesn’t.
This post explains why we made that call, walks through the v1 architecture, and points at the parts we’re least sure about. The full RFC is published as a GitHub Discussion — this is the narrative version. If you’re going to push back on the design (and we’d like you to), the RFC is where the architectural detail lives.
The most-requested feature, narrowed down
Section titled “The most-requested feature, narrowed down”Since the credctl CLI shipped, the most consistent demand signal has been a team broker. The pain breaks into three shapes, in roughly this order of frequency:
- Policy — “only senior engineers can assume the production role”
- Audit — “who assumed what role when, across the org, in one place”
- Device fleet management — onboarding, off-boarding, lost laptops
These are real problems. But they aren’t all the same shape of problem, and that mattered for what v1 should be.
When we looked closely at each one:
- Policy at the “X can assume role Y” level is already expressible in AWS IAM trust policies. The hard part is managing which user maps to which role at scale, not enforcing it at issuance time.
- Audit of role assumptions is already in CloudTrail. The hard part is mapping the cryptographic identity (the JWT
subclaim) back to a person, and aggregating cleanly across clouds. - Device fleet management is mostly a question of which public keys are currently trusted, and revoking the ones that aren’t.
All three shapes are addressable by a registry — a system that knows who’s on the team, which devices they have, and which roles they can assume, and that publishes this information to the cloud’s existing trust machinery. None of them require the broker to actually issue credentials.
So v1 doesn’t.
The architectural decision
Section titled “The architectural decision”In v1, the credctl team broker is not in the credential issuance path. The auth flow is unchanged from single-developer credctl:
- Laptop signs a JWT with the hardware-bound key (Secure Enclave or TPM 2.0)
- Laptop calls
sts:AssumeRoleWithWebIdentitydirectly against AWS - AWS STS fetches JWKS from the broker-hosted endpoint (cached at CloudFront)
- AWS STS validates the JWT against the JWKS and returns temporary credentials
The broker’s only role at runtime is hosting the JWKS. Its only role at design time is being the source of truth for the team’s roster, and emitting Terraform that keeps IAM trust policies aligned with that roster.
This is the smallest possible team broker compatible with credctl’s flow.
It also means the broker can be down for minutes without breaking developer auth — JWKS is served from CloudFront with aggressive TTLs, so STS hits the cache, not the broker. Broker compromise doesn’t directly compromise customer credentials: an attacker who pwned the broker could publish a malicious manifest, but the customer’s terraform plan would surface the diff before anything was applied. Broker availability is not on the critical path of credential issuance.
That’s the bet. Smallest blast radius, smallest surface area, smallest operational footprint compatible with solving the registry-shaped pain.
It is also very different from how every other broker in this space is designed. Vault, CyberArk Conjur, Venafi, Keyfactor — even SPIFFE in many deployments — all sit in the credential path. We think the cost of being in-path isn’t justified by the marginal capability it buys for v1.
What v1 ships
Section titled “What v1 ships”In scope:
- A SaaS-hosted registry of users, devices, and per-org role bindings, with GitHub OAuth as the v1 identity provider
- Per-org JWKS hosting, served via CloudFront
- An open-source Terraform module (
credctl/terraform-credctl-aws, published to the HashiCorp Terraform Registry) that consumes a manifest from the broker and produces IAM trust policy resources - A minimal admin web dashboard
- A broker-side audit log of admin actions in Postgres — complementary to CloudTrail, which remains the system of record for STS calls
Explicitly out:
- Real-time revocation. JWT expiry (~1 hour by default, tunable down to 15 minutes) is the only revocation mechanism — structural to the out-of-path design.
- Policy beyond membership. “Alice can assume role X” — yes. Time-of-day, IP allowlists, posture, attribute-based conditions — no, not in v1.
- Approval workflows. (Planned for Phase 4 of the roadmap.)
- SSO beyond GitHub. (Planned for Phase 5.)
- Self-hosted deployment.
- GCP and Azure role mapping. The data model accommodates them; the per-cloud Terraform modules ship later.
The “explicitly out” list is doing real work in the design. Each item is something some adopter will ask about, and the answer for v1 is “not yet.” Whether any of these eventually flips to “yes” depends on what the next section asks for.
What we’re uncertain about
Section titled “What we’re uncertain about”The RFC names three open questions. The most important is:
When does registry-only stop being enough?
We have candidate Phase 2 drivers — sub-minute revocation, per-request approval, cross-cloud policy, attribute-based conditions, business-context audit. But candidate scenarios aren’t the same as real ones. If your team is somewhere in the space where credctl might be a fit, the single most useful thing you can do is describe the specific scenario where v1 wouldn’t solve your problem.
We’d rather hear three concrete scenarios than a hundred abstract opinions.
The other two open questions are smaller but not trivial:
GitHub orgs/teams as source of truth for membership, or independent of GitHub? We’re defaulting to independent — membership lives in the broker’s database, decoupled from GitHub’s data model. Teams already running their access boundaries via GitHub orgs might prefer derived membership. The RFC asks for the concrete case.
Is the sub claim format right? We’re proposing user:<user-id>/device:<device-id> because it lets IAM trust policies match on the user via StringLike while keeping per-device fidelity in CloudTrail. It’s a one-way door once customers depend on it. The RFC asks whether you’d push back before the Terraform module ships v1.0.
What to do next
Section titled “What to do next”If you’d consider adopting a team broker like this, read the full RFC in the GitHub Discussion. It has the data model, JWKS layout, Terraform module shape, and revocation behaviour in detail. Then push back on the parts you’d hit first.
Channels for response:
- The RFC discussion on GitHub
- Direct:
rfc@credctl.com
Comment window is ~2 weeks. Implementation begins once the architectural questions settle. The Phase 2 question can stay open longer — we’d rather gather real scenarios than design speculatively.
Stay up to date
Get notified about new credctl releases, security best practices, and hardware identity insights.