Skip to content
Français
Account: not signed in, sync available My learning
Select theme
Français
Lire en français

Secret lifecycle: the 8 key stages

By updated

Improve this page

A secret is not a fixed object: it is born, stored, distributed, used, must be rotated, can be revoked, and access to it must be audited. This lesson is for the DevOps engineer who has to formalise this path so that a rotation or a revocation is no longer a risky operation. It describes eight stages, preceded by a framing step, with the moves that make them automatable.

The commands were replayed on Vault 2.1.1 in development mode, and the KV engine ones on OpenBao 2.7.0 too. Two reads of database/creds/app produce two distinct PostgreSQL users valid for one hour, and revoking the lease removes the role from the database. And vault kv destroy on the secret/data/... path, a common form in tutorials, destroys nothing: the command answers Success! and the version remains readable.

What you will learn

  • Frame each secret before it is created: inventory, classification, owner
  • Walk through the eight operational stages, from generation to destruction
  • Tell apart the three rotation models and choose the right one for each secret
  • Revoke a dynamic secret and check that it has disappeared from the database
  • Avoid the kv destroy trap, which answers Success! without destroying anything
  • Anchor the approach in SOCLE-SEC-ROT-1 (in French), the rotation policy and the TTL per secret

Lifecycle overview

The diagram sums up the path: a framing stage 0, then eight operational stages from generation to destruction. Audit is not a stage like the others, it is cross-cutting and watches all the others. Rotation, in red, periodically leads back to generation: it really is a cycle, not a straight line.

Secret lifecycle: inventory and classification, then generation, storage, distribution, use; rotation leads back to generating a new version, compromise or end of life leads to revocation then destruction; audit watches every stage.new versioncompromiseor end of lifewatches every stage0. Inventory and classification1. Generation2. Storage3. Distribution4. Use5. Rotation6. Revocation8. Destruction7. Audit (cross-cutting)
Source · SVG
Esc to close, + and − to zoom, scroll to move around. 100 %

0. Inventory, classification and ownership

Before even generating a secret, you need to know who owns it, who uses it and what it protects. Without this groundwork, no rotation, revocation or destruction can be reliably automated, since the script would not know which services to notify.

What to define at creation

These metadata are not paperwork: they are what the on-call engineer looks up at three in the morning when a token leaks, and what a rotation script reads to know which services to restart. Filling them in costs two minutes at creation and saves hours during an incident.

Each secret should carry, from its creation:

  • an owner (responsible team or service)
  • a list of consumers (services, systems, pipelines)
  • a criticality level (critical, standard, low)
  • an expected lifetime (short, long, permanent)
  • a documented rotation procedure
  • an emergency procedure in case of compromise

Secret classification

Not all secrets deserve the same effort. Classification puts each secret in a class that sets its rotation frequency and the level of control. A compromised root secret opens all the others, whereas a session token expires on its own within minutes: treating them the same way wastes effort where it is useless.

ClassExamplesCriticalityRotation
Root secretDatabase administrator account, master keyVery highAfter each use
Service secretService-to-service token, pipeline credentialHighAutomated, frequent
Application secretApplication database password, external API keyStandardPlanned
Temporary secretSession token, one-time codeLowNative expiry

Minimal register

A register can be as simple as a YAML file versioned in Git, which contains no secret value, only its metadata. What matters is that it exists and is maintained: an outdated register gives a false list of consumers on the day of the revocation.

# Minimal register: metadata, never a value
- name: db-production
owner: team-platform
consumers: [api-service, worker-service]
criticality: high
rotation_policy: automated-30d
emergency_contact: oncall-platform

1. Generation

Generation is the birth of the secret, and the most definitive stage of the cycle. A secret created with insufficient entropy (the real amount of randomness it contains) stays weak all its life: neither encryption nor rotation makes up for a predictable generator. The rule fits in one sentence: use the system's cryptographic generator.

Good practices

Requirements differ according to the recipient. A human must be able to type the secret or hand it to a password manager, which limits its useful length; a machine has no such constraint and can receive 256 bits of pure randomness.

