Kubernetes

Octelium supports a Kubernetes mode by setting the Service mode to KUBERNETES. This mode provides:

  • Secret-less access for authorized Users to Kubernetes cluster APIs.
  • Application-layer aware access control where you, for example, allow certain Users to access certain Kubernetes resources in certain namespaces under certain conditions.
  • Application-layer aware dynamic configuration such as routing to different upstreams and/or credentials (read more here).
  • Application-layer aware visibility where

Secret-less Access

In order to provide secret-less access to KUBERNETES Services, you need to set the credentials required for the authentication to the upstream Kubernetes cluster. There are three authentication methods: Kubeconfig files, client certificates and bearer tokens.

Kubeconfig

1
kind: Service
2
metadata:
3
name: k8s1
4
spec:
5
mode: KUBERNETES
6
config:
7
upstream:
8
url: https://k8s-cluster.example.com:6443
9
kubernetes:
10
kubeconfig:
11
fromSecret: kubeconfig-k8s1

You can also choose a specific Kubeconfig context if you have more than one as follows:

1
kind: Service
2
metadata:
3
name: k8s1
4
spec:
5
mode: KUBERNETES
6
config:
7
upstream:
8
url: https://k8s-cluster.example.com:6443
9
kubernetes:
10
kubeconfig:
11
context: ctx-abcd
12
fromSecret: kubeconfig-k8s1

Client Certificate

You can manually set the client certificate credentials as follows:

1
kind: Service
2
metadata:
3
name: k8s1
4
spec:
5
mode: KUBERNETES
6
config:
7
upstream:
8
url: https://k8s-cluster.example.com:6443
9
kubernetes:
10
clientCertificate:
11
fromSecret: k8s-client-cert
12
trustedCAs:
13
- |
14
-----BEGIN CERTIFICATE-----
15
MIIDBTCCAe2gAwIBAgIIf811HQrTMBAwDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE
16
AxMKa3ViZXJuZXRlczAeFw0yNDA4MTkxMTEzNThaFw0zNDA4MTcxMTE4NThaMBUx
17
EzARBgNVBAMTCmt1YmVybmV0ZXMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
18
AoIBAQCg/Bw/rDlvZE6If1aVGfU324owXgLWsaI8MXThedmauhEp1xSPK9gtPaVR
19
omG6JwAgyln5YyFWSYDSLn2Pb/jBVPWslkdnTGfd3cDPe22+dpQinF1WsBylNuji
20
p00gst4rUl8bsxL/9a+3fcl4FBBUsyc6jQGBzHeH8Ilj+pUizIX1dj3oN97h1qiQ
21
VB0OiX/UNn/BePfoIzPBFtAqBQMKosLQ4aoVru0J4xDf4upDAN90bjWYiuxqMhXX
22
N49PZVZS8hw0k3zlTjOXxkrcQNCoPOA16a+gHbq8klUVhPoiwEIDpvu9QQ61Ppp/
23
gUIG98XviG6uPuRNa11zaRrFGcVJAgMBAAGjWTBXMA4GA1UdDwEB/wQEAwICpDAP
24
BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTVR79cj39ezb0jHsS13gPBc1VMzTAV
25
BgNVHREEDjAMggprdWJlcm5ldGVzMA0GCSqGSIb3DQEBCwUAA4IBAQA9K9tQlqW4
26
vVPdWHb1LngRmvafgtrSN5K8m0yj3cCW3wOAms/zLN7QF6L5x9BwHCIzub3mbJUa
27
QG+Hgs071q8UdBjWRtosh30L7LEpV0UZkLNPYjzFtbA+OVZH/htfijfAp68xnQ1E
28
E3nZah06C59InOZHC5zbNdybhbiyVIr+0zbGFbHWrA19tIakM5o34uEnC2QEnkQu
29
CKu1lpmacjJMiztGgEIq9GSc67hYdrHiy3oThkno/jdeBETCFeWB4TDuUSUIefAp
30
4MjEh8mhH3An8HEmXtfpCxXc5HaFf3gavakAzwshe+zBs5L4CS7/IZvoOzW8P3MN
31
tGKzn7JqDH2O
32
-----END CERTIFICATE-----

Bearer Token

You can also manually set a bearer token if required by the upstream cluster as follows:

1
kind: Service
2
metadata:
3
name: k8s1
4
spec:
5
mode: KUBERNETES
6
config:
7
upstream:
8
url: https://k8s-cluster.example.com:6443
9
kubernetes:
10
bearerToken:
11
fromSecret: kubeconfig-k8s1
12
trustedCAs:
13
- |
14
-----BEGIN CERTIFICATE-----
15
MIIDBTCCAe2gAwIBAgIIf811HQrTMBAwDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE
16
AxMKa3ViZXJuZXRlczAeFw0yNDA4MTkxMTEzNThaFw0zNDA4MTcxMTE4NThaMBUx
17
EzARBgNVBAMTCmt1YmVybmV0ZXMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
18
AoIBAQCg/Bw/rDlvZE6If1aVGfU324owXgLWsaI8MXThedmauhEp1xSPK9gtPaVR
19
omG6JwAgyln5YyFWSYDSLn2Pb/jBVPWslkdnTGfd3cDPe22+dpQinF1WsBylNuji
20
p00gst4rUl8bsxL/9a+3fcl4FBBUsyc6jQGBzHeH8Ilj+pUizIX1dj3oN97h1qiQ
21
VB0OiX/UNn/BePfoIzPBFtAqBQMKosLQ4aoVru0J4xDf4upDAN90bjWYiuxqMhXX
22
N49PZVZS8hw0k3zlTjOXxkrcQNCoPOA16a+gHbq8klUVhPoiwEIDpvu9QQ61Ppp/
23
gUIG98XviG6uPuRNa11zaRrFGcVJAgMBAAGjWTBXMA4GA1UdDwEB/wQEAwICpDAP
24
BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTVR79cj39ezb0jHsS13gPBc1VMzTAV
25
BgNVHREEDjAMggprdWJlcm5ldGVzMA0GCSqGSIb3DQEBCwUAA4IBAQA9K9tQlqW4
26
vVPdWHb1LngRmvafgtrSN5K8m0yj3cCW3wOAms/zLN7QF6L5x9BwHCIzub3mbJUa
27
QG+Hgs071q8UdBjWRtosh30L7LEpV0UZkLNPYjzFtbA+OVZH/htfijfAp68xnQ1E
28
E3nZah06C59InOZHC5zbNdybhbiyVIr+0zbGFbHWrA19tIakM5o34uEnC2QEnkQu
29
CKu1lpmacjJMiztGgEIq9GSc67hYdrHiy3oThkno/jdeBETCFeWB4TDuUSUIefAp
30
4MjEh8mhH3An8HEmXtfpCxXc5HaFf3gavakAzwshe+zBs5L4CS7/IZvoOzW8P3MN
31
tGKzn7JqDH2O
32
-----END CERTIFICATE-----

Access Control

You can control access based on the Kubernetes HTTP request information. Such information are stored in ctx.request.kubernetes where it contains information such as the resource, namespace, verb, API group, API version and sub-resource if available. Additionally all the HTTP related information that are exposed in the HTTP mode are also exposed in the variable ctx.request.kubernetes.http. Here is a detailed example of a inline Policy that controls access based on Kubernetes-specific information:

1
kind: Service
2
metadata:
3
name: svc1
4
spec:
5
mode: KUBERNETES
6
config:
7
upstream:
8
url: https://k8s-cluster.example.com:6443
9
kubernetes:
10
kubeconfig:
11
context: ctx-abcd
12
fromSecret: kubeconfig-k8s1
13
authorization:
14
inlinePolicies:
15
- spec:
16
rules:
17
- effect: ALLOW
18
condition:
19
any:
20
of:
21
- match: ctx.request.kubernetes.apiGroup in ["k8s.cni.cncf.io", "events.k8s.io"]
22
- match: ctx.request.kubernetes.apiVersion == "v1"
23
- match: ctx.request.kubernetes.verb in ["create", "get", "list", "update", "watch", "patch", "delete"]
24
- match: ctx.request.kubernetes.namespace == "production"
25
- match: ctx.request.kubernetes.resource in ["pods", "services"]
26
- match: ctx.request.kubernetes.name == "pod-abcdef"
27
- match: ctx.request.kubernetes.subresource == "status"
28
- match: ctx.request.kubernetes.http.headers["x-custom-header"] == "this-value"

Visibility

