Kubernetes Secrets and RBAC Hardening
Kubernetes Secrets were accessible to any service account in the namespace because no RBAC restrictions were in place. I retrieved the exposed credentials, created scoped Roles and RoleBindings, and validated that only the authorised service account could read the secret.
Status: HARDENED · VERIFIED
TOOLS
Objective
I set out to assess whether Kubernetes Secrets were protected by RBAC, restrict access to only authorised service accounts, and validate that the controls worked.
Scenario
A Minikube cluster ran an Nginx application with a Kubernetes Secret called terminal-creds containing a username and password. No RBAC restrictions were in place, so any service account in the namespace could query and decode the secret. I wanted to lock it down to a single authorised service account.
What I found
Secret: terminal-creds
Namespace: default
Access restriction: None (any service account)
Encoding: base64 only (not encrypted)
Credentials: <REDACTED>Secret accessible without RBAC restrictions
The terminal-creds secret could be retrieved by any identity in the default namespace. The credentials were base64-encoded but not encrypted and could be decoded immediately.
Without RBAC, any pod or service account in the namespace could read the secret and obtain the credentials.
What I did
- Enumerated the cluster
I started the Minikube cluster, listed running pods, and deployed the Nginx application.
- Retrieved the secret
I queried
terminal-credsand decoded the username and password, confirming unrestricted access. - Created service accounts
I set up
terminal-user(should be denied) andterminal-admin(should be allowed) service accounts. - Configured RBAC
I created a Role granting
getaccess to theterminal-credssecret and a RoleBinding that bound it only toterminal-admin. - Validated access controls
I tested both service accounts with
kubectl auth can-i.
EVIDENCE
# RoleBinding restricting secret access to terminal-admin
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: terminal-creds-binding
namespace: default
subjects:
- kind: ServiceAccount
name: terminal-admin
namespace: default
roleRef:
kind: Role
name: terminal-creds-reader
apiGroup: rbac.authorization.k8s.ioValidation
After applying the RBAC configuration, access was correctly restricted:
terminal-user can get secret/terminal-creds: no
terminal-admin can get secret/terminal-creds: yesThe terminal-user service account was denied access, while terminal-admin was authorised, confirming the RBAC controls were enforced.
Before and after
| CONTROL | BEFORE | AFTER |
|---|---|---|
| Secret access | Any service account | Only terminal-admin |
| RBAC Role | Not configured | terminal-creds-reader |
| RoleBinding | Not configured | Bound to terminal-admin only |
terminal-user access | Allowed | Denied |
terminal-admin access | Allowed | Allowed (authorised) |
What I recommend
- 01Apply RBAC to every Kubernetes Secret so that only the service accounts that need them can read them.
- 02Avoid relying on namespace isolation alone; use Roles and RoleBindings for fine-grained access.
- 03Use encrypted secret storage (such as sealed secrets or an external secrets manager) rather than base64-encoded Kubernetes Secrets.
- 04Audit RBAC configurations regularly and remove any overly broad bindings.
- 05Use
kubectl auth can-ito validate access controls after every change.
“Kubernetes Secrets alone do not prevent unauthorised access. RBAC must be used to enforce which identities are allowed to retrieve sensitive resources.”
SKILLS IT PROVES
- Kubernetes Security
- RBAC
- Access Control
- Secrets Management
- Identity and Access Management
- DevSecOps
- Container Security
- Security Hardening
- Least Privilege
- Kubernetes Administration
- Access Validation