Type of secretMain requirementImplementation
Human passwordLength, memorability16 characters or more, password manager
Machine token or secretPure entropyCryptographic generator, 256 bits or more
Provider API keyQuality of the sourceIssued by the provider, never generated locally

Not all secrets are generated in-house. A provider API key, a cloud token or a credential from a dynamic secrets engine get their quality from their source: your role is then to store, distribute and revoke them correctly, not to generate them.

Generation examples

The commands below all draw from the system's cryptographic generator (/dev/urandom on Linux) and print the secret on standard output. Redirect this output to your vault: left as is, the value stays in the shell history and in the terminal scrollback.

Terminal window
# 32 random bytes (256 bits), base64-encoded
openssl rand -base64 32
# 32 bytes in hexadecimal, for an AES-256 encryption key
openssl rand -hex 32
# API token: Python's secrets module, designed for cryptography
import secrets
token = secrets.token_urlsafe(32) # 32 bytes of randomness

Common mistakes

The following three cases produce a secret that has the appearance of randomness without its properties. Python's random module is deterministic once its seed is known, a hash of public data can be replayed in a second, and an old secret with a suffix stays breakable if the original has already leaked.

# ❌ Non-cryptographic generator
import random
password = ''.join(random.choices('abcdefgh', k=8))
# ❌ Secret derived from predictable data
password = hashlib.md5(username.encode()).hexdigest()
# ❌ Reuse of an existing secret
new_password = old_password + "2026"

2. Storage

Storage determines who can read the secret back and for how long. A well-generated secret dropped into a versioned file is already compromised: the question is no longer whether someone will find it, but when. The right reflex is to centralise it in a vault (a dedicated secrets manager) that encrypts, traces reads and can revoke.

Good practices

These four requirements add up, none replaces the others. Versioning is the one most often neglected: without a history of versions, a failed rotation cannot be replayed, and the service stays down while the secret is rebuilt.

PracticeImplementation
Encryption at restAES-256-GCM or equivalent, provided by the vault
Access controlStrict policies, least privilege
CentralisationOne vault, no copies
VersioningVersion history to roll back

Storage options

Encryption at rest is necessary but not sufficient. Good storage can also tell who can read what, who read what and when, change the secret without breaking the application and invalidate a compromised secret. Without these capabilities, an encrypted file remains a black box.

SolutionUse caseWhat it brings
OpenBao / HashiCorp VaultCentral vault, dynamic secretsPolicies, audit, revocable leases
AWS Secrets ManagerAWS ecosystemManaged rotation, CloudTrail log
Azure Key VaultAzure ecosystemEntra ID access control
GCP Secret ManagerGCP ecosystemIAM access control
InfisicalOpen source, teamsInterface, synchronisation
SOPSEncrypted files in Git (GitOps)Encryption, no audit of reads
Kubernetes SecretsDistribution within the clusterNot a vault: etcd encryption, strict RBAC and often an external operator

Common mistakes

These three situations have one thing in common: the secret exists in clear on a disk, outside any access control and without the slightest trace of reading. It is then impossible to know who looked at it, or to guarantee it has disappeared everywhere after a rotation.

# ❌ Secret in an unencrypted file (config.yaml)
database:
password: SuperSecret123
# ❌ Secret in a persistent environment variable (~/.bashrc)
# export DB_PASSWORD=SuperSecret123
# ❌ Secret in a personal password manager
# (no audit, no controlled sharing)

3. Distribution

Distribution is the journey between the vault and the process that consumes the secret. It is the most exposed stage of the cycle: each intermediary added (file, image layer, environment variable) becomes a copy to protect and then destroy. The goal is to shorten this journey and to open it only to an authenticated identity.

The first-access problem

Before distributing a secret, a question arises: how does the application prove its identity to the system that delivers it? How does an agent authenticate at startup, how does a pod get the right to read a secret, how does a CI runner exchange an OIDC identity for access?

