Skip to content

Commit 7e7887b

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 aea80e6 commit 7e7887b

File tree

2 files changed

+137
-11
lines changed

2 files changed

+137
-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: 135 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,145 @@ 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_errno();
334+
flb_free(token_buf);
335+
return -1;
336+
}
337+
338+
memcpy(payload_b64, first_dot + 1, payload_b64_len);
339+
340+
/* Convert base64url to base64 and add padding */
341+
for (size_t i = 0; i < payload_b64_len; i++) {
342+
if (payload_b64[i] == '-') {
343+
payload_b64[i] = '+';
344+
}
345+
else if (payload_b64[i] == '_') {
346+
payload_b64[i] = '/';
347+
}
348+
}
349+
while (payload_b64_len < padded_len) {
350+
payload_b64[payload_b64_len++] = '=';
351+
}
352+
payload_b64[padded_len] = '\0';
353+
354+
/* Base64 decode the payload */
355+
payload = flb_malloc(payload_b64_len * 3 / 4 + 4); /* Conservative size estimate */
356+
if (!payload) {
357+
flb_errno();
358+
flb_free(token_buf);
359+
flb_free(payload_b64);
360+
return -1;
361+
}
362+
363+
ret = flb_base64_decode((unsigned char *)payload, padded_len * 3 / 4 + 4,
364+
&payload_len, (unsigned char *)payload_b64, padded_len);
365+
366+
flb_free(token_buf);
367+
flb_free(payload_b64);
368+
369+
if (ret != 0) {
370+
flb_free(payload);
371+
return -1;
372+
}
373+
374+
payload[payload_len] = '\0';
375+
376+
/* Look for "iss" field in the JSON payload */
377+
issuer_start = strstr(payload, "\"iss\":");
378+
if (!issuer_start) {
379+
flb_free(payload);
380+
return -1;
381+
}
382+
383+
/* Skip to the value part */
384+
issuer_start = strchr(issuer_start, ':');
385+
if (!issuer_start) {
386+
flb_free(payload);
387+
return -1;
388+
}
389+
issuer_start++;
390+
391+
/* Skip whitespace and opening quote */
392+
while (*issuer_start == ' ' || *issuer_start == '\t') issuer_start++;
393+
if (*issuer_start != '"') {
394+
flb_free(payload);
395+
return -1;
396+
}
397+
issuer_start++;
398+
399+
/* Find closing quote */
400+
issuer_end = strchr(issuer_start, '"');
401+
if (!issuer_end) {
402+
flb_free(payload);
403+
return -1;
404+
}
405+
406+
/* Check if issuer contains EKS OIDC URL pattern */
407+
/* EKS OIDC URLs follow pattern: https://oidc.eks.{region}.amazonaws.com/id/{cluster-id} */
408+
issuer_len = issuer_end - issuer_start;
409+
issuer_value = flb_strndup(issuer_start, issuer_len);
410+
if (!issuer_value) {
411+
flb_free(payload);
412+
return -1;
413+
}
291414

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;
415+
is_eks = strstr(issuer_value, "oidc.eks.") != NULL;`
416+
flb_free(issuer_value);
417+
418+
if (is_eks) {
419+
flb_free(payload);
420+
return 1; /* EKS detected */
296421
}
297-
return -1;
422+
423+
flb_free(payload);
424+
return -1; /* Not EKS */
298425
}
299426

300427
/* Gather pods list information from Kubelet */

0 commit comments

Comments
 (0)