Skip to content

Commit

Permalink
Implements handling of insecure TLS connections in Mehkit
Browse files Browse the repository at this point in the history
Signed-off-by: yash37158 <[email protected]>
  • Loading branch information
yash37158 committed Sep 20, 2023
1 parent a11ed83 commit c75d194
Show file tree
Hide file tree
Showing 2 changed files with 277 additions and 59 deletions.
210 changes: 151 additions & 59 deletions utils/kubernetes/client.go
Original file line number Diff line number Diff line change
@@ -1,70 +1,162 @@
package kubernetes

import (
"os"
"path/filepath"
"os"
"path/filepath"

"github.com/layer5io/meshkit/models"
"gopkg.in/yaml.v2"
"github.com/layer5io/meshkit/utils"
events "github.com/layer5io/meshkit/utils/events"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"log"

"github.com/layer5io/meshkit/utils"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
)

// CustomEvent is a custom event type for recording events.
type CustomEvent struct {
EventType string
Level string
Message string
}

// DetectKubeConfig detects the kubeconfig for the kubernetes cluster and returns it
func DetectKubeConfig(configfile []byte) (config *rest.Config, err error) {
if len(configfile) > 0 {
cfgFile, err := processConfig(configfile)
if err != nil {
return nil, err
}

if config, err = clientcmd.RESTConfigFromKubeConfig(cfgFile); err == nil {
return config, err
}
}

// If deployed within the cluster
if config, err = rest.InClusterConfig(); err == nil {
return config, err
}

// Look for kubeconfig from the path mentioned in $KUBECONFIG
kubeconfig := os.Getenv("KUBECONFIG")
if kubeconfig != "" {
if config, err = clientcmd.BuildConfigFromFlags("", kubeconfig); err == nil {
return config, err
}
}

// Look for kubeconfig at the default path
path := filepath.Join(utils.GetHome(), ".kube", "config")
if config, err = clientcmd.BuildConfigFromFlags("", path); err == nil {
return config, err
}

return
if len(configfile) > 0 {
cfgFile, err := processConfig(configfile)
if err != nil {
return nil, err
}

models := &models.Kubeconfig{}

cfgFile, err = processConfig(configfile)
if err != nil {
return nil, err
}

if err := yaml.Unmarshal(cfgFile, models); err != nil {
return nil, err
}

for _, clusters := range models.Clusters {
if config, err = clientcmd.RESTConfigFromKubeConfig(cfgFile); err == nil {
// Check the `InsecureSkipTLSVerify` field
if insecureSkipTLSVerify := clusters.Cluster.InsecureSkipTLSVerify; insecureSkipTLSVerify != nil && *insecureSkipTLSVerify {
// Skip TLS verification if the field is set to true
config.TLSClientConfig.Insecure = *insecureSkipTLSVerify

// Create an event to record the insecure connection
event := CustomEvent{
EventType: "Warning",
Level: "Warning",
Message: "Insecure connection to Kubernetes cluster detected",
}

log.Println("SKIP TLS verification part was called")


// Send the event to the client
handleCustomEvent(event)

}

return config, err
}
}
}

// If deployed within the cluster
if config, err = rest.InClusterConfig(); err == nil {
return config, err
}

// Look for kubeconfig from the path mentioned in $KUBECONFIGZ
var models models.Kubeconfig
kubeconfig := os.Getenv("KUBECONFIG")
if kubeconfig != "" {
if config, err = clientcmd.BuildConfigFromFlags("", kubeconfig); err == nil {
for _, cluster := range models.Clusters {
if cluster.Cluster.InsecureSkipTLSVerify != nil {
// Skip TLS verification for this cluster
config.TLSClientConfig.Insecure = true

// Create an event to record the insecure connection
event := CustomEvent{
EventType: "Warning",
Level: "Warning",
Message: "Insecure connection to Kubernetes cluster detected",
}
log.Println("SKIP TLS verification part was called")

handleCustomEvent(event)
}
}

return config, err
}
}

// Look for kubeconfig at the default path
path := filepath.Join(utils.GetHome(), ".kube", "config")
if config, err = clientcmd.BuildConfigFromFlags("", path); err == nil {
for _, cluster := range models.Clusters {
if cluster.Cluster.InsecureSkipTLSVerify != nil {
// Skip TLS verification for this cluster
config.TLSClientConfig.Insecure = true

// Create an event to record the insecure connection
event := CustomEvent{
EventType: "Warning",
Level: "Warning",
Message: "Insecure connection to Kubernetes cluster detected",
}
log.Println("SKIP TLS verification part was called")

handleCustomEvent(event)
}
}
return config, err
}

return
}

