Skip to content

Commit 176bf18

Browse files
committed
filter_kubernetes: use service account issuer to detect EKS env
More reliable AWS EKS detection by inspecting service account token issuer Signed-off-by: Hyunsoo Kim <[email protected]>
1 parent ed06c31 commit 176bf18

File tree

2 files changed

+131
-11
lines changed

2 files changed

+131
-11
lines changed

plugins/filter_kubernetes/kube_conf.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,10 @@
7474
#define SERVICE_NAME_SOURCE_MAX_LEN 64
7575

7676
/*
77-
* Configmap used for verifying whether if FluentBit is
78-
* on EKS or native Kubernetes
77+
* Namespace and token path used for verifying whether FluentBit is
78+
* on EKS or native Kubernetes by inspecting serviceaccount token issuer
7979
*/
8080
#define KUBE_SYSTEM_NAMESPACE "kube-system"
81-
#define AWS_AUTH_CONFIG_MAP "aws-auth"
8281

8382
/*
8483
* Possible platform values for Kubernetes plugin

plugins/filter_kubernetes/kubernetes_aws.c

Lines changed: 129 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <fluent-bit/flb_jsmn.h>
2424
#include <fluent-bit/flb_record_accessor.h>
2525
#include <fluent-bit/flb_ra_key.h>
26+
#include <fluent-bit/flb_utils.h>
2627

2728
#include "kube_conf.h"
2829
#include "kube_meta.h"
@@ -282,19 +283,139 @@ int fetch_pod_service_map(struct flb_kube *ctx, char *api_server_url,
282283
return 0;
283284
}
284285

285-
/* Determine platform by checking aws-auth configmap */
286+
/* Determine platform by checking serviceaccount token issuer */
286287
int determine_platform(struct flb_kube *ctx)
287288
{
288289
int ret;
289-
char *config_buf;
290-
size_t config_size;
290+
char *token_buf = NULL;
291+
size_t token_size;
292+
char *payload = NULL;
293+
size_t payload_len;
294+
char *issuer_start;
295+
char *issuer_end;
296+
char *first_dot;
297+
char *second_dot;
298+
size_t payload_b64_len;
299+
size_t padded_len;
300+
char *payload_b64;
301+
size_t issuer_len;
302+
char *issuer_value;
303+
int is_eks;
304+
305+
/* Read serviceaccount token */
306+
ret = flb_utils_read_file(FLB_KUBE_TOKEN, &token_buf, &token_size);
307+
if (ret != 0 || !token_buf) {
308+
return -1;
309+
}
310+
311+
/* JWT tokens have 3 parts separated by dots: header.payload.signature */
312+
first_dot = strchr(token_buf, '.');
313+
if (!first_dot) {
314+
flb_free(token_buf);
315+
return -1;
316+
}
317+
318+
second_dot = strchr(first_dot + 1, '.');
319+
if (!second_dot) {
320+
flb_free(token_buf);
321+
return -1;
322+
}
323+
324+
/* Extract and decode the payload (middle part) */
325+
payload_b64_len = second_dot - (first_dot + 1);
326+
327+
/* Calculate padded length */
328+
padded_len = payload_b64_len;
329+
while (padded_len % 4 != 0) padded_len++;
330+
331+
payload_b64 = flb_malloc(padded_len + 1);
332+
if (!payload_b64) {
333+
flb_free(token_buf);
334+
return -1;
335+
}
336+
337+
memcpy(payload_b64, first_dot + 1, payload_b64_len);
338+
339+
/* Convert base64url to base64 and add padding */
340+
for (size_t i = 0; i < payload_b64_len; i++) {
341+
if (payload_b64[i] == '-') payload_b64[i] = '+';
342+
else if (payload_b64[i] == '_') payload_b64[i] = '/';
343+
}
344+
while (payload_b64_len < padded_len) {
345+
payload_b64[payload_b64_len++] = '=';
346+
}
347+
payload_b64[padded_len] = '\0';
348+
349+
/* Base64 decode the payload */
350+
payload = flb_malloc(payload_b64_len * 3 / 4 + 4); /* Conservative size estimate */
351+
if (!payload) {
352+
flb_free(token_buf);
353+
flb_free(payload_b64);
354+
return -1;
355+
}
356+
357+
ret = flb_base64_decode((unsigned char *)payload, padded_len * 3 / 4 + 4,
358+
&payload_len, (unsigned char *)payload_b64, padded_len);
359+
360+
flb_free(token_buf);
361+
flb_free(payload_b64);
362+
363+
if (ret != 0) {
364+
flb_free(payload);
365+
return -1;
366+
}
367+
368+
payload[payload_len] = '\0';
369+
370+
/* Look for "iss" field in the JSON payload */
371+
issuer_start = strstr(payload, "\"iss\":");
372+
if (!issuer_start) {
373+
flb_free(payload);
374+
return -1;
375+
}
376+
377+
/* Skip to the value part */
378+
issuer_start = strchr(issuer_start, ':');
379+
if (!issuer_start) {
380+
flb_free(payload);
381+
return -1;
382+
}
383+
issuer_start++;
384+
385+
/* Skip whitespace and opening quote */
386+
while (*issuer_start == ' ' || *issuer_start == '\t') issuer_start++;
387+
if (*issuer_start != '"') {
388+
flb_free(payload);
389+
return -1;
390+
}
391+
issuer_start++;
392+
393+
/* Find closing quote */
394+
issuer_end = strchr(issuer_start, '"');
395+
if (!issuer_end) {
396+
flb_free(payload);
397+
return -1;
398+
}
399+
400+
/* Check if issuer contains EKS OIDC URL pattern */
401+
/* EKS OIDC URLs follow pattern: https://oidc.eks.{region}.amazonaws.com/id/{cluster-id} */
402+
issuer_len = issuer_end - issuer_start;
403+
issuer_value = flb_strndup(issuer_start, issuer_len);
404+
if (!issuer_value) {
405+
flb_free(payload);
406+
return -1;
407+
}
291408

292-
ret = get_api_server_configmap(ctx, KUBE_SYSTEM_NAMESPACE, AWS_AUTH_CONFIG_MAP, &config_buf, &config_size);
293-
if (ret != -1) {
294-
flb_free(config_buf);
295-
return 1;
409+
is_eks = strstr(issuer_value, "oidc.eks.") != NULL;`
410+
flb_free(issuer_value);
411+
412+
if (is_eks) {
413+
flb_free(payload);
414+
return 1; /* EKS detected */
296415
}
297-
return -1;
416+
417+
flb_free(payload);
418+
return -1; /* Not EKS */
298419
}
299420

300421
/* Gather pods list information from Kubelet */

0 commit comments

Comments
 (0)