← Policy catalog
</> ValidatingAdmissionPolicy · Apache-2.0

Grants Access to Secrets

role-secrets-access

severityCritical resourceRoles productKubernetes bundles1

Reading Secrets exposes the credentials they hold in the namespace, including service account tokens, TLS private keys and registry passwords, and the write verbs let those values be replaced with attacker-controlled ones.

Rejects unless

!has(object.rules) || object.rules.all(r,
  !(r.apiGroups.exists(ag, ag == "") &&
    r.resources.exists(res, res == "secrets") &&
    r.verbs.exists(v, variables.secretVerbs.exists(sv, sv == v))
  )
)

Roles must not grant read or write access to Secrets without tight scoping.

Variables

secretVerbs

["get","list","watch","create","update","patch","delete"]

Remediation

Remove get, list, watch, create, update, patch and delete from every rule covering secrets in the core API group, and deliver credentials through a projected volume or an external secret store instead. Fields: rules[*].apiGroups, rules[*].resources, rules[*].verbs.

Applies to

  • roles · rbac.authorization.k8s.io/v1 · CREATE, UPDATE

Manifest

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: role-secrets-access
  annotations:
    kubeapt.io/uuid: "f2cdf998-1fbc-40e6-9602-1a721388f40f"
    security.kubeapt.io/displayName: "Grants Access to Secrets"
    security.kubeapt.io/description: "Reading Secrets exposes the credentials they hold in the namespace, including service account tokens, TLS private keys and registry passwords, and the write verbs let those values be replaced with attacker-controlled ones."
    security.kubeapt.io/resource: "Roles"
    security.kubeapt.io/severity: "Critical"
    security.kubeapt.io/remediation: "Remove get, list, watch, create, update, patch and delete from every rule covering secrets in the core API group, and deliver credentials through a projected volume or an external secret store instead. Fields: rules[*].apiGroups, rules[*].resources, rules[*].verbs."
    security.kubeapt.io/product: "Kubernetes"
spec:
  failurePolicy: Fail
  matchConstraints:
    resourceRules:
    - apiGroups:
      - rbac.authorization.k8s.io
      apiVersions:
      - v1
      operations:
      - CREATE
      - UPDATE
      resources:
      - roles
  variables:
  - name: secretVerbs
    expression: |
      ["get","list","watch","create","update","patch","delete"]
  validations:
  - expression: |
      !has(object.rules) || object.rules.all(r,
        !(r.apiGroups.exists(ag, ag == "") &&
          r.resources.exists(res, res == "secrets") &&
          r.verbs.exists(v, variables.secretVerbs.exists(sv, sv == v))
        )
      )
    message: |
      Roles must not grant read or write access to Secrets without tight scoping.

Save it as role-secrets-access.yaml — the commands below assume that name.

Validate with kubeapt

Check a workload against this one policy, before anything is installed on a cluster.

$ kubeapt validate -p ./role-secrets-access.yaml -r ./workload.yaml

Or without the file, from the published policy set — -r takes a directory too:

$ kubeapt policies download && kubeapt validate --policy-name role-secrets-access -r ./manifests

Or against every namespace in the cluster your kubeconfig points at:

$ kubeapt validate --policy-name role-secrets-access -A