Skip to content
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

feat(operator): fetch cluster name from providers #1881

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 150 additions & 0 deletions pkg/KubeArmorOperator/internal/controller/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import (
"bytes"
"context"
"fmt"
"io"
"net/http"
"regexp"
"strings"
"time"

Expand Down Expand Up @@ -469,6 +472,152 @@ func (clusterWatcher *ClusterWatcher) deployControllerDeployment(deployment *app
return nil
}

func (clusterWatcher *ClusterWatcher) getProvider() string {
nodes, err := clusterWatcher.Client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
if err != nil {
clusterWatcher.Log.Warnf("Error listing nodes: %s\n", err.Error())
}

for _, node := range nodes.Items {
for key, label := range node.Labels {
if strings.Contains(key, "gke") || strings.Contains(label, "gke") {
return "gke"
} else if strings.Contains(key, "eks") || strings.Contains(label, "eks") {
return "eks"
} else if strings.Contains(key, "aks") || strings.Contains(label, "aks") {
return "aks"
}
}
}
return "default"
}

func (clusterWatcher *ClusterWatcher) fetchClusterNameFromGoogle() (string, error) {
url := "http://metadata.google.internal/computeMetadata/v1/instance/attributes/cluster-name"
req, err := http.NewRequest("GET", url, nil)
if err != nil {
clusterWatcher.Log.Warnf("failed to create request: %w", err)
return "", err
}

// Set the required header
req.Header.Set("Metadata-Flavor", "Google")

// Create an HTTP client and make the request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
clusterWatcher.Log.Warnf("error making request: %w", err)
return "", err
}
defer resp.Body.Close()

// Check for a successful response
if resp.StatusCode != http.StatusOK {
clusterWatcher.Log.Warnf("failed to fetch from metadata, status code: %d", resp.StatusCode)
return "", err
}

// Read the response body
body, err := io.ReadAll(resp.Body)
if err != nil {
clusterWatcher.Log.Warnf("error reading response body: %w", err)
return "", err
}

return string(body), nil
}

func (clusterWatcher *ClusterWatcher) fetchClusterNameFromAWS() (string, error) {
var token []byte
client := &http.Client{Timeout: 2 * time.Second}
req, err := http.NewRequest("PUT", "http://169.254.169.254/latest/api/token", nil)
if err != nil {
clusterWatcher.Log.Warnf("failed to create request for fetching token: %w", err)
return "", err
}
req.Header.Set("X-aws-ec2-metadata-token-ttl-seconds", "21600")

resp, err := client.Do(req)
if err != nil {
clusterWatcher.Log.Warnf("error making request: %w", err)
return "", err
}
defer resp.Body.Close()

if resp.StatusCode == http.StatusOK {
token, err = io.ReadAll(resp.Body)
if err != nil {
clusterWatcher.Log.Warnf("failed to read token: %d", err)
return "", err
}
}

// Fetch the EKS cluster name from user data
req, err = http.NewRequest("GET", "http://169.254.169.254/latest/user-data", nil)
client = &http.Client{Timeout: 2 * time.Second}
if err != nil {
clusterWatcher.Log.Warnf("failed to create request for fetching metadata: %w", err)
return "", err
}
req.Header.Set("X-aws-ec2-metadata-token", string(token))

resp, err = client.Do(req)
if err != nil {
clusterWatcher.Log.Warnf("error making request: %w", err)
return "", err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
clusterWatcher.Log.Warnf("failed to fetch from metadata, status code: %d", resp.StatusCode)
return "", err
}

body, err := io.ReadAll(resp.Body)
if err != nil {
clusterWatcher.Log.Warnf("failed to read metadata: %d", err)
return "", err
}

// Extract EKS cluster name
re := regexp.MustCompile(`/etc/eks/bootstrap\.sh (\S+)`)
match := re.FindStringSubmatch(string(body))
if len(match) > 0 {
return match[1], nil
}

return "", err
}

func (clusterWatcher *ClusterWatcher) getClusterName() string {
provider := clusterWatcher.getProvider()
if provider == "gke" {
clusterWatcher.Log.Infof("Provider is GKE")
if clusterName, err := clusterWatcher.fetchClusterNameFromGoogle(); err != nil {
clusterWatcher.Log.Warnf("Cannot fetch cluster name for GKE %s", err.Error())
} else {
return clusterName
}
} else if provider == "eks" {
clusterWatcher.Log.Infof("Provider is EKS")
if clusterName, err := clusterWatcher.fetchClusterNameFromAWS(); err != nil {
clusterWatcher.Log.Warnf("Cannot fetch cluster name for EKS %s", err.Error())
} else {
return clusterName
}
}
// } else if provider == "aks" {
rootxrishabh marked this conversation as resolved.
Show resolved Hide resolved
// if clusterName, err := fetchClusterNameFromAzure(); err != nil {
// clusterWatcher.Log.Warnf("Cannot fetch cluster name %s, err.Error()")
// } else {
// return clusterName
// }
// }

return "default"
}

func (clusterWatcher *ClusterWatcher) WatchRequiredResources() {
var caCert, tlsCrt, tlsKey *bytes.Buffer
var kGenErr, err, installErr error
Expand Down Expand Up @@ -564,6 +713,7 @@ func (clusterWatcher *ClusterWatcher) WatchRequiredResources() {
// kubearmor configmap
configmap := addOwnership(deployments.GetKubearmorConfigMap(common.Namespace, deployments.KubeArmorConfigMapName)).(*corev1.ConfigMap)
configmap.Data = common.ConfigMapData
configmap.Data["cluster"] = clusterWatcher.getClusterName()

for {
caCert, tlsCrt, tlsKey, kGenErr = common.GeneratePki(common.Namespace, deployments.KubeArmorControllerWebhookServiceName)
Expand Down
Loading