Skip to content
All writing
Security6 min read

Least privilege for identities that are not people

Your IAM model assumes a human on the other end who gets tired, goes home, and can be asked what they were thinking. None of that is true of a machine.

Inès Lefebvre

Head of Security

Access control as most organisations practise it carries an unstated assumption: that a credential belongs to a person, and that the person provides a layer of judgement between the permission and its use. An engineer with production write access does not use it a thousand times an hour, and if they did, someone would notice.

An automated client has the permission and none of the judgement, operates at machine rate, and does not get tired. The same grant is a materially different risk.

Scope to the task, not to the actor

The instinct is to create one service account per workload and grant it the union of everything that workload might ever need. This reproduces the problem: a long-lived identity with a broad standing grant, differing from the human case only in that it never sleeps.

The alternative is to issue credentials per job, scoped to the task, expiring on completion. It is more moving parts, and it changes the question an auditor can answer from 'what could this thing do' to 'what was this specific job permitted to do, and why'.

const grant = await halyard.grant({
  job: job.id,
  scopes: ["crm:contacts:read", "crm:notes:write"],
  resources: { account: task.accountId },   // this account, not all accounts
  ttl: "10m",
  reason: task.description,
});

The `reason` field is not decoration. It is the only part of this record that a non-engineer can read, and it is the field that gets quoted back in an incident review.

Three failure modes worth designing against

  • Scope creep by accretion. A workload needs one new permission for one new task, and the grant is widened permanently. Per-job grants make this structurally impossible.
  • The confused deputy. A client with legitimate access is induced by untrusted input to use it on an attacker's behalf. Resource-scoped grants contain the damage even when the induction succeeds.
  • Orphaned credentials. A workload is retired and its service account is not. Expiry by default means the credential dies whether or not anyone remembers it.
Treat every credential a machine holds as though it will one day be pointed at something you did not intend. Design for that, because it is not a hypothetical.

None of this is novel security thinking. It is ordinary least-privilege, applied without the assumption of a human in the loop — and it is that assumption, rather than the controls themselves, that most existing models quietly depend on.

Keep reading

  • Engineering

    A log is not an explanation

    A complete log tells you everything the system did and nothing about why it did it. The gap between those two is where the hard afternoons go.

Point it at what you already wrote.

Connect one source, run a week in draft mode, and read the diff against your team's replies. If it isn't better, you've lost an afternoon.

Free for 14 days · No card required

Live demo of Vantis · see all five brands