Skip to main content

Kubernetes

The Kubernetes collector reads the certificates cert-manager manages in your clusters, so workload certificates — the ones issued and renewed automatically, without anyone requesting them — count toward your post-quantum readiness reporting.

It is read-only, and it never reads Kubernetes Secrets, so the private keys your certificates reference are out of reach. That is a structural property of the connector, not a setting you need to get right.

What it collects​

ResourceWhat Mesh takes from it
Certificate (cert-manager)The certificate inventory — key algorithm, key size, validity and renewal settings
Issuer / ClusterIssuer (cert-manager)What signed each certificate. Resolved by name for every certificate; listing them in full is optional
PodContainer image references, so a certificate can be tied to the workload using it
ReplicaSet (apps)One owner hop, Pod → ReplicaSet → Deployment, so an image is attributed to a stable workload name instead of a pod hash that changes on every rollout
Namespace (kube-system)Cluster identity, so two clusters are not confused for one another. Optional — if it is not granted, collection continues
It reads Pods, not only certificates

Beyond certificates and issuers, the collector reads Pod container image references and resolves the workload that owns them. Worth knowing before you approve a cluster-wide credential — it reads what is running, not only what is issued.

Certificates removed from a cluster are retired in Mesh after the next complete collection.

Before you start​

  • cert-manager installed in the cluster. If its custom resources are not registered, Mesh reports that it found none, rather than failing.
  • An API server URL reachable from Mesh, over HTTPS.
  • A read-only credential — a service account token, or a client certificate and key. Creating one is covered below.

Decide your scope first​

One decision shapes everything else: which namespaces you want inventoried. It determines the Kubernetes permission you create, so it is worth settling before you start.

You wantLeave NamespacesYou grant
The whole clusterEmptyA ClusterRole and ClusterRoleBinding
Only certain namespacesA comma-separated listA Role and RoleBinding in each one
Empty means cluster-wide, not "whatever I can see"

Leaving Namespaces empty makes one cluster-wide request per resource kind. The Kubernetes API server does not quietly narrow that to the namespaces your credential happens to cover — it refuses the whole request with 403, and the collection fails.

So if you grant per-namespace Roles, you must also list those namespaces in the Namespaces field. Granting narrowly and leaving the field empty is the most common way this connector fails its first run.

Create the read-only access​

First create the service account Mesh will authenticate as. This is the same for either scope.

apiVersion: v1
kind: ServiceAccount
metadata:
name: axiad-mesh-crypto
namespace: kube-system

Then apply one of the following, matching the scope you chose above.

