Least Privilege and Credential Rotation Across 60 Services
A production Atlas project has 22 database users. Sixty microservices share a single SCRAM user with readWriteAnyDatabase, created in 2019, whose password was found last week in a public GitHub repository (since deleted). The organisation is adopting LDAP for workforce authentication but wants application users to stay SCRAM. A contractor needs read access to one collection, analytics.events_rollup, for 30 days. Internal audit, driven by a SOC 2 review, asks for evidence of who changed cluster configuration and who connected to production databases. The Atlas organisation has three owners, all using personal email addresses, one without MFA. Nobody knows which service depends on which database.
1. Design the target access model and the immediate exposure remediation. What can you do before you know each service's real dependencies?
Read the worked answer
Immediate (today): rotate the leaked credential and treat all data as potentially exposed - check Atlas access logs and audit log for connections from unfamiliar sources before the rotation, then disable the user. Because 60 services depend on it, rotation is a deployment, not a click: create replacement users first (see next task), not a password change that breaks production at once.
Target model
- One SCRAM user per service, named after the service, authenticated against
admin, with roles scoped to the specific database(s) it uses -readWriteonshop, notreadWriteAnyDatabase. - Collection-level needs require a custom role:
{ resource: { db: "analytics", collection: "events_rollup" }, actions: ["find"] }. Built-in roles cannot be narrowed to one collection, which is why the contractor case needs a custom role. - Separate users for humans and for automation; no shared credentials between teams.
- Atlas organisation access is not database access: the contractor gets a database user only, never project or organisation membership.
Before dependencies are known: cluster the work. Use the audit log and current connection statistics to map which databases each service touches, then migrate the highest-risk services (customer data, payments) first, assigning readWrite on the smallest database that keeps them functional. Any service still unresolved gets a temporary user scoped to one database - never back to a cluster-wide role.
2. How do you rotate credentials for 60 services with no downtime, and how do you stop this recurring?
Read the worked answer
Add-then-remove, never replace-in-place. Existing authenticated connections survive a password change, but new connections need the new secret, so a straight changeUserPassword turns any deploy lag into an outage.
- Create
svc-<name>-v2for each service with the same scoped roles. - Store the new credential in the secrets manager under a new version; have services read the current version at startup.
- Roll deployments in waves of ~10 services, monitoring connection errors and auth failures per user.
- For each wave, confirm the v1 user has zero connections, then delete v1. Deleting the user terminates its remaining sessions - which is also your containment tool if a key leaks.
Prevent recurrence
- Secrets manager with rotation; no credentials in environment files or repositories. Add secret scanning to CI and block the build on a hit.
- Prefer short-lived credentials where the platform supports them; SCRAM passwords are long-lived by nature, so treat rotation as routine, not incident-driven.
- Scope the API keys as well: organisation keys only for organisation automation, project keys per project, and no human work done with automation keys.
- Fix the organisation layer: enforce MFA for all owners, replace personal-email owners with role accounts or groups, and reduce owners to two with a documented break-glass path.
3. What does the LDAP rollout change for database users, and what evidence can you give the auditors?
Read the worked answer
LDAP covers people, SCRAM covers workloads - keep them separate. Enabling LDAP lets workforce users authenticate to Atlas and to the database via $external with group-to-role mapping, which is a big win for joiner/mover/leaver: disabling a person in the directory removes database access without a ticket to the DBA. But LDAP becomes an availability dependency on the authentication path, so leave application SCRAM users as SCRAM. Otherwise an identity-provider outage stops every service from opening new connections.
Contractor case: create a custom role limited to find on analytics.events_rollup, assign it to the contractor's LDAP-backed user, and put the 30-day expiry in the directory group membership rather than in a calendar reminder - the removal must be enforced by the directory, not by memory.
Audit evidence
- Ship the Atlas audit log to an S3 bucket in a separate, restricted account; it captures administrative actions and authentication events for database users. Retention must match the SOC 2 window, and access to the bucket must not be controlled by the same people who administer Atlas.
- Export project access lists and database user change history via the Admin API on a schedule, so you can show current and historical state.
- Test one real question end to end before the audit: 'who dropped the index on orders on 14 March, and from which IP?' If you cannot answer it in minutes, the control is not working.