Skip to content

Commit

Permalink
Fix EKS cluster detection (#1532)
Browse files Browse the repository at this point in the history
  • Loading branch information
musa-asad authored Feb 11, 2025
1 parent 5e3b831 commit 799f0c3
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 2 deletions.
47 changes: 46 additions & 1 deletion translator/util/eksdetector/eksdetector.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ package eksdetector

import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"strings"
"sync"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -15,6 +18,7 @@ import (

type Detector interface {
getConfigMap(namespace string, name string) (map[string]string, error)
getIssuer() (string, error)
}

type EksDetector struct {
Expand Down Expand Up @@ -55,7 +59,8 @@ var (
}

// IsEKS checks if the agent is running on EKS. This is done by using the kubernetes API to determine if the aws-auth
// configmap exists in the kube-system namespace
// configmap exists in the kube-system namespace or by extracting the "iss" field from the service account token and
// checking if it contains "eks" as a fall-back
IsEKS = func() IsEKSCache {
once.Do(func() {
var errors error
Expand All @@ -71,6 +76,11 @@ var (
awsAuth, err := eksDetector.getConfigMap(authConfigNamespace, authConfigConfigMap)
if err == nil {
value = awsAuth != nil
} else {
issuer, err := eksDetector.getIssuer()
if err == nil {
value = strings.Contains(strings.ToLower(issuer), "eks")
}
}
}
isEKSCacheSingleton = IsEKSCache{Value: value, Err: errors}
Expand All @@ -90,6 +100,41 @@ func (d *EksDetector) getConfigMap(namespace string, name string) (map[string]st
return configMap.Data, nil
}

// getIssuer retrieves the issuer ("iss") from the service account token
func (d *EksDetector) getIssuer() (string, error) {
conf, err := getInClusterConfig()
if err != nil {
return "", fmt.Errorf("failed to get in-cluster config: %w", err)
}

token := conf.BearerToken
if token == "" {
return "", fmt.Errorf("empty token in config")
}

parts := strings.Split(token, ".")
if len(parts) < 2 {
return "", fmt.Errorf("missing payload")
}

decoded, err := base64.RawURLEncoding.DecodeString(parts[1])
if err != nil {
return "", fmt.Errorf("failed to decode token payload: %w", err)
}

var claims map[string]interface{}
if err = json.Unmarshal(decoded, &claims); err != nil {
return "", fmt.Errorf("failed to unmarshal token payload: %w", err)
}

iss, ok := claims["iss"].(string)
if !ok {
return "", fmt.Errorf("issuer field not found in token")
}

return iss, nil
}

func getClient() (kubernetes.Interface, error) {
//Get cluster config
confs, err := getInClusterConfig()
Expand Down
26 changes: 26 additions & 0 deletions translator/util/eksdetector/eksdetector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package eksdetector

import (
"encoding/base64"
"fmt"
"testing"

Expand Down Expand Up @@ -54,9 +55,17 @@ func TestEKS(t *testing.T) {
}

testDetector.On("getConfigMap", authConfigNamespace, authConfigConfigMap).Return(map[string]string{conventions.AttributeK8SClusterName: "my-cluster"}, nil)

isEks := IsEKS()
assert.True(t, isEks.Value)
assert.NoError(t, isEks.Err)

testDetector.On("getConfigMap", authConfigNamespace, authConfigConfigMap).Return(nil, fmt.Errorf("configmap not found"))
testDetector.On("getIssuer").Return("https://oidc.eks.us-west-2.amazonaws.com/id/someid", nil)

isEks = IsEKS()
assert.True(t, isEks.Value)
assert.NoError(t, isEks.Err)
}

func Test_getConfigMap(t *testing.T) {
Expand All @@ -82,6 +91,23 @@ func Test_getConfigMap(t *testing.T) {
assert.NotNil(t, res)
}

func Test_getIssuer(t *testing.T) {
client := fake.NewSimpleClientset()
testDetector := &EksDetector{Clientset: client}

payload := `{"iss":"https://oidc.eks.us-west-2.amazonaws.com/id/someid"}`
encodedPayload := base64.RawURLEncoding.EncodeToString([]byte(payload))
dummyToken := "header." + encodedPayload + ".signature"

getInClusterConfig = func() (*rest.Config, error) {
return &rest.Config{BearerToken: dummyToken}, nil
}

issuer, err := testDetector.getIssuer()
assert.NoError(t, err)
assert.Equal(t, "https://oidc.eks.us-west-2.amazonaws.com/id/someid", issuer)
}

func Test_getClientError(t *testing.T) {
//InClusterConfig error
getInClusterConfig = func() (*rest.Config, error) {
Expand Down
7 changes: 6 additions & 1 deletion translator/util/eksdetector/eksdetectortestutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ var (
return &EksDetector{Clientset: fake.NewSimpleClientset()}, nil
}

// TestIsEKSCacheEKS os used for unit testing EKS route
// TestIsEKSCacheEKS is used for unit testing EKS route
TestIsEKSCacheEKS = func() IsEKSCache {
return IsEKSCache{Value: true, Err: nil}
}
Expand All @@ -44,3 +44,8 @@ func (detector *MockDetector) getConfigMap(namespace string, name string) (map[s
args := detector.Called(namespace, name)
return args.Get(0).(map[string]string), args.Error(1)
}

func (detector *MockDetector) getIssuer() (string, error) {
args := detector.Called()
return args.Get(0).(string), args.Error(1)
}

0 comments on commit 799f0c3

Please sign in to comment.