- 
                Notifications
    
You must be signed in to change notification settings  - Fork 1.8k
 
filter_kubernetes: use service account issuer to detect EKS env #11002
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| 
          
            
          
           | 
    @@ -74,11 +74,10 @@ | |
| #define SERVICE_NAME_SOURCE_MAX_LEN 64 | ||
| 
     | 
||
| /* | ||
| * Configmap used for verifying whether if FluentBit is | ||
| * on EKS or native Kubernetes | ||
| * Namespace and token path used for verifying whether FluentBit is | ||
| * on EKS or native Kubernetes by inspecting serviceaccount token issuer | ||
| */ | ||
| #define KUBE_SYSTEM_NAMESPACE "kube-system" | ||
| #define AWS_AUTH_CONFIG_MAP "aws-auth" | ||
| 
         There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we keep this as a fallback for old clusters? Or does the issuer exist on both old and new cluster so it should just be the definitive mechanism for determining platforms? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is a good point. We found that the EKS service account issuer was introduced starting with EKS version 1.21, which has been EOL for quite some time now. This gave us confidence to move forward with this approach without a fallback.  | 
||
| 
     | 
||
| /* | ||
| * Possible platform values for Kubernetes plugin | ||
| 
          
            
          
           | 
    ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| 
          
            
          
           | 
    @@ -23,6 +23,7 @@ | |
| #include <fluent-bit/flb_jsmn.h> | ||
| #include <fluent-bit/flb_record_accessor.h> | ||
| #include <fluent-bit/flb_ra_key.h> | ||
| #include <fluent-bit/flb_utils.h> | ||
| 
     | 
||
| #include "kube_conf.h" | ||
| #include "kube_meta.h" | ||
| 
          
            
          
           | 
    @@ -282,19 +283,123 @@ int fetch_pod_service_map(struct flb_kube *ctx, char *api_server_url, | |
| return 0; | ||
| } | ||
| 
     | 
||
| /* Determine platform by checking aws-auth configmap */ | ||
| /* Determine platform by checking serviceaccount token issuer */ | ||
| int determine_platform(struct flb_kube *ctx) | ||
| { | ||
| int ret; | ||
| char *config_buf; | ||
| size_t config_size; | ||
| char *token_buf = NULL; | ||
| size_t token_size; | ||
| char *payload = NULL; | ||
| size_t payload_len; | ||
| char *issuer_start; | ||
| char *issuer_end; | ||
| char *first_dot; | ||
| char *second_dot; | ||
| size_t payload_b64_len; | ||
| char *payload_b64; | ||
| size_t issuer_len; | ||
| char *issuer_value; | ||
| 
     | 
||
| /* Read serviceaccount token */ | ||
| ret = flb_utils_read_file(FLB_KUBE_TOKEN, &token_buf, &token_size); | ||
| if (ret != 0 || !token_buf) { | ||
| return -1; | ||
| } | ||
| 
     | 
||
| /* JWT tokens have 3 parts separated by dots: header.payload.signature */ | ||
| first_dot = strchr(token_buf, '.'); | ||
| if (!first_dot) { | ||
| flb_free(token_buf); | ||
| return -1; | ||
| } | ||
| 
     | 
||
| second_dot = strchr(first_dot + 1, '.'); | ||
| if (!second_dot) { | ||
| flb_free(token_buf); | ||
| return -1; | ||
| } | ||
| 
     | 
||
| /* Extract and decode the payload (middle part) */ | ||
| payload_b64_len = second_dot - (first_dot + 1); | ||
| payload_b64 = flb_malloc(payload_b64_len + 1); | ||
| if (!payload_b64) { | ||
| flb_free(token_buf); | ||
| return -1; | ||
| } | ||
| 
     | 
||
| memcpy(payload_b64, first_dot + 1, payload_b64_len); | ||
| payload_b64[payload_b64_len] = '\0'; | ||
| 
     | 
||
| /* Base64 decode the payload */ | ||
| payload = flb_malloc(payload_b64_len * 3 / 4 + 4); /* Conservative size estimate */ | ||
| if (!payload) { | ||
| flb_free(token_buf); | ||
| flb_free(payload_b64); | ||
| return -1; | ||
| } | ||
| 
     | 
||
| ret = flb_base64_decode((unsigned char *)payload, payload_b64_len * 3 / 4 + 4, | ||
| &payload_len, (unsigned char *)payload_b64, payload_b64_len); | ||
                
      
                  movence marked this conversation as resolved.
               
          
            Show resolved
            Hide resolved
         | 
||
| 
     | 
||
| flb_free(token_buf); | ||
| flb_free(payload_b64); | ||
| 
         
      Comment on lines
    
      +341
     to 
      +345
    
   
  There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 
 The new EKS detection reads the service account JWT and decodes the payload with  Useful? React with 👍 / 👎. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cc: @movence ^  | 
||
| 
     | 
||
| if (ret != 0) { | ||
| flb_free(payload); | ||
| return -1; | ||
| } | ||
| 
     | 
||
| payload[payload_len] = '\0'; | ||
| 
     | 
||
| /* Look for "iss" field in the JSON payload */ | ||
| issuer_start = strstr(payload, "\"iss\":"); | ||
| if (!issuer_start) { | ||
| flb_free(payload); | ||
| return -1; | ||
| } | ||
| 
     | 
||
| /* Skip to the value part */ | ||
| issuer_start = strchr(issuer_start, ':'); | ||
| if (!issuer_start) { | ||
| flb_free(payload); | ||
| return -1; | ||
| } | ||
| issuer_start++; | ||
| 
     | 
||
| /* Skip whitespace and opening quote */ | ||
| while (*issuer_start == ' ' || *issuer_start == '\t') issuer_start++; | ||
| if (*issuer_start != '"') { | ||
| flb_free(payload); | ||
| return -1; | ||
| } | ||
| issuer_start++; | ||
| 
     | 
||
| /* Find closing quote */ | ||
| issuer_end = strchr(issuer_start, '"'); | ||
| if (!issuer_end) { | ||
| flb_free(payload); | ||
| return -1; | ||
| } | ||
| 
     | 
||
| /* Check if issuer contains EKS OIDC URL pattern */ | ||
| /* EKS OIDC URLs follow pattern: https://oidc.eks.{region}.amazonaws.com/id/{cluster-id} */ | ||
| issuer_len = issuer_end - issuer_start; | ||
| issuer_value = flb_strndup(issuer_start, issuer_len); | ||
| if (!issuer_value) { | ||
| flb_free(payload); | ||
| return -1; | ||
| } | ||
| 
     | 
||
| ret = get_api_server_configmap(ctx, KUBE_SYSTEM_NAMESPACE, AWS_AUTH_CONFIG_MAP, &config_buf, &config_size); | ||
| if (ret != -1) { | ||
| flb_free(config_buf); | ||
| return 1; | ||
| int is_eks = (strstr(issuer_value, "oidc.eks.") && strstr(issuer_value, ".amazonaws.com/id/")); | ||
| flb_free(issuer_value); | ||
| 
     | 
||
| if (is_eks) { | ||
| flb_free(payload); | ||
| return 1; /* EKS detected */ | ||
| } | ||
| return -1; | ||
| 
     | 
||
| flb_free(payload); | ||
| return -1; /* Not EKS */ | ||
| } | ||
| 
     | 
||
| /* Gather pods list information from Kubelet */ | ||
| 
          
            
          
           | 
    ||
Uh oh!
There was an error while loading. Please reload this page.