This is the bootstrap trust problem, or secret zero problem. Without an attestation mechanism, you just move the problem: instead of a secret in the code, you have an access token to protect. The next lesson is entirely devoted to it.

Good practices

Injection at startup is the most structuring of the four: as long as the secret appears in an image or a configuration file, it can be reproduced by anyone who gets hold of the artifact, even months later.

PracticeImplementation
Injection at startupNever in the code or in a static configuration
Encrypted channelTLS for retrieval
AuthenticationThe application proves its identity
Minimal durationThe secret exists in memory only as long as needed

Distribution methods

Three approaches coexist depending on where the application runs. They are equal in security; what sets them apart is the component that carries the authentication: a local agent, the orchestrator, or the CLI that launches the process.

1. Injection by a vault agent: the agent authenticates, retrieves the secret, writes it to a file or a variable and renews it before expiry.

Terminal window
# Vault Agent (or bao agent for OpenBao) with its configuration file
vault agent -config=agent.hcl

2. Injection by the orchestrator: the External Secrets operator reads the vault and creates a Kubernetes Secret. In its version 2.11.0, only the external-secrets.io/v1 API is served: a manifest in v1beta1 is rejected by the cluster, measured on ESO 2.11.0 and Kubernetes 1.37.

apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: db-credentials
namespace: payment
spec:
refreshInterval: 1h
secretStoreRef:
kind: SecretStore
name: vault-backend
target:
name: db-credentials
data:
- secretKey: password
remoteRef:
key: production/db
property: password

The same manifest in v1beta1 fails on submission with no matches for kind "ExternalSecret" in version "external-secrets.io/v1beta1". The ESO 2.11.0 CRD still declares this version, but with served: false: it no longer exists for the cluster.

3. CLI at startup: the tool authenticates, injects the secrets as environment variables and launches the application.

Terminal window
# Infisical injects the secrets then launches the application
infisical run -- npm start

Common mistakes

The cases below share the same flaw: the secret leaves the controlled channel, and nobody knows where it ended up. A complete revocation becomes impossible, since the list of copies is unknown.

Terminal window
# ❌ Secret exported to a .env file
cp vault-export.env .env
# ❌ Secret passed as a command argument (visible in ps)
./myapp --db-password=SuperSecret123
# ❌ Environment variable without precautions: visible in /proc/PID/environ,
# inherited by child processes, captured by crash reports
export API_KEY=s3cr3t123
# ❌ Secret file readable by everyone (must be 0400 or 0600)
chmod 644 /run/secrets/db-password
# ❌ Secret loaded at startup and never reread: rotation on the vault side
# stays invisible to the application, which keeps the old value

4. Use

Use is the only moment when the secret must exist in clear in the process. The whole point is to stay there as briefly as possible and never let it leak through a side channel: a debug log, a stack trace (the call trace printed on an error) or a crash report. Most leaks come from a secret copied into a log, not from a sophisticated attack.

Good practices

The first row is the one most often broken: a secret loaded once at startup into a global variable stays in memory for the whole life of the process, and it survives rotation on the vault side, since the application never rereads it.

PracticeImplementation
Minimal time in memoryLoad just before use, limit copies
No loggingNever print the secret
Single connectionOpen the connection once, reread the secret on reconnection
Error handlingDo not expose the secret in exceptions

Example

The following snippet reads the secret from a file mounted by the vault agent, uses it immediately to open the connection, then releases the reference. It illustrates the right intention, not a guarantee of erasure: in Python as in Java, assigning None does not remove the value from memory.

# Load the secret from a file, open the connection
def get_db_connection():
with open('/etc/secrets/db-password') as f:
password = f.read().strip()
conn = psycopg2.connect(host="db", user="app", password=password, dbname="mydb")
# Shortens the lifetime of the reference, without guaranteeing erasure
# (internal copies, garbage collector, buffers)
password = None
return conn

In managed languages (Python, Java, Node.js, Go), the garbage collector and implicit copies often keep the value accessible. The real protection lies elsewhere: load as late as possible, never store the secret in a class attribute or a cache, never expose it in an exception, and isolate the process with minimal permissions.

