writing-skills
writing-skills
Use when creating new skills, editing existing skills, or verifying skills work before deployment
kyverno-secret-validationValidates Kubernetes Secrets meet security requirements by checking secret types, enforcing labeling standards, and preventing legacy service-account-token usage.
Independent GitHub snapshot · Automated classification · Original documentation governs
name: kyverno-secret-validation description: Validates Kubernetes Secrets meet security requirements by checking secret types, enforcing labeling standards, and preventing legacy service-account-token usage. license: MIT compatibility: opencode archetypes:
Validates Kubernetes Secrets to ensure they meet security requirements: rejecting the deprecated kubernetes.io/service-account-token secret type, enforcing required labels (e.g., managed-by: kyverno), and limiting secret data size to prevent abuse or accidental exposure.
kubernetes.io/service-account-token secret typemanaged-by or app.kubernetes.io/managed-by on all Secretskube-system namespace secrets from validation rulesPolicyReport via kubectl get policyreports -AUse this skill when:
kubernetes.io/service-account-token secrets which expose service account credentialsAvoid this skill for:
kyverno-resource-quota-validation instead)kyverno-network-policy-generation instead)kube-system namespace resources — use the exclude block insteadIdentify secret type requirements — Determine which secret types are permitted (e.g., Opaque, kubernetes.io/tls, kubernetes.io/dockerconfigjson) and which must be explicitly denied (e.g., kubernetes.io/service-account-token). Checkpoint: Document the approved secret type list and the deny list before writing the policy.
Create deny rule for service-account-token — Write a ClusterPolicy validate rule that rejects any Secret with type: kubernetes.io/service-account-token. Use a deny message referencing the deprecation. Checkpoint: Verify the rule matches only the Secret kind and checks spec.type (actually type at the root level for Secrets).
Create label enforcement rule — Write a second rule that requires all Secrets to have a managed-by label (value: kyverno). Use a validate pattern that checks metadata.labels.managed-by. Checkpoint: Confirm the label pattern uses "?*" to accept any non-empty value.
Create data size validation rule — Write a third rule that limits the total size of secret data to a maximum (e.g., 1 MiB). Use validate with anyPattern to check that each secret value's length is within bounds. Checkpoint: Test with a Secret that has large base64-encoded values to confirm rejection.
Deploy and verify PolicyReport — Apply the ClusterPolicy, create test Secrets with violations, and verify results appear in PolicyReport. Checkpoint: Run kubectl get policyreports -A -o wide to see pass/fail breakdown.
This rule blocks creation of kubernetes.io/service-account-token secrets. This type is deprecated since Kubernetes 1.21 and should be replaced with projected volumes (serviceAccountToken projection). Using deny with a match on the secret type field ensures no new token-type secrets can be created.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: deny-service-account-token-secrets
annotations:
policies.kyverno.io/title: Deny Service Account Token Secrets
policies.kyverno.io/category: Secrets Management
policies.kyverno.io/severity: high
policies.kyverno.io/description: >-
The kubernetes.io/service-account-token secret type is deprecated as of
Kubernetes 1.21. This policy denies creation of secrets with this type
and requires use of projected service account tokens instead.
policies.kyverno.io/minversion: 1.12.0
spec:
validationFailureAction: Enforce
background: true
rules:
- name: deny-service-account-token
match:
any:
- resources:
kinds:
- Secret
exclude:
any:
- namespaces:
- kube-system
- kyverno
validate:
message: >-
The kubernetes.io/service-account-token secret type is deprecated.
Use projected service account tokens (spec.serviceAccountToken)
instead of dedicated token secrets.
pattern:
type: "Opaque"
Pattern notes:
type: "Opaque" pattern only matches Secrets of type Opaquekubernetes.io/service-account-token) fails validation and is deniedexclude block ensures kube-system secrets are not affectedAll Secrets must carry a managed-by label to indicate the tool responsible for managing them. This rule enforces managed-by: kyverno for secrets created directly, or allows any value for secrets managed by other tools.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-secret-labels
annotations:
policies.kyverno.io/title: Require Secret Labels
policies.kyverno.io/category: Secrets Management
policies.kyverno.io/severity: medium
policies.kyverno.io/description: >-
All Secrets must have the managed-by label to indicate which tool or
process manages them. This supports asset tracking, ownership queries,
and policy management.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: require-managed-by-label
match:
any:
- resources:
kinds:
- Secret
exclude:
any:
- namespaces:
- kube-system
- kyverno
validate:
message: "Secrets must have the managed-by label."
pattern:
metadata:
labels:
managed-by: "?*"
BAD vs GOOD example:
# ❌ BAD — Secret without managed-by label
apiVersion: v1
kind: Secret
metadata:
name: app-credentials
namespace: production
labels:
app: myapp
environment: production
type: Opaque
data:
username: YWRtaW4=
password: c2VjcmV0MTIz
# ❌ Missing managed-by label — policy rejects this
# ✅ GOOD — Secret with managed-by label
apiVersion: v1
kind: Secret
metadata:
name: app-credentials
namespace: production
labels:
app: myapp
environment: production
managed-by: kyverno
app.kubernetes.io/managed-by: kyverno
type: Opaque
data:
username: YWRtaW4=
password: c2VjcmV0MTIz
# ✅ GOOD — Secret managed by a different tool
apiVersion: v1
kind: Secret
metadata:
name: tls-cert
namespace: production
labels:
app: ingress
managed-by: cert-manager
type: kubernetes.io/tls
data:
tls.crt: LS0tLS1CRUdJTi...
tls.key: LS0tLS1CRUdJTi...
This rule limits the total size of a Secret's data to prevent injection of oversized payloads. It checks that each base64-encoded value in the data map stays under a defined maximum length (equivalent to ~1 MiB when decoded).
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: limit-secret-size
annotations:
policies.kyverno.io/title: Limit Secret Size
policies.kyverno.io/category: Secrets Management
policies.kyverno.io/severity: medium
policies.kyverno.io/description: >-
Limit the size of Secret data to prevent oversized payloads. Each
base64-encoded value in the Secret data must not exceed 1048576
bytes (1 MiB decoded).
spec:
validationFailureAction: Enforce
background: true
rules:
- name: validate-secret-data-size
match:
any:
- resources:
kinds:
- Secret
exclude:
any:
- namespaces:
- kube-system
- kyverno
validate:
message: "Secret data values must not exceed 1 MiB each."
pattern:
data:
(=*) : "<1048576"
Pattern notes:
(<1048576) operator in Kyverno performs a numeric comparison on the base64-decoded length"(=*)" matches any key name in the data map (e.g., username, password, ca.crt)stringData are also checked because Kyverno normalizes both fieldsCombine all secret validation rules into a single ClusterPolicy for streamlined management.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: secret-security-policy
annotations:
policies.kyverno.io/title: Secret Security Policy
policies.kyverno.io/category: Secrets Management
policies.kyverno.io/severity: high
policies.kyverno.io/description: >-
Comprehensive secret validation: deny service-account-token type,
enforce managed-by label, and limit data size.
policies.kyverno.io/minversion: 1.12.0
spec:
validationFailureAction: Enforce
background: true
rules:
- name: deny-service-account-token
match:
any:
- resources:
kinds:
- Secret
exclude:
any:
- namespaces:
- kube-system
- kyverno
validate:
message: "kubernetes.io/service-account-token type is deprecated."
pattern:
type: "Opaque"
- name: require-managed-by-label
match:
any:
- resources:
kinds:
- Secret
exclude:
any:
- namespaces:
- kube-system
- kyverno
validate:
message: "Secrets must have the managed-by label."
pattern:
metadata:
labels:
managed-by: "?*"
- name: limit-secret-data-size
match:
any:
- resources:
kinds:
- Secret
exclude:
any:
- namespaces:
- kube-system
- kyverno
validate:
message: "Secret data values must not exceed 1 MiB each."
pattern:
data:
(=*) : "<1048576"
kubernetes.io/service-account-token type secrets using a type: "Opaque" pattern in the validate rulemanaged-by label on all Secrets using the "?*" non-empty match pattern(<1048576) for a 1 MiB ceiling per valuekube-system namespace from all secret validation rules to avoid disrupting Kubernetes internalstype at the top level (root field), not under metadata or spec — Secrets are a CoreV1 resource with type as a top-level fieldClusterPolicy for cluster-wide enforcement; do not fragment into namespace-scoped Policy resourceskube-system namespace — system secrets (e.g., bootstrap-token-*, default-token-*) are managed by the control planeExternalSecret from external-secrets.io) — those are managed by their own controllers and should not be subject to CoreV1 Secret policies"*" (empty-match) pattern for labels — it would accept an empty string; always use "?*" to enforce non-empty valuesexclude blocks — without exclusions, even kube-system secrets like extension-apiserver-authentication would be rejected| Skill | Purpose |
|---|---|
kyverno-resource-quota-validation | Validate pod resource constraints alongside secret security policies |
kyverno-image-registry-validation | Validate container image registries as part of a comprehensive security posture |
Authoritative documentation links for Kyverno secret validation and PolicyReport management.