Connect Kubernetes Clusters
This guide walks you through connecting a Kubernetes cluster to Onam — any CNCF-conformant distribution: EKS, AKS, GKE, OKE, ACK, IKS, or self-managed. You create a read-only ServiceAccount bound to a get/list/watch ClusterRole, then register the API server endpoint, CA certificate, and token in the Onam console. The connection is agentless and read-only: nothing is installed in the cluster, and Onam never modifies any object.
Time to complete: ~10 minutes per cluster. Kubernetes knowledge required: kubectl, RBAC basics.

How the connection works
Onam talks directly to the Kubernetes API server using a dedicated ServiceAccount whose ClusterRole allows exactly three verbs: get, list, and watch. At scan time, Onam enumerates cluster objects — workloads, RBAC bindings, network policies, secrets metadata, admission configuration — and evaluates them against 718 Kubernetes rules covering 51 resource kinds, plus 103 identity-focused CIEM rules for RBAC analysis.
- Nothing runs in your cluster. No DaemonSet, no operator, no sidecars — Onam is a read-only API client, so there is zero workload overhead.
- RBAC is the enforcement boundary. The ClusterRole you apply has no
create,update,patch, ordeleteverb, and the Kubernetes API server rejects anything beyond it. - Revocation is one command. Delete the ServiceAccount (or its namespace) and access ends instantly.
How the connection stays read-only: the ClusterRole in this guide grants onlyget,list, andwatch— the Kubernetes API server's admission path enforces that on every request, so Onam cannot create, modify, or delete any object even in error. The ServiceAccount token is stored in AWS Secrets Manager, encrypted with KMS, andkubectl delete ns onam-systemsevers access immediately.
Before you begin
kubectlaccess to the cluster with permission to create namespaces, ServiceAccounts, and ClusterRoleBindings (typicallycluster-admin)- A cluster running Kubernetes 1.24 or later
- Network reachability: the API server endpoint must be reachable from Onam — either a public endpoint restricted to Onam's egress IPs (shown on the onboarding screen), or private connectivity on Enterprise plans
- An Onam account with at least the
tenant_adminrole
Step 1 — Create read-only cluster credentials
Apply this manifest. It creates a namespace, a ServiceAccount, a read-only ClusterRole, the binding, and a long-lived token Secret:
# onam-scanner.yaml
apiVersion: v1
kind: Namespace
metadata:
name: onam-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: onam-scanner
namespace: onam-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: onam-scanner-readonly
rules:
- apiGroups:
- ""
- "apps"
- "batch"
- "networking.k8s.io"
- "rbac.authorization.k8s.io"
- "policy"
- "storage.k8s.io"
- "autoscaling"
- "apiextensions.k8s.io"
- "admissionregistration.k8s.io"
resources: ["*"]
verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/version", "/healthz"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: onam-scanner-readonly
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: onam-scanner-readonly
subjects:
- kind: ServiceAccount
name: onam-scanner
namespace: onam-system
---
apiVersion: v1
kind: Secret
metadata:
name: onam-scanner-token
namespace: onam-system
annotations:
kubernetes.io/service-account.name: onam-scanner
type: kubernetes.io/service-account-tokenkubectl apply -f onam-scanner.yamlThe ClusterRole includes read access to Secrets so Onam can flag risky patterns — stale ServiceAccount tokens, secrets mounted into privileged pods, plaintext credentials in ConfigMaps. Onam evaluates secret metadata and never stores secret values. If your policy forbids this, replaceresources: ["*"]in the core API group with an explicit list that omitssecrets— the related checks are then skipped and marked as such in reports.
Retrieve the token, CA certificate, and endpoint
# API server endpoint
APISERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
echo "API server: $APISERVER"
# ServiceAccount token (long-lived, bound to the Secret above)
TOKEN=$(kubectl -n onam-system get secret onam-scanner-token \
-o jsonpath='{.data.token}' | base64 -d)
echo "$TOKEN"
# Cluster CA certificate
kubectl -n onam-system get secret onam-scanner-token \
-o jsonpath='{.data.ca\.crt}' | base64 -d > onam-ca.crtStep 2 — Register the cluster in the Onam console
- In the Onam console, navigate to Onboarding → Connect Cloud Account
- Select Kubernetes
- Fill in the fields below
- Click Validate Connection — Onam performs a
get /versionand a namespace list to verify read access
| Field | Value |
|---|---|
| Cluster Alias | any friendly name, e.g. prod-eks-us-east-1 |
| API Server URL | the $APISERVER value from Step 1 |
| Distribution | EKS, AKS, GKE, OKE, ACK, IKS, or self-managed |
| CA Certificate | contents of onam-ca.crt |
| ServiceAccount Token | the $TOKEN value from Step 1 |
Run your first scan
- Navigate to Onboarding → Cloud Accounts
- Click the cluster you just added
- Click Run Scan Now — a cluster scan typically completes in 5–20 minutes depending on object count
Findings appear in the console graded Critical, High, Medium, Low, or Info, and flow into the Container Security views alongside image and runtime findings.
Managed clusters: EKS, AKS, and GKE
Cluster onboarding complements — not replaces — cloud account onboarding. The cloud connection sees the managed control plane from the outside; the cluster connection sees the objects inside it. Connect both for full coverage:
| Distribution | Cloud account connection covers | Cluster connection adds |
|---|---|---|
| EKS (connect AWS) | Cluster config, node groups, IRSA roles, security groups | Workloads, RBAC bindings, NetworkPolicies, Pod Security admission |
| AKS (connect Azure) | Cluster config, node pools, managed identities, NSGs | Workloads, RBAC bindings, NetworkPolicies, Pod Security admission |
| GKE (connect GCP) | Cluster config, node pools, Workload Identity, firewall rules | Workloads, RBAC bindings, NetworkPolicies, Pod Security admission |
When both connections exist, Onam's Container Security engine correlates them — for example, linking an over-privileged IRSA role (cloud side) to the pod that mounts it (cluster side), which also feeds attack path analysis.
Enable audit-log ingestion for CDR
Onam's CDR engine ingests Kubernetes audit logs through the Discovery & Inventory pipeline and runs three detection tiers over them: single-event rules (L1), multi-event correlation scenarios (L2), and statistical behavior baselines (L3). Audit logging is off by default on most distributions — enable it per platform:
| Distribution | How to enable audit logs |
|---|---|
| EKS | Enable audit in control-plane logging (logs land in CloudWatch, read via the AWS connection) |
| AKS | Add a diagnostic setting for the kube-audit category to a storage account |
| GKE | Cloud Audit Logs are on by default; confirm Data Access logs for the Kubernetes Engine API |
| Self-managed | Set --audit-log-path or an audit webhook on the API server, shipping to object storage |
Detections include anonymous API access, exec into production pods, ClusterRoleBinding escalation, and secret enumeration bursts.
What gets scanned
Onam evaluates 51 Kubernetes resource kinds against 718 posture rules, plus 103 CIEM rules focused on RBAC and identity — part of the 10,000+ rule registry spanning all seven supported clouds.
| Area | Resource kinds (examples) | Example checks |
|---|---|---|
| Workloads | Pods, Deployments, StatefulSets, DaemonSets, Jobs, CronJobs | Privileged containers · hostPath mounts · missing resource limits · latest-tag images |
| RBAC & identity | Roles, ClusterRoles, RoleBindings, ServiceAccounts | Wildcard verbs · cluster-admin bindings · auto-mounted tokens |
| Network | Services, Ingresses, NetworkPolicies | Namespaces without default-deny · public LoadBalancers · missing TLS on Ingress |
| Secrets & config | Secrets, ConfigMaps | Credentials in ConfigMaps · stale ServiceAccount tokens · unencrypted etcd (self-managed) |
| Cluster & admission | Namespaces, Nodes, PodSecurity admission, webhooks | Anonymous auth enabled · missing Pod Security standards · permissive admission webhooks |
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
401 Unauthorized | Token invalid or Secret recreated | Re-extract the token from onam-scanner-token and update it in the console |
Connection timed out | API server not reachable from Onam | Allowlist Onam's egress IPs on the endpoint, or use private connectivity |
x509: certificate signed by unknown authority | Wrong or truncated CA certificate | Re-extract ca.crt from the token Secret and re-paste the full PEM |
403 Forbidden on some kinds | ClusterRole missing an API group | Re-apply the manifest from Step 1 unchanged |
| Scan finds 0 workloads | ClusterRoleBinding subject mismatch | Verify the binding's subject namespace is onam-system |
| No audit-based CDR findings | Audit logging not enabled | Enable audit logs per the CDR section above |
Next steps
- Container Security — image scanning, runtime posture, and K8s RBAC analysis on this cluster.
- CIEM — effective-permission analysis across RBAC bindings and cloud IAM.
- CDR — behavioral detection over the audit logs you just enabled.
- Book a demo — walk through your first cluster scan with an Onam engineer.