Kubernetes access without a kubeconfig
Octelium is a free and open source, self-hosted zero trust access platform. Its Kubernetes mode holds the kubeconfig, client certificate or bearer token, authorizes every API request on its verb, resource and namespace, and records what was called and by whom.
- Free and open source
- Designed for self-hosting
- Works with ordinary kubectl
kind: Service
metadata:
name: prod-k8s
spec:
mode: KUBERNETES
config:
upstream:
url: https://k8s.internal:6443
kubernetes:
kubeconfig:
fromSecret: kubeconfig-prodkind: Policy
metadata:
name: k8s-sre
spec:
rules:
- effect: ALLOW
condition:
all:
of:
- match: ctx.request.kubernetes.verb == "get"
- match: ctx.request.kubernetes.resource == "pods"
- match: '"sre" in ctx.user.spec.groups'kind: Service
metadata:
name: staging-k8s
spec:
mode: KUBERNETES
config:
upstream:
url: https://k8s-staging.internal:6443
kubernetes:
kubeconfig:
context: staging
fromSecret: kubeconfig-allA unified secure access platform
Kubernetes is one mode of the same platform. Each capability is described in detail below, in the same order.
- Unified access platform
One architecture for client-based zero-config VPN-like access over WireGuard and QUIC tunnels and clientless access over browsers for humans and OAuth2 access for workloads.
Read more - L7-aware access control
Identity-based, application-layer aware ABAC access control with policy-as-code via CEL and OPA, applied on a per-request basis.
Read more - Secretless access
Dynamic secretless access where teams and AI agents access protected infrastructure without ever holding a credential.
Read more - Unified identity management
Teams, workloads and AI agents share the same model for identity management, access control, and auditing.
Read more - Real-time visibility and auditing
OpenTelemetry-native, real-time, application-layer-aware visibility and structured logging.
Read more - GitOps-friendly management
Octelium is administered like Kubernetes. Define your resources in YAML files, store them in a Git repository.
Read more
One architecture for every cluster you operate
Each Kubernetes cluster is represented by a Service, which is served by an identity-aware proxy that abstracts away the network details of the API server behind it. People keep using kubectl, and applications keep using ordinary HTTP clients.
- Over a client-based WireGuard or QUIC tunnel, the API server is reached at a stable private name, so a private cluster does not need a public endpoint or a bastion to hop through.
- Published clientlessly, the same Service lets workloads call the API over HTTPS with standard OAuth2 client credentials or a bearer access token, with no kubeconfig and no SDK.
- A cluster in a network the Octelium Cluster cannot reach directly is served from the side of a connected host inside it, so a remote or edge cluster needs no inbound port.
kind: Service
metadata:
name: prod-k8s
spec:
mode: KUBERNETES
config:
upstream:
url: https://k8s.internal:6443
kubernetes:
kubeconfig:
fromSecret: kubeconfig-prodkind: Service
metadata:
name: prod-k8s
spec:
mode: KUBERNETES
isPublic: true
config:
upstream:
url: https://k8s.internal:6443
kubernetes:
kubeconfig:
fromSecret: kubeconfig-prodkind: Service
metadata:
name: edge-k8s
spec:
mode: KUBERNETES
config:
upstream:
url: https://10.90.0.4:6443
user: edge-gw
kubernetes:
kubeconfig:
fromSecret: kubeconfig-edgeLayer-7 aware access control with policy-as-code
Access is authorized on a per-request basis, using CEL or Open Policy Agent, against the identity behind the request and the API call itself rather than the network path it arrived on.
- The verb, resource, namespace, API group, API version, object name and subresource are each normalized into the request context and available to a Policy.
- Those combine with identity, group membership, device posture, session type and time in the same expression, so read access in production can require a managed device.
- One set of Policies covers every cluster behind the platform, which avoids maintaining parallel role bindings in each of them for the same team.
kind: Policy
metadata:
name: read-only-prod
spec:
rules:
- effect: ALLOW
condition:
all:
of:
- match: ctx.request.kubernetes.verb in ["get", "list"]
- match: ctx.request.kubernetes.namespace == "production"
- match: ctx.request.kubernetes.resource in ["pods"]
- match: '"support" in ctx.user.spec.groups'kind: Policy
metadata:
name: logs-only
spec:
rules:
- effect: ALLOW
condition:
all:
of:
- match: ctx.request.kubernetes.verb == "get"
- match: ctx.request.kubernetes.resource == "pods"
- match: ctx.request.kubernetes.subresource == "log"
- match: ctx.request.kubernetes.apiVersion == "v1"kind: Policy
metadata:
name: no-secrets
spec:
rules:
- effect: DENY
condition:
match: ctx.request.kubernetes.resource == "secrets"
- effect: ALLOW
condition:
match: '"engineers" in ctx.user.spec.groups'Kubeconfigs that are never distributed
The upstream credential is stored in the Cluster as a Secret and used to authenticate to the API server once a request is authorized. Nobody receives a kubeconfig, a client certificate or a service account token, so there is nothing to collect back when someone leaves.
- Kubeconfigs, client certificates with trusted CAs, and bearer tokens are all supported, and a kubeconfig containing several contexts can be pinned to the one a Service uses.
- Which upstream credential is used can be selected per request from identity and context, so one Service maps an operations group to a privileged identity and everyone else to a read-only one.
- Revoking access is a Policy change or a Session revocation rather than rotating a credential across every cluster and every laptop that held a copy.
octeliumctl create secret \
--file /path/to/kubeconfig \
kubeconfig-prod
# The Service then references it by name,
# and Users never receive the file itself.kind: Service
metadata:
name: prod-k8s
spec:
mode: KUBERNETES
config:
upstream:
url: https://k8s.internal:6443
kubernetes:
bearerToken:
fromSecret: k8s-bearer-tokenkind: Service
metadata:
name: prod-k8s
spec:
mode: KUBERNETES
config:
upstream:
url: https://k8s.internal:6443
kubernetes:
bearerToken:
fromSecret: k8s-read-only-token
dynamicConfig:
configs:
- name: admin
upstream:
url: https://k8s.internal:6443
kubernetes:
bearerToken:
fromSecret: k8s-admin-token
rules:
- condition:
match: '"sre" in ctx.user.spec.groups'
configName: adminA unified identity model for humans and workloads
Human and workload Users share the same identity management, authentication, access control and visibility model. A deployment pipeline calling the API is authorized and audited exactly as an engineer would be.
- Workloads authenticate with authentication tokens, with the OAuth2 client credentials flow, or secretlessly with federated OIDC assertions from GitHub Actions, cloud providers and Kubernetes clusters.
- People authenticate through any OpenID Connect or SAML 2.0 identity provider, with native FIDO2 and WebAuthn passkeys, TOTP and TPM 2.0 authenticators available on top of it.
- Applications running inside a cluster can be published as ordinary Services of their own, so a dashboard or an internal API does not need a separate ingress and a separate authentication story.
- Cordium, built on Octelium, provides isolated sandboxes for agents and developers, where processes reach authorized Services through the Workspace identity with no secrets inside the sandbox.
kind: IdentityProvider
metadata:
name: github-actions
spec:
oidcIdentityToken:
issuerURL: https://token.actions.githubusercontent.com
audience: https://example.comkind: User
metadata:
name: deployer
spec:
type: WORKLOAD
groups:
- cikind: Service
metadata:
name: argocd
spec:
mode: WEB
isPublic: true
config:
upstream:
url: http://argocd-server.argocd.svc:80Every API call, with the identity that made it
Every request produces an AccessLog identifying the User, Session and Device alongside the Kubernetes detail of the request itself, emitted in real time to your OpenTelemetry OTLP receivers.
- Entries record the verb, resource, namespace, API version and the underlying HTTP information, attributed to an Octelium User rather than to a shared service account.
- That holds across every cluster behind the platform, so an audit does not have to be assembled from separate API server audit logs with different retention.
- Logs are exported over OpenTelemetry OTLP in real-time to SIEM providers you already operate.
A scalable platform that also deploys your workloads
A Cluster runs on Kubernetes and uses it to scale its own data plane, place Service proxies across Gateways, and run containerized applications that the Cluster itself deploys.
- Managed containers deploy, scale and serve containerized applications as Service upstreams, which also makes the platform usable as an ingress and hosting layer for the workloads it protects.
- The Cluster is managed declaratively. Resources are defined in YAML, kept in a Git repository, and applied with a single octeliumctl apply that reproduces the entire Cluster state.
- Management is centralized over the Cluster's gRPC APIs, so onboarding a new cluster can itself be automated.
$ octeliumctl apply ./cluster
Secret: kubeconfig-prod Updated
Secret: k8s-admin-token Updated
IdentityProvider: okta Updated
Policy: read-only-prod Created
Group: sre Created
Group: support Updated
Service: prod-k8s Created
Service: staging-k8s Created
Service: argocd Created
User: deployer Created
Cluster Core resources successfully applied
7 resources created
3 resources updated
ClusterConfig updatedWhat a Kubernetes API request carries, and what checks it
A kubectl call is not one decision. These are the parts of a request that matter for access control and auditing, next to the mechanism in an Octelium Cluster that handles each one.
- 01
Who is making the call
The request carries an Octelium identity rather than a kubeconfig. People authenticate through your OpenID Connect or SAML 2.0 identity provider, and workloads through OAuth2 client credentials, access tokens or federated OIDC assertions.
Read more - 02
The verb
get, list, watch, create, update, patch and delete are normalized into the request context, so read access and write access to the same resource are separate decisions rather than one role binding.
Read more - 03
The resource and its API group
The resource, API group and API version are each available, so a policy can allow pods and services while leaving custom resources or cluster-scoped objects untouched.
Read more - 04
The namespace
The namespace is a normalized field, so the same Service can allow one group everything in staging and only reads in production, without maintaining parallel RBAC in each cluster.
Read more - 05
The object and subresource
The object name and subresource are available too, which is what makes rules such as reading pod logs without reading pod specs, or reading a status without patching it, expressible.
Read more - 06
The underlying HTTP request
Kubernetes is an HTTP API, and the full HTTP request is exposed alongside the normalized fields, including headers and paths, for the cases the normalized view does not cover.
Read more - 07
The credential used upstream
A kubeconfig, a client certificate or a bearer token is held as a Secret and used to authenticate to the API server after authorization. Which one is used can itself be selected per request from identity and context.
Read more - 08
What ends up in the audit trail
Each request produces an identity-aware AccessLog with the verb, resource, namespace, API version and the User behind it, streamed in real time over OpenTelemetry to your own log management and SIEM providers.
Read more
RBAC still decides what the credential the Cluster holds may do. What changes is that nobody carries that credential, and the decision about who may use it is made per request against an identity you already manage.
The same platform capabilities ship with every deployment, whichever way you use it.
Frequently asked
- Does this replace Kubernetes RBAC?
- No. RBAC still governs what the credential held by the Cluster is allowed to do inside the cluster. What changes is who holds that credential and how each request is decided: the kubeconfig, client certificate or bearer token stays in the Cluster, and every API call is authorized per request against an identity you already manage, before it reaches the API server.
- How do people use kubectl?
- With their ordinary kubectl. The Service is reached at a stable private name over the client-based tunnel, and the identity-aware proxy authenticates to the API server on the User's behalf. Nobody is issued a kubeconfig, a client certificate or a service account token of their own.
- Which upstream credentials are supported?
- Three. A kubeconfig stored as a Secret, optionally pinned to a specific context when the file contains several; a client certificate with its private key and trusted CAs; or a bearer token with trusted CAs. All three are referenced by Secret name from the Service definition.
- Can workloads reach the API without a client?
- Yes. A KUBERNETES Service can be published clientlessly, so an application authenticates with the standard OAuth2 client credentials flow or a bearer access token and calls the API over ordinary HTTPS, without a kubeconfig, a client or a proprietary SDK.
- Does it work across several clusters?
- Yes. Each cluster is its own Service with its own upstream credential and its own Policies, and a cluster in a network the Octelium Cluster cannot reach directly can be served from the side of a connected host inside that network with no inbound port. People reach all of them through the same single route and the same identity.
- Do I need Kubernetes experience to run Octelium itself?
- No. An Octelium Cluster runs on top of Kubernetes, but you do not need Kubernetes experience to install, operate or use it. The quick installer provisions a complete single-node Cluster, including Kubernetes itself, on one fresh Linux VM with 2 vCPUs, 2 GB of RAM and a domain you own.
Related solutions
Zero trust SSH
Secretless SSH without distributing keys or operating a PKI, with session recording and embedded SSH for fleets.
Read moreZero trust database access
Secretless PostgreSQL and MySQL access with per-request authorization and application-layer auditing.
Read moreSelf-hosted PaaS
Deploy, scale and serve containerized applications that the Cluster itself runs, with or without public access.
Read moreDeploy Octelium on your own infrastructure in minutes
Free and open source. Self-hosted. No vendor lock-in.