Common mistakes

These three mistakes make the secret readable without going through the vault: a class attribute can be inspected from anywhere in the code, a log goes to the central aggregator, and an exception often travels all the way back to the HTTP response.

# ❌ Secret stored in a class attribute
class Database:
password = "SuperSecret123" # accessible via Database.password
# ❌ Secret in the logs
logger.debug(f"Connecting with password: {password}")
# ❌ Secret in the exception
raise Exception(f"Connection failed for {username}:{password}")

5. Rotation

Rotation replaces a still-valid secret with a new one, at regular intervals or after an incident. It reduces the exposure window: a secret stolen and then replaced has no value left. It is also the stage most often abandoned, because a badly designed rotation breaks production; designing it automated from the start makes it sustainable.

Good practices

A rotation that has never been tested does not exist. It is usually on the day of the incident that you discover the application never rereads its secret, or that the service account is not allowed to change its own password. Requirement SOCLE-SEC-ROT-3 actually asks for a documented emergency rotation test.

PracticeImplementation
AutomationRotation without human intervention
No interruptionA period when both versions work
Suitable frequencyThe more critical the secret, the more frequent
Tested regularlyRotation drills, with a report

The 3 rotation models

The model depends on what triggers the change: a schedule, an event, or the simple expiry of the secret. The first two require explicit orchestration; the third removes it by making each secret disposable from the moment it is issued.

1. Planned rotation. For database passwords, API keys and long-lived tokens, rotation follows a schedule. The sequence makes the old and the new value coexist during the switch, a period called dual-active.

T0: secret A active
T1: generate secret B
T2: A and B active together (dual-active)
T3: migrate all consumers to B
T4: deactivate A, then check that it fails

The dual-active period avoids a production incident during the switch: you never deactivate the old secret before all consumers have migrated. Some providers cap it: an AWS IAM user can only hold two access keys at a time.

2. Event-driven rotation. It is triggered by an incident, an employee's departure or a change of role. For a confirmed compromise, the order changes: you revoke first, accepting an outage, because leaving the old secret active during the migration also leaves the door open to the attacker. The last lesson of the module details this order.

3. Native expiry (dynamic secrets). The logic is no longer a rotation, but generation on demand with automatic expiry, the lease. Measured on Vault 2.1.1 with PostgreSQL 17: each read creates a distinct user, valid for one hour, which the database knows with an expiry date.

Terminal window
$ vault read database/creds/app
Key Value
--- -----
lease_id database/creds/app/aMTXQzqtuyKCe9yO7pHw624a
lease_duration 1h
lease_renewable true
password vL-0OqdMgh3CGQ4T36k6
username v-token-app-NkdSHbitYpic3j25kQ0Z-1790862956
# A second read created another user (lease OTOY...); we renew it
$ vault lease renew database/creds/app/OTOYt9CsPoFYt3CvqCZ7QEQn
lease_duration 1h

The duration comes from the role (default_ttl=1h, max_ttl=24h): renewal pushes back the deadline without exceeding the max_ttl. On the PostgreSQL side, each user carries a VALID UNTIL aligned with the lease: even if Vault went down, the credential would expire on its own.

Indicative frequencies

The values in the table are a starting point when no regulatory constraint or provider limit already imposes a pace. NIST talks about a cryptoperiod (SP 800-57) and recommends a risk analysis, not a fixed grid. For human passwords, OWASP relays NIST's position: they are changed on suspicion of compromise, not on a schedule.

Type of secretIndicative frequencyComment
Root credentialsAfter each useNever leave them lying around
Production secrets30 to 90 daysAdapt to criticality
API tokens30 to 90 daysMore exposed, shorter
CertificatesBefore expiryAutomate, for instance with cert-manager
Dynamic secretsOn each requestShort TTL, no rotation
Human passwordsOn suspicion of compromiseNIST position relayed by OWASP

Common mistakes

Three classics repeat from one team to the next: rotation postponed for lack of automation, rotation that breaks production because the old secret was deactivated without a dual-active period, and rotation that produces a secret derived from the previous one, hence guessable.

