CNPE — Cloud Native Platform Engineer
The Conditions Under Which an Audit Trail Holds
One-line summary
An audit trail needs an identifier for what ran, trustworthy production evidence, and per-point-in-time deployment records. Storing more secret values does not make the evidence better.
Why a single tag is not enough
A tag can move to a different image, but a digest is an identifier of the content. So it is good to pin the desired deployment by digest and connect it to the target of scanning and signing. The digest itself does not prove safety, the author, or the source commit. Kubernetes images
Even if you deployed by tag, it is not that you cannot investigate the current image at all. status.containerStatuses[].imageID holds the image information identified by the runtime, and it can differ from the image you declared. Check the format and the meaning of the digest according to the runtime and the image type. A current query does not restore the past state of a Pod that has already been deleted, so also preserve the identifier and the time at the moment of deployment. Kubernetes ContainerStatus source
How it works
Connect four kinds of evidence
| Evidence | What to check | What it alone does not prove |
|---|---|---|
| Image digest | The identity of the verified and deployed target | Absence of vulnerabilities, the source commit |
| Image signature | A signature by a signer that fits the trust policy | The fact that the signer is actually the builder |
| SBOM | The component list and its link to the target | The completeness of the list and the trustworthiness of its author |
| Build provenance | The target, the builder, the inputs, and the build process | The honesty of an untrusted builder |
An image signature and an SBOM signature are separate. Even if the image signature is valid, an arbitrary SBOM file placed next to it is not thereby authenticated. For example, for an attestation that contains an SBOM, you check not only the signature verification but also that the digest of the subject equals the target and that it is the expected predicateType. Build provenance also needs the trusted builder and the expected source and build conditions verified. SLSA artifact verification
Sigstore's cosign verify and cosign verify-attestation verify different targets. In keyless verification, you concretely restrict the allowed certificate identity and the OIDC issuer. A signature being cryptographically correct and our release principal having signed it are different judgments. Sigstore verification guide
In a scan report, bind together the target digest, the scanner and vulnerability database versions, the scan time, and the exceptions. The success of generating a report alone does not make a deployment gate. Distinguish a criteria violation from a scanner error and confirm that both stop the deployment appropriately. When a new vulnerability is discovered, the same image must be re-evaluated too, so do not use a pass at build time as a permanent safety judgment.
Do not copy the Secret body into the audit log
Metadata records the user, time, resource, and action, but does not record the request and response bodies. Request includes the request body, and RequestResponse includes both bodies. If you record Secrets at a detailed level, sensitive content can be copied into the log. Kubernetes audit levels
A Secret's base64 is not encryption, so an encoded value is also an exposure. Even if you narrowed Secret read permissions, if the body is visible to log readers, it leaks through another path. You must also avoid putting secrets directly in a ConfigMap or a Pod spec. Secret management principles
The following is a starting-point example that does not keep the body. It is not a workload to kubectl apply but the API server's audit policy file. Actually enabling it needs the policy file and the log and webhook storage path settings, and for a managed service you must check the provider's settings. Do not replace production settings with it as is.
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
resources:
- group: ""
resources: ["secrets", "configmaps"]
- level: Metadata
At first you record every request at Metadata. Even if you add detailed rules later, do not put a broad body-recording rule ahead of the rules that protect sensitive resources. The first matching rule applies, so a later protection rule cannot override an earlier decision. Also review separately the sensitive data of subresources and other API groups. The audit policy API contract
Metadata is also not a public log. Do not put sensitive information in the request URI or audit annotations, and manage log viewing and export permissions, the retention period, integrity, and alerts for collection failures. Omitting the body does not guarantee automatic removal of all secrets from the whole log.
What it looks like in the field
An example scenario: an investigator does not need the secret value but needs to know who read the production Secret. In an isolated environment you own, you make create, read, and delete requests with synthetic markers rather than real credentials, and check that the user, action, target, and response result of those requests were recorded. At the same time, you also check that there is no requestObject or responseObject and no original or encoded value of the synthetic marker. If the record is empty, only the second condition passes, so you must first check that the request evidence exists.
That the collection path is healthy is also a separate condition. If it is in the API server's local file but not in the central store, you cannot investigate an incident with central search. Searching all the way for a known test request is more direct evidence than the green light on the collector's screen.
What to check in the next quiz
You judge omissions in policy scope, the difference between NetworkPolicy and mTLS, the Secret audit level, digest and provenance, and the SBOM link.
The scope we actually checked
On 2026-09-11, in an isolated k3s v1.36.4+k3s1 probe, we ran creation, reading, and deletion of a synthetic Secret and a read by a non-allowed user. With Metadata, only the evidence of the four requests remained; when a detailed rule was placed first, the synthetic body was exposed; and after the fix, the body disappeared again. When Secret recording was turned off with None, a separate /version comparison request was recorded but there was no Secret evidence, so the verifier failed.
We left the reproduction and counterexample checks in the repository's scripts/probe_cnpe_audit.py and tests/test_cnpe_audit_probe.py. This check is limited to a single node's local audit file. It does not mean we verified or changed central collection, log integrity, the whole sensitive-resource policy, or a production cluster's audit settings. Next you perform an 8-step lab on a personal VM that directly reproduces secret exposure, Metadata recovery, and the missing evidence under None. You check both the excerpt taken at collection time and a fresh query of the current API, and this material does not guarantee the integrity of a central audit store.