Whole cluster​

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: axiad-mesh-crypto-reader
rules:
- apiGroups: ["cert-manager.io"]
resources: ["certificates", "issuers", "clusterissuers"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
- apiGroups: ["apps"]
resources: ["replicasets"]
verbs: ["get"]
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["get"]
- apiGroups: ["apiextensions.k8s.io"]
resources: ["customresourcedefinitions"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: axiad-mesh-crypto-reader
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: axiad-mesh-crypto-reader
subjects:
- kind: ServiceAccount
name: axiad-mesh-crypto
namespace: kube-system

Selected namespaces​

Apply a Role and RoleBinding in each namespace you want inventoried, and list those same namespaces in the Namespaces field.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: axiad-mesh-crypto-reader
namespace: my-namespace
rules:
- apiGroups: ["cert-manager.io"]
resources: ["certificates", "issuers"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
- apiGroups: ["apps"]
resources: ["replicasets"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: axiad-mesh-crypto-reader
namespace: my-namespace
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: axiad-mesh-crypto-reader
subjects:
- kind: ServiceAccount
name: axiad-mesh-crypto
namespace: kube-system

ClusterIssuer is cluster-scoped, so it cannot be granted by a namespaced Role. If you are scoping to namespaces, leave Enable Cluster Issuers off.

Get a token for the service account​

kubectl -n kube-system create token axiad-mesh-crypto --duration=8760h
--duration is a request, not a guarantee

The API server may issue a token that expires sooner than you asked for — many clusters cap bound-token lifetimes well below a year. Do not work out the renewal date from the flag you typed.

Read the real expiry from the token's own exp claim, and set your reminder from that. Decode it locally — the token is a live credential, so do not paste it into an online decoder:

TOKEN=$(kubectl -n kube-system create token axiad-mesh-crypto --duration=8760h)
echo "$TOKEN" | python3 -c '
import base64, datetime, json, sys
payload = sys.stdin.read().strip().split(".")[1]
payload += "=" * (-len(payload) % 4)
exp = json.loads(base64.urlsafe_b64decode(payload))["exp"]
print(datetime.datetime.fromtimestamp(exp, datetime.timezone.utc))'

An expired token stops collection, and the connector cannot warn you in advance — so replace it before that date.

Add the connector in Mesh​

  1. Go to Settings › Connectors, then select Add connector.
  2. Under Crypto collectors, choose Kubernetes.
  3. Fill in the fields below.
  4. Select Test configuration, then Add & connect.

Connection fields​

FieldRequiredWhat to enter
API Server URLYesThe cluster's API server, for example https://host:6443. Must be https:// — the credential travels with every request, so plain HTTP is refused
Bearer TokenOne ofA service account token. Use either this or the client certificate and key — not both
Client Certificate (PEM)One ofSign in with a client certificate instead of a token. Supply the key below as well
Client Key (PEM)With certThe private key for that client certificate
CA Certificate (PEM)NoThe cluster's CA, so Mesh can verify it. Leave empty if the API server presents a certificate that is already publicly trusted
Skip TLS VerificationNoDefault off. Lab use only — never enable it against a production cluster
NamespacesNoComma-separated. Empty means cluster-wide — see Decide your scope first
Enable IssuersNoDefault off. Also list namespaced Issuer resources
Enable Cluster IssuersNoDefault off. Also list cluster-scoped ClusterIssuer resources
cert-manager API GroupNoDefault cert-manager.io. Change only for a forked or pre-GA cert-manager
cert-manager API VersionNoDefault v1. Change only for a pre-GA cert-manager
Collection frequencyNoHow often Mesh re-reads the cluster, as a duration such as 1h

Paste credentials as text, not file paths — Mesh has no access to your cluster's filesystem. The token and client key are write-only: once saved, they are never shown again.

Issuers are resolved either way

Enable Issuers and Enable Cluster Issuers control whether Mesh lists issuers in full. The issuer behind each certificate is resolved by name regardless, so leaving both off does not cost you the issuer of a certificate you collected.

Check the first collection​

After Add & connect, open Data source syncs and find the connector's first run. A healthy first run reports success for each part it was granted.

Then look for the certificates themselves in your crypto asset inventory, and in the PQC Readiness Index widget on your dashboard. A cluster with cert-manager installed but no certificates issued yet reports a successful run that collected nothing — that is the expected result, not a failure.

Troubleshooting​

What you seeWhat it means
Run fails with a permission error, and you granted per-namespace RolesNamespaces was left empty, so Mesh made a cluster-wide request. List your namespaces in that field, or grant a ClusterRole
One namespace missing, the rest fineThe credential has no Role in that namespace. Mesh records it as inaccessible and continues with the others
Certificates collected, but not attributed to a workloadget on replicasets was not granted. Images are still collected; only the owning Deployment is unresolved
"No certificates found", but you know they existcert-manager's custom resources are not registered in this cluster, or they are registered under a non-default API group or version. Check cert-manager API Group and API Version
Collection worked, then stoppedThe token expired. Issue a new one and update the connector
TLS or certificate-verification errorsThe API server presents a certificate Mesh does not trust. Paste the cluster CA into CA Certificate (PEM). Do not reach for Skip TLS Verification against production

If a run still fails after these, see Troubleshooting & support.