❌ "We'll do it next quarter" forgotten manual rotation
❌ Old secret deactivated before migration rotation that breaks applications
❌ "I'll just add a digit at the end" guessable new secret

6. Revocation

Revocation makes a secret unusable immediately, without waiting for its expiry. It is the emergency move of the cycle: suspected compromise, an employee's departure, a key published in a public repository. Its value is measured by the delay between detection and invalidation, and by its completeness: a secret revoked in one place only remains active elsewhere.

Good practices

The ability to revoke is prepared in advance. In the middle of an incident, nobody improvises the command that invalidates a token or the list of services to restart: the runbook written beforehand makes the difference between ten minutes and half a day.

PracticeImplementation
Immediate revocationAbility to invalidate within minutes
Complete revocationAll copies, all systems
CheckConfirm that the old secret no longer works
Documented procedureReady-to-use runbook

Revoking a dynamic secret: measured

With a dynamic secret, revocation is a single command, and it can be checked in the target system. Measured on Vault 2.1.1: after vault lease revoke, the PostgreSQL user no longer exists, and the -prefix option revokes all the leases of a role at once.

Terminal window
$ vault lease revoke database/creds/app/OTOYt9CsPoFYt3CvqCZ7QEQn
All revocation operations queued successfully!
$ psql -U postgres -tAc "select count(*) from pg_roles where rolname = 'v-token-app-5tvL7mCwBctCAF5bH1ri-1790862956'"
0
# Revoke every credential issued by the role, for instance after a leak
$ vault lease revoke -prefix database/creds/app
All revocation operations queued successfully!

The same principle applies to a Vault token: measured, a token created with -ttl=1h shows creation_ttl: 3600, and after vault token revoke any attempt to use it fails. This final check is the step procedures forget most.

Standard procedure

For a static secret replaced without compromise (departure, end of life), the new secret is deployed before the old one is revoked, otherwise the service goes down. The final check is not optional: as long as nobody has seen the old secret fail, the procedure is not closed.

  1. Detect the end of life or the need for replacement
  2. Assess the impact and the list of consumers
  3. Generate a new secret
  4. Deploy the new secret to the applications
  5. Revoke the old secret at the provider and in the vault
  6. Check that the old secret no longer works
  7. Document the operation in the register

In the event of a confirmed compromise, steps 4 and 5 are swapped: revocation comes first, even if it cuts the service for a few minutes. The lesson Responding to a compromised secret explains why this order wins.

Revocation and propagation

Revoking a static secret only makes sense if all consumers have switched over. Otherwise, a security incident becomes a production incident. The five questions in the table are asked before pressing the button, not after.

QuestionWhy it matters
Which services consume this secret?Inventory of consumers to migrate
In what order should they migrate?Avoid circular dependencies
How do you check it has been picked up?Health checks, application logs
What is the rollback plan?If the migration fails before revocation
What delay is acceptable?Trade-off between security and stability

Common mistakes

These three situations leave a compromised secret active while the team believes the incident is closed. It is the worst state: nobody watches any more, and the attacker keeps their access.

❌ "I changed the password in Vault" partial revocation (3 .env files still have it)
❌ "It should be revoked by now" no check
❌ "We'll do it tomorrow" revocation too slow

7. Audit

Audit records who read, wrote, rotated or revoked each secret. It protects nothing by itself, but it is the only source able to answer the question that follows a leak: which data was exposed, and since when. Without a usable log, a contained incident turns into widespread suspicion, and everything gets rotated as a precaution.

Good practices

Log protection is the most neglected row. An attacker who gains admin rights erases their tracks if the log remains modifiable on the same machine: hence the value of separate storage, write-only, and of centralisation in a SIEM.

PracticeImplementation
Complete logsWho, what, when, from where
CentralisationSIEM or log aggregator
Real-time alertsSuspicious access, abnormal volumes, repeated failures
Log protectionImmutability, separate storage
RetentionCompliance and investigation

What to trace