func processConfig(configFile []byte) ([]byte, error) {
cfg, err := clientcmd.Load(configFile)
if err != nil {
return nil, ErrLoadConfig(err)
}

err = clientcmdapi.MinifyConfig(cfg)
if err != nil {
return nil, ErrValidateConfig(err)
}

err = clientcmdapi.FlattenConfig(cfg)
if err != nil {
return nil, ErrValidateConfig(err)
}

err = clientcmd.Validate(*cfg)
if err != nil {
return nil, ErrValidateConfig(err)
}

return clientcmd.Write(*cfg)
func handleCustomEvent(event CustomEvent) {

eventStreamer := events.NewEventStreamer()

clientChannel := make(chan interface{})
eventStreamer.Subscribe(clientChannel)
eventStreamer.Publish(event)

// log.Printf("%s: %s", event.EventType, event.Message)

}


func processConfig(configFile []byte) ([]byte, error) {
cfg, err := clientcmd.Load(configFile)
if err != nil {
return nil, ErrLoadConfig(err)
}

err = clientcmdapi.MinifyConfig(cfg)
if err != nil {
return nil, ErrValidateConfig(err)
}

err = clientcmdapi.FlattenConfig(cfg)
if err != nil {
return nil, ErrValidateConfig(err)
}

err = clientcmd.Validate(*cfg)
if err != nil {
return nil, ErrValidateConfig(err)
}

return clientcmd.Write(*cfg)
}
126 changes: 126 additions & 0 deletions utils/kubernetes/client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package kubernetes

import (
"fmt"
"testing"
)

func TestDetectKubeConfig(t *testing.T) {
// Test case 1: Insecure TLS verification for context1
testKubeConfig1 := []byte(`
apiVersion: v1
clusters:
- name: cluster1
cluster:
server: https://localhost:9443
insecure-skip-tls-verify: true
contexts:
- context:
cluster: cluster1
user: user1
name: context1
current-context: context1
kind: Config
preferences: {}
users:
- name: user1
user:
`)
config1, err1 := DetectKubeConfig(testKubeConfig1)
if err1 != nil {
t.Errorf("Test case 1: Error while detecting kubeconfig: %v", err1)
}
if config1 == nil {
t.Errorf("Test case 1: Config should not be nil")
}
if !config1.TLSClientConfig.Insecure {
t.Errorf("Test case 1: TLS verification should be skipped, but it's not")
}

// Test case 2: Secure TLS verification for context2
testKubeConfig2 := []byte(`
apiVersion: v1
clusters:
- name: cluster2
cluster:
server: https://localhost:9443
insecure-skip-tls-verify: false
contexts:
- context:
cluster: cluster2
user: user2
name: context2
current-context: context2
kind: Config
preferences: {}
users:
- name: user2
user:
`)
config2, err2 := DetectKubeConfig(testKubeConfig2)
if err2 != nil {
t.Errorf("Test case 2: Error while detecting kubeconfig: %v", err2)
}
if config2 == nil {
t.Errorf("Test case 2: Config should not be nil")
}
if config2.TLSClientConfig.Insecure {
t.Errorf("Test case 2: TLS verification should not be skipped, but it is")
}

// Test case 3: Multi-context kubeconfig with mixed TLS settings
testKubeConfig3 := []byte(`
apiVersion: v1
clusters:
- name: cluster1
cluster:
server: https://localhost:9443
insecure-skip-tls-verify: true
- name: cluster2
cluster:
server: https://localhost:9443
insecure-skip-tls-verify: false
contexts:
- context:
cluster: cluster1
user: user1
name: context1
- context:
cluster: cluster2
user: user2
name: context2
current-context: context1
kind: Config
preferences: {}
users:
- name: user1
user:
- name: user2
user:
`)
config3, err3 := DetectKubeConfig(testKubeConfig3)
if err3 != nil {
t.Errorf("Test case 3: Error while detecting kubeconfig: %v", err3)
}
if config3 == nil {
t.Errorf("Test case 3: Config should not be nil")
}
if !config3.TLSClientConfig.Insecure {
t.Errorf("Test case 3: TLS verification should be skipped, but it's not")
}

event := CustomEvent{
EventType: "Warning",
Level: "Warning",
Message: "Insecure connection to Kubernetes cluster detected",
}

handleCustomEvent(event)


// Print whether TLS verification is skipped or not for each test case
fmt.Printf("Test case 1: TLS verification is skipped (Insecure: %v)\n", config1.TLSClientConfig.Insecure)
fmt.Printf("Test case 2: TLS verification is not skipped (Insecure: %v)\n", config2.TLSClientConfig.Insecure)
fmt.Printf("Test case 3: TLS verification is skipped (Insecure: %v)\n", config3.TLSClientConfig.Insecure)

}

0 comments on commit c75d194

Please sign in to comment.