Skip to content

Commit 630081e

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 630081e

File tree

2 files changed

+130
-11
lines changed

2 files changed

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

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;
408+
int is_eks = (strstr(issuer_value, "oidc.eks.") && strstr(issuer_value, ".amazonaws.com/id/"));
409+
flb_free(issuer_value);
410+
411+
if (is_eks) {
412+
flb_free(payload);
413+
return 1; /* EKS detected */
296414
}
297-
return -1;
415+
416+
flb_free(payload);
417+
return -1; /* Not EKS */
298418
}
299419

300420
/* Gather pods list information from Kubelet */

0 commit comments

Comments
 (0)