Effective audit captures every interaction with a secret, but also the vault's administration operations, often more critical: policy changes, enabling an engine, adding an authentication method, sealing and unsealing.

EventInformation
CreationWho created it, when, what type
ReadWho read it, when, from which address
ModificationWho modified it, when
RotationWho triggered it, automatic or manual
RevocationWho revoked it, why
Access failureWho failed, why

Example: a real Vault audit log

Vault never writes sensitive values in clear: each confidential string appears as an HMAC-SHA256, a fingerprint computed with a key specific to the audit device. Here is the entry produced by Vault 2.1.1 for a read of secret/production/db, reduced to the useful fields.

{
"time": "2026-10-01T13:33:43.983030165Z",
"type": "response",
"auth": {
"accessor": "hmac-sha256:a6937a3e4b51...",
"client_token": "hmac-sha256:1dc68317ea49...",
"policies": ["root"],
"token_type": "service"
},
"request": {
"operation": "read",
"path": "secret/data/production/db",
"remote_address": "127.0.0.1"
},
"response": {
"data": {
"data": {
"password": "hmac-sha256:e4a524c253fb6eb7fc9cf8fa59c308c8afc70810d2cabfe2a62d97ced2a7478c"
}
}
}
}

The fingerprint makes it possible to correlate without revealing: vault write sys/audit-hash/file input=SuperSecret123 returns exactly the same HMAC as the one in the log. An investigator can therefore check whether a precise value was read, without the log containing it. On OpenBao 2.7.0, measured, an audit device can no longer be enabled through the API (cannot enable audit device via API): it is declared in the server configuration.

Common mistakes

Three ways to end up blind at the exact moment you need to see. Disabling audit to save a few milliseconds costs the ability to qualify an incident; logs kept locally disappear with the compromised server; and without an alert, nobody opens the log before disaster strikes.

❌ Audit disabled "for performance"
❌ Logs left on each vault, not centralised
❌ "We'll look at the logs if something happens" no alert

8. Destruction

Destruction makes the secret permanently unusable and eliminates, as far as possible, all its copies. It is the most irreversible stage: a destroyed version cannot be recovered. Before launching it, check that no data encrypted with this secret still needs to be read, otherwise you destroy the data along with the key.

Revoking is not destroying

Revoking a secret invalidates it: it no longer works. But it can still exist in backups, forgotten .env files, build artifacts or shell histories. Destruction aims to eliminate the operational copies; in immutable backups, a retention and expiry policy applies.

PracticeImplementation
Version purgeDestroy old versions in the vault
Cleaning up copiesTemporary files, backups, CI
ZeroizationErasure of cryptographic material in an HSM or TPM
CheckConfirm that the secret no longer exists anywhere

Zeroization is the overwriting of cryptographic material inside a hardware module (HSM, TPM). Since the key is never exportable there, this command is the only way to make it disappear.

What to clean up

The list covers the places where a secret gets copied without anyone having decided it. The most frequent oversight remains the CI build cache, which outlives pipelines and is restored on the next job; then come image layers and Git history.

  • Vault: destroy obsolete versions (kv destroy, not just kv delete)
  • Backups: apply retention policies
  • CI/CD: variables, build logs, artifact caches
  • Container images: layers containing the secret (rebuild, registry purge)
  • Temporary environments: stopped containers, VMs, snapshots
  • Git history: if the secret was committed (git filter-repo, after revocation)
  • Crash reports and memory dumps: they often contain values in clear

The kv destroy trap: measured

With the KV version 2 engine, vault kv delete only performs a soft deletion: the version is hidden and vault kv undelete restores it. Only vault kv destroy really erases the data. But the command takes a path without the data/ segment, and that is where tutorials go wrong.

