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 destroytrap, which answersSuccess!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.
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.
| Class | Examples | Criticality | Rotation |
|---|---|---|---|
| Root secret | Database administrator account, master key | Very high | After each use |
| Service secret | Service-to-service token, pipeline credential | High | Automated, frequent |
| Application secret | Application database password, external API key | Standard | Planned |
| Temporary secret | Session token, one-time code | Low | Native 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-platform1. 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 secret | Main requirement | Implementation |
|---|---|---|
| Human password | Length, memorability | 16 characters or more, password manager |
| Machine token or secret | Pure entropy | Cryptographic generator, 256 bits or more |
| Provider API key | Quality of the source | Issued 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.
# 32 random bytes (256 bits), base64-encodedopenssl rand -base64 32
# 32 bytes in hexadecimal, for an AES-256 encryption keyopenssl rand -hex 32# API token: Python's secrets module, designed for cryptographyimport secretstoken = secrets.token_urlsafe(32) # 32 bytes of randomnessCommon 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 generatorimport randompassword = ''.join(random.choices('abcdefgh', k=8))
# ❌ Secret derived from predictable datapassword = hashlib.md5(username.encode()).hexdigest()
# ❌ Reuse of an existing secretnew_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.
| Practice | Implementation |
|---|---|
| Encryption at rest | AES-256-GCM or equivalent, provided by the vault |
| Access control | Strict policies, least privilege |
| Centralisation | One vault, no copies |
| Versioning | Version 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.
| Solution | Use case | What it brings |
|---|---|---|
| OpenBao / HashiCorp Vault | Central vault, dynamic secrets | Policies, audit, revocable leases |
| AWS Secrets Manager | AWS ecosystem | Managed rotation, CloudTrail log |
| Azure Key Vault | Azure ecosystem | Entra ID access control |
| GCP Secret Manager | GCP ecosystem | IAM access control |
| Infisical | Open source, teams | Interface, synchronisation |
| SOPS | Encrypted files in Git (GitOps) | Encryption, no audit of reads |
| Kubernetes Secrets | Distribution within the cluster | Not 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.
| Practice | Implementation |
|---|---|
| Injection at startup | Never in the code or in a static configuration |
| Encrypted channel | TLS for retrieval |
| Authentication | The application proves its identity |
| Minimal duration | The 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.
# Vault Agent (or bao agent for OpenBao) with its configuration filevault agent -config=agent.hcl2. 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/v1kind: ExternalSecretmetadata: name: db-credentials namespace: paymentspec: refreshInterval: 1h secretStoreRef: kind: SecretStore name: vault-backend target: name: db-credentials data: - secretKey: password remoteRef: key: production/db property: passwordThe 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.
# Infisical injects the secrets then launches the applicationinfisical run -- npm startCommon 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.
# ❌ Secret exported to a .env filecp 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 reportsexport 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 value4. 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.
| Practice | Implementation |
|---|---|
| Minimal time in memory | Load just before use, limit copies |
| No logging | Never print the secret |
| Single connection | Open the connection once, reread the secret on reconnection |
| Error handling | Do 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 connectiondef 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 connIn 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 attributeclass Database: password = "SuperSecret123" # accessible via Database.password
# ❌ Secret in the logslogger.debug(f"Connecting with password: {password}")
# ❌ Secret in the exceptionraise 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.
| Practice | Implementation |
|---|---|
| Automation | Rotation without human intervention |
| No interruption | A period when both versions work |
| Suitable frequency | The more critical the secret, the more frequent |
| Tested regularly | Rotation 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 activeT1: generate secret BT2: A and B active together (dual-active)T3: migrate all consumers to BT4: deactivate A, then check that it failsThe 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.
$ vault read database/creds/appKey Value--- -----lease_id database/creds/app/aMTXQzqtuyKCe9yO7pHw624alease_duration 1hlease_renewable truepassword vL-0OqdMgh3CGQ4T36k6username v-token-app-NkdSHbitYpic3j25kQ0Z-1790862956
# A second read created another user (lease OTOY...); we renew it$ vault lease renew database/creds/app/OTOYt9CsPoFYt3CvqCZ7QEQnlease_duration 1hThe 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 secret | Indicative frequency | Comment |
|---|---|---|
| Root credentials | After each use | Never leave them lying around |
| Production secrets | 30 to 90 days | Adapt to criticality |
| API tokens | 30 to 90 days | More exposed, shorter |
| Certificates | Before expiry | Automate, for instance with cert-manager |
| Dynamic secrets | On each request | Short TTL, no rotation |
| Human passwords | On suspicion of compromise | NIST 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 secret6. 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.
| Practice | Implementation |
|---|---|
| Immediate revocation | Ability to invalidate within minutes |
| Complete revocation | All copies, all systems |
| Check | Confirm that the old secret no longer works |
| Documented procedure | Ready-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.
$ vault lease revoke database/creds/app/OTOYt9CsPoFYt3CvqCZ7QEQnAll 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/appAll 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.
- Detect the end of life or the need for replacement
- Assess the impact and the list of consumers
- Generate a new secret
- Deploy the new secret to the applications
- Revoke the old secret at the provider and in the vault
- Check that the old secret no longer works
- 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.
| Question | Why 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 slow7. 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.
| Practice | Implementation |
|---|---|
| Complete logs | Who, what, when, from where |
| Centralisation | SIEM or log aggregator |
| Real-time alerts | Suspicious access, abnormal volumes, repeated failures |
| Log protection | Immutability, separate storage |
| Retention | Compliance 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.
| Event | Information |
|---|---|
| Creation | Who created it, when, what type |
| Read | Who read it, when, from which address |
| Modification | Who modified it, when |
| Rotation | Who triggered it, automatic or manual |
| Revocation | Who revoked it, why |
| Access failure | Who 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 alert8. 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.
| Practice | Implementation |
|---|---|
| Version purge | Destroy old versions in the vault |
| Cleaning up copies | Temporary files, backups, CI |
| Zeroization | Erasure of cryptographic material in an HSM or TPM |
| Check | Confirm 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 justkv 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.
# ❌ Common form: the command succeeds... on another path$ vault kv destroy -versions=1,2,3 secret/data/production/dbSuccess! Data written to: secret/destroy/data/production/db$ vault kv get -version=1 -field=password secret/production/dbv1 # version 1 is still readable
# Correct form: logical path, without data/$ vault kv destroy -versions=1,2 secret/production/dbSuccess! 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/dbNo value found at secret/data/production/dbMeasured 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.
- Initial authentication: the service proves its identity through a strong mechanism (Kubernetes ServiceAccount, cloud identity, OIDC token), with no shared secret at bootstrap.
- Issuance: the vault checks the identity, applies the policies and issues a short-TTL secret.
- Renewal: an agent renews the lease before expiry, the application carries on without interruption.
- Application reload: when the secret changes, the application must take the new value into account.
- Logging: each access goes to the SIEM with active detection rules.
- 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.
| Mechanism | Use case | Point of attention |
|---|---|---|
| Restart | Applications without hot reload | Progressive update to avoid downtime |
| SIGHUP signal | nginx, HAProxy | Depends on application support |
| Kubernetes rolling update | Containers | A few seconds of switchover |
| Reread on each request | Applications designed for it | Code 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.
| Phase | Tool or mechanism |
|---|---|
| Authentication | Kubernetes ServiceAccount, OIDC, AppRole |
| Issuance and storage | OpenBao, Vault, AWS Secrets Manager |
| Distribution in Kubernetes | External Secrets Operator, Vault Agent Injector |
| Renewal | Vault Agent, dedicated sidecar container |
| Application reload | Rolling update, SIGHUP, SDK |
| Audit | Audit device, to a SIEM |
| Revocation | Vault 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,secretsin Python), neverrandom. - 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/appcreates a distinct one-hour user. - Revocation:
vault lease revoke -prefixremoves all the users of a role; a confirmed compromise puts revocation before deployment. - Audit: values are HMAC-SHA256, correlatable through
sys/audit-hashwithout being revealed. - Destruction:
kv destroyonsecret/data/...answersSuccess!without destroying anything; always checkdestroyed 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
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
Review
(0/0)Score by domain
A domain groups several guides and gets several questions, so its score is more reliable than a per-topic score, which often rests on a single question.
Summary
Strengths
No topic passed at 80% on at least two questions yet.
Weak areas
No topic below the pass mark.
Recommended next
Hints before you try again?
Continue the course: The secret zero problem: who hands out the first secret?
Continue the course: The secret zero problem: who hands out the first secret?
A new full quiz with random questions
Work again only on the questions you missed