Secrets, PKI & CertificatesI · Secrets and Identity FoundationsFoundations
Human identity, machine identity and workload identity
What you'll learn
- Distinguish human, machine and workload principals by their lifecycle constraints
- Explain why passwords and second factors degrade to a single factor on a machine
- Describe how a platform attestation becomes a workload credential
- Name the trust anchor at which an identity chain stops being cryptographic
Prerequisites
Verified against OpenSSL 3.5.x teaching target; 3.0+ minimum · OpenSSH 10.x teaching target; 8.2+ minimum for certificate workflows · OpenBao 2.6.x · Smallstep step-ca 0.30.x · Certbot / Pebble Certbot current release; Pebble 2.10.x ACME test server · Kubernetes (cross-course target) 1.36.x · PostgreSQL 17.x · 2026-08-26
Identity is not one problem with one answer. A person, a server and a container instance differ in how they come into existence, how long they last, how quickly access must be withdrawn, and whether anybody is present to type something. Those four differences are enough to force three separate designs, and most of the awkwardness in real estates comes from a pattern built for one principal being stretched over another.
Three principals with three different constraints
A human exists before the system does and continues after it. Enrolment is an organisational event with identity proofing attached to it, and withdrawal is an organisational event too, usually on a known date. A person is present, can be asked to confirm something, and can be deceived. They authenticate irregularly, across dozens of unrelated services, and they forget things, so recovery is a first-class part of the design rather than an edge case.
A machine is a host: a physical server, a virtual machine, a network appliance. It exists for months or years, it is expected to come back after a power cut with no operator present, and its identity is anchored either to hardware or to the moment it was provisioned. Nobody is available at 03:00 to approve anything, so every credential it holds must work unattended, which by construction rules out anything that depends on a person.
A workload is a running instance of code: a container, a pod, a serverless invocation. It may exist for forty seconds. Twenty identical copies may run at once and share one logical identity while being individually disposable. Crucially, the instance did not exist at the moment anybody configured anything, so there was no opportunity to enrol it in advance and no safe place to have put a secret it could later present.
flowchart TD
H["Human"] --> H1["Enrolled by an organisation\nwith identity proofing"]
H1 --> H2["Short session after a\nphishing-resistant login"]
M["Machine"] --> M1["Enrolled at provisioning\nor anchored in hardware"]
M1 --> M2["Durable key plus a\nrenewable host certificate"]
W["Workload"] --> W1["Attested by the platform\nit is running on"]
W1 --> W2["Short-lived credential\nissued on demand"]
Each row is an enrolment path, and the difference between the rows is where the first trustworthy statement comes from. For a person it comes from an organisation checking documents. For a host it comes from hardware or from the provisioning system that built it. For a workload it comes from the platform scheduling it, because nothing else was present at the moment it started.
Why the human pattern breaks on a machine
The failure is not that machines are somehow less trustworthy. It is that every property a human credential relies on disappears.
- A password assumes a memory and a prompt. Give one to a machine and it becomes a file. The knowledge factor collapses into a read permission, and the strength of the credential is now the strength of the filesystem mode, not the entropy of the string.
- A second factor assumes two independent channels. On an unattended host both factors sit on the same disk under the same user, so an attacker who reaches one reaches both. What looks like multi-factor authentication is single-factor authentication with extra moving parts to break.
- Human revocation runs at ticket speed. Removing an account within a working day is acceptable for a leaver and useless for a compromised workload credential that is being used right now by an automated process making thousands of calls a minute.
- Human identity is one-to-one; workload identity is one-to-many. If twenty replicas share one static secret and it appears in a paste site, no evidence can tell you which replica leaked it, and the remedy affects all twenty at once.
- Rotation means different things. For a person it is a password change. For a service it is a deployment with an ordering constraint, because the verifier must accept both the old and the new value during the overlap or the change is an outage rather than a rotation.
- A person can decline. A human can notice that a login prompt looks wrong. An unattended client will authenticate to anything that answers on the expected address, which is why verifying the server and binding the credential to that channel matters more for machines, not less.
Machine identity and the enrolment moment
The hard part of machine identity is the first credential. A freshly built host has nothing that distinguishes it from an attacker’s host claiming the same name, so something has to make the first assertion. In practice there are four candidates: a bootstrap token planted by the provisioning system, a hardware root such as a TPM holding a key installed during manufacture, a signed instance identity document from a cloud provider, or a human at a console. Every estate uses one of these whether or not anybody has written it down.
Once enrolled, the host holds a durable private key and receives a certificate that names it. For SSH this replaces the distribution problem that host keys create.
# Sign the host public key for one year, with the host CA.
ssh-keygen -s host_ca -I "sshd.lab.example" -h -n sshd.lab.example -V -5m:+52w hostkey.pub
Two flags carry the whole design. The -h flag makes this a host
certificate rather than a user certificate, and the -n flag
fixes the names the certificate is valid for, which is what a
client checks. The -V flag sets the validity window, and it is
not optional in any real sense: without it the certificate is
valid from the Unix epoch to the distant future, which is the
opposite of what a machine credential should be.
On the client side, one line in known_hosts beginning with the
@cert-authority marker replaces every per-host key entry for a
domain. The effect on operations is large: a rebuilt host gets a
new key pair and a new certificate, and no client anywhere prints
a changed-host-key warning, because clients were never trusting
the host key in the first place. They were trusting the CA.
Workload identity and the attestation shortcut
A workload cannot present a pre-shared secret, because there was nowhere honest to put one. Baking a credential into a container image makes it a shared secret inside a published artefact, and every replica, every cached layer and every developer pull holds the same copy. The way out is to stop trying to give the workload a secret in advance and instead let the platform vouch for it at run time.
Kubernetes does this with the TokenRequest API. The kubelet obtains a token for the pod’s service account and projects it into the container filesystem, and the pod presents that token to whatever it needs to authenticate against.
volumes:
- name: bao-token
projected:
sources:
- serviceAccountToken:
path: token
audience: bao.example.com
expirationSeconds: 3600
The audience field is the part that deserves attention. A token
minted for bao.example.com carries that audience inside it, and
a correctly configured verifier rejects a token whose audience
names somebody else. That is the mechanism preventing a token
intended for the secret manager from being replayed against the
cloud provider, and it is why one workload should hold several
narrow tokens rather than one universal one.
# Mint a short-lived token for a service account, on demand.
kubectl create token app-sa --duration=1h
SPIFFE generalises the same idea across platforms. A workload
receives an identity document whose subject is a URI such as
spiffe://example.com/ns/payments/sa/api, carried in the
certificate as a URI subject alternative name. The agent on the
node decides which document a caller is entitled to by inspecting
verifiable facts about the calling process and matching them to a
registration entry made in advance. The workload proves its
identity by holding the corresponding private key, which never
leaves the node, so nothing replayable ever crosses the wire.
Where the chain actually terminates
Follow any identity chain far enough and it stops being cryptography and becomes an assertion somebody made. A TPM endorsement key was installed during manufacture. A cloud provider signs an instance identity document because it built the instance. A registration entry says that a process with these attributes on this node is the payments API. A human approved a certificate signing request at a console.
Naming that termination point is the single most useful thing you can do when reviewing an identity design, because its compromise is total. An attacker who can make the platform attest a workload that is not yours does not need to steal any key: everything downstream will believe them, correctly, according to the rules you configured. If nobody on the team can name the anchor, the anchor is whatever the installation process happened to do, and that is not a design.
Production discipline
- Classify the principal before choosing the credential. Write down whether the holder is a person, a host or a workload, because that single answer eliminates most of the options immediately.
- Never issue a human-shaped credential to an unattended process. A password in a config file and a second factor on the same disk are both accounting fictions.
- Scope every workload credential to one audience. A token accepted by two verifiers has the blast radius of both, and audience checking is usually one configuration line away.
- Pair every issuance command with an explicit validity window. For SSH certificates in particular, omitting the validity flag produces a credential valid for effectively all of time.
- Write the trust anchor into the design document. Name the hardware, the provider, the registration authority or the person. An unnamed anchor cannot be reviewed, monitored or replaced.
Cross-course references
- Kubernetes for Production Sysadmins - Part LX (ServiceAccounts) covers the projected token lifecycle in the cluster, including how a pod obtains one and what happens when the audience does not match.
- Linux for Production Sysadmins - Part XXVII (Auth) covers the host-side authentication stack that decides which credentials a login is allowed to present at all.
- Git, CI/CD & GitOps for Infrastructure Engineers - Part XLIII (OIDC) covers the same attestation idea applied to a pipeline, where the forge vouches for a job instead of a platform vouching for a pod.
Quiz
Knowledge check · 4 questions
Q1. A team proposes giving each of its twenty API replicas the same static token, stored in the container image, and enabling a time-based one-time password as a second factor for that token. What is the main flaw?
Q2. Trusting an SSH certificate authority in known_hosts means a rebuilt server with a brand new host key does not trigger a changed-host-key warning on clients.
Q3. Explain why a workload cannot simply be given a long-lived secret in advance, and what replaces that approach.
Q4. Identify which principal each credential belongs to and what must change.
An estate has forty hosts. Each host holds a copy of a shared SSH private key called deploy_key, used by a scheduled job and also pasted into the onboarding document so new engineers can run the same job by hand. A separate ansible-runner account uses a password stored in the automation tool. On 2026-08-24 an engineer left the company; their laptop still holds a copy of deploy_key.
Passing score: 75%. Answers are checked in this browser.