Terminal window
# ❌ Common form: the command succeeds... on another path
$ vault kv destroy -versions=1,2,3 secret/data/production/db
Success! Data written to: secret/destroy/data/production/db
$ vault kv get -version=1 -field=password secret/production/db
v1 # version 1 is still readable
# Correct form: logical path, without data/
$ vault kv destroy -versions=1,2 secret/production/db
Success! Data written to: secret/destroy/production/db
$ vault kv metadata get secret/production/db
...
destroyed true # versions 1 and 2
# Delete the secret, all versions and metadata included
$ vault kv metadata delete secret/production/db
$ vault kv get secret/production/db
No value found at secret/data/production/db

Measured identically on Vault 2.1.1 and OpenBao 2.7.0: the form with secret/data/... answers Success! and destroys nothing, just like vault kv metadata delete secret/data/.... The only reliable proof is the check that follows: reread the version, see destroyed true. The -mount=secret production/db form removes any ambiguity.

Automating the full cycle

The goal is a cycle where humans only step in for decisions: initial classification, emergency revocation, choice of policy. Everything else, issuance, renewal, reloading and logging, runs without intervention.

Flow of an automated cycle

The six phases below describe what happens from service startup to emergency revocation. The fourth is the one that makes most implementations fail, because it depends on the application's code and not on the infrastructure.

  1. Initial authentication: the service proves its identity through a strong mechanism (Kubernetes ServiceAccount, cloud identity, OIDC token), with no shared secret at bootstrap.
  2. Issuance: the vault checks the identity, applies the policies and issues a short-TTL secret.
  3. Renewal: an agent renews the lease before expiry, the application carries on without interruption.
  4. Application reload: when the secret changes, the application must take the new value into account.
  5. Logging: each access goes to the SIEM with active detection rules.
  6. Emergency revocation: revocation in the vault, notification, check and documentation.

Reloading can be done in four ways, each with its own cost. A progressive restart is the simplest; rereading on each request is the most responsive, but requires code designed for it.

MechanismUse casePoint of attention
RestartApplications without hot reloadProgressive update to avoid downtime
SIGHUP signalnginx, HAProxyDepends on application support
Kubernetes rolling updateContainersA few seconds of switchover
Reread on each requestApplications designed for itCode complexity and cache duration

What to tool up

Each phase of the cycle calls for a dedicated component: the table gives the most common building blocks for a Kubernetes or cloud deployment. No row is optional, and the reload row depends on the application's code.

PhaseTool or mechanism
AuthenticationKubernetes ServiceAccount, OIDC, AppRole
Issuance and storageOpenBao, Vault, AWS Secrets Manager
Distribution in KubernetesExternal Secrets Operator, Vault Agent Injector
RenewalVault Agent, dedicated sidecar container
Application reloadRolling update, SIGHUP, SDK
AuditAudit device, to a SIEM
RevocationVault API and documented runbook

Key points

  • First of all: owner, consumers, criticality and emergency procedure, in a register with no secret value.
  • Generation: cryptographic generator (openssl rand, secrets in Python), never random.
  • Storage and distribution: a vault that traces and revokes, injection at startup; ESO 2.11 only accepts external-secrets.io/v1.
  • Rotation: planned with a dual-active period, event-driven, or native through a lease; measured, each vault read database/creds/app creates a distinct one-hour user.
  • Revocation: vault lease revoke -prefix removes all the users of a role; a confirmed compromise puts revocation before deployment.
  • Audit: values are HMAC-SHA256, correlatable through sys/audit-hash without being revealed.
  • Destruction: kv destroy on secret/data/... answers Success! without destroying anything; always check destroyed true.
  • The evidence expected by SOCLE-SEC-ROT-1 is a rotation policy by criticality, with a TTL defined per secret.

Knowledge check

Check that you have the essentials of this lesson. The questions only cover what has just been explained here.

Knowledge check

Check what you have learned with this interactive quiz

6 questions
6 min
70% to pass

How it works

  • The timer starts when you click Start
  • Multiple choice, true/false and short answer questions
  • You can move between questions
  • Detailed results are shown at the end

Starts the quiz and the timer

Is this project useful to you?

The guides, courses, quizzes and labs stay free. If you use them regularly, you can contribute to their upkeep and development.

Become a supporting member (new tab) One-time support (new tab) Learn more

Follow the project on LinkedIn