The Service emits access logs in real time to the audit collector. Each log provides Kubernetes application-layer aware information about the request such as the request's namespace, resource, sub-resource, API version and API prefix. Additionally, all underlying HTTP-based information are also included. Here is an example:

1
{
2
"apiVersion": "core/v1",
3
"entry": {
4
"common": {
5
"endedAt": "2025-03-21T23:09:59.918594707Z",
6
"isAuthenticated": true,
7
"isAuthorized": true,
8
"namespaceRef": {
9
"apiVersion": "core/v1",
10
"kind": "Namespace",
11
"name": "default",
12
"resourceVersion": "0195b81d-43ec-7ba7-81f7-9b77202b3612",
13
"uid": "bff0768e-eec8-4044-a972-9f7af81b79d8"
14
},
15
"reason": {
16
"details": {
17
"policyMatch": {
18
"inlinePolicy": {
19
"name": "allow-all",
20
"resourceRef": {
21
"apiVersion": "core/v1",
22
"kind": "Group",
23
"name": "g1",
24
"resourceVersion": "0195b821-209b-76f7-bde9-b078e870621c",
25
"uid": "972e1808-7248-468a-ba7c-8da43d33c626"
26
}
27
}
28
}
29
},
30
"type": "POLICY_MATCH"
31
},
32
"regionRef": {
33
"apiVersion": "core/v1",
34
"kind": "Region",
35
"name": "default",
36
"uid": "6e233d12-2fd6-4670-a82d-8c712e1f7374"
37
},
38
"serviceRef": {
39
"apiVersion": "core/v1",
40
"kind": "Service",
41
"name": "k8s1.default",
42
"resourceVersion": "0195baf7-8941-78ce-a54b-52dbaa7b9a1d",
43
"uid": "6a2d8b0f-a0fe-4544-927f-7b3094bad578"
44
},
45
"sessionRef": {
46
"apiVersion": "core/v1",
47
"kind": "Session",
48
"name": "usr1-3pt93j",
49
"resourceVersion": "0195baf5-206b-7587-8c41-cf5766602111",
50
"uid": "e8bea7be-b858-4457-a8ee-a0cb7f6c91da"
51
},
52
"startedAt": "2025-03-21T23:09:59.871329180Z",
53
"userRef": {
54
"apiVersion": "core/v1",
55
"kind": "User",
56
"name": "usr1",
57
"resourceVersion": "0195b821-228d-79b2-92f3-4bb458944f97",
58
"uid": "e0f251b2-6952-4a46-a771-2712a45c47f5"
59
}
60
},
61
"info": {
62
"kubernetes": {
63
"apiPrefix": "api",
64
"apiVersion": "v1",
65
"http": {
66
"httpVersion": "HTTP11",
67
"request": {
68
"method": "GET",
69
"path": "/api/v1/namespaces/octelium/pods?limit=500",
70
"userAgent": "kubectl/v1.32.3 (linux/amd64) kubernetes/32cc146"
71
},
72
"response": {
73
"bodyBytes": "18559",
74
"code": 200
75
}
76
},
77
"namespace": "octelium",
78
"resource": "pods",
79
"verb": "list"
80
}
81
}
82
},
83
"kind": "AccessLog",
84
"metadata": {
85
"actorRef": {
86
"apiVersion": "core/v1",
87
"kind": "Session",
88
"name": "usr1-3pt93j",
89
"resourceVersion": "0195baf5-206b-7587-8c41-cf5766602111",
90
"uid": "e8bea7be-b858-4457-a8ee-a0cb7f6c91da"
91
},
92
"createdAt": "2025-03-21T23:09:59.918580014Z",
93
"id": "hg47-2zve-u8x5vh20ri132e2zptiv5jad-v1bx-51u7",
94
"targetRef": {
95
"apiVersion": "core/v1",
96
"kind": "Service",
97
"name": "k8s1.default",
98
"resourceVersion": "0195baf7-8941-78ce-a54b-52dbaa7b9a1d",
99
"uid": "6a2d8b0f-a0fe-4544-927f-7b3094bad578"
100
}
101
}
102
}
© 2025 octelium.comOctelium Labs, LLCAll rights reserved
Octelium and Octelium logo are trademarks of Octelium Labs, LLC.
WireGuard is a registered trademark of Jason A. Donenfeld