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

Implements handling of insecure TLS connections in Mehkit #373

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c75d194
Implements handling of insecure TLS connections in Mehkit
yash37158 Sep 20, 2023
27ac06d
Merge branch 'master' into master
yash37158 Sep 25, 2023
3ea693d
Fixing go formating changes
yash37158 Sep 26, 2023
f0a66b1
Merge remote-tracking branch 'origin'
yash37158 Sep 26, 2023
2a49b89
Merge branch 'meshery:master' into master
yash37158 Sep 29, 2023
0380716
Fixing formatting errors
yash37158 Sep 29, 2023
3b8ed1c
Merge branch 'meshery:master' into master
yash37158 Oct 2, 2023
48fbcbf
fix: Fix format script
yash37158 Oct 2, 2023
3d84b71
Fixing nil pointer dereferences
yash37158 Oct 2, 2023
3b9eee7
Merge branch 'meshery:master' into master
yash37158 Oct 10, 2023
7ecfe12
Adding CertificateAuthorityData capabilities when flag is true
yash37158 Oct 10, 2023
50af4d7
Merge remote-tracking branch 'origin/master'
yash37158 Oct 10, 2023
a4485cf
fixing suggestion from muzair on adding events
yash37158 Oct 24, 2023
2ee76b0
Merge branch 'master' into master
yash37158 Oct 24, 2023
848bee4
Update utils/kubernetes/client.go
yash37158 Oct 26, 2023
9a613e7
Update utils/kubernetes/client.go
yash37158 Oct 26, 2023
d4522c1
Fixing indentation utils/kubernetes/client.go
yash37158 Oct 26, 2023
ba210fe
Fixing DCO changes
yash37158 Oct 27, 2023
3137d5b
Merge branch 'master' into master
yash37158 Oct 30, 2023
5427339
Accepting changes from Aisuko
yash37158 Nov 1, 2023
8827e75
Merge branch 'master' into master
yash37158 Nov 1, 2023
5c687da
Merge branch 'master' into master
yash37158 Nov 10, 2023
899223a
Removing logging of komposeObject
yash37158 Nov 10, 2023
634d994
Merge branch 'master' into master
yash37158 Nov 13, 2023
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
61 changes: 58 additions & 3 deletions utils/kubernetes/client.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
package kubernetes

import (
"fmt"
"log"
"os"
"path/filepath"

"github.com/layer5io/meshkit/models"
event "github.com/layer5io/meshkit/models/events"
"github.com/layer5io/meshkit/utils"
"github.com/layer5io/meshkit/utils/events"
"gopkg.in/yaml.v3"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
Expand All @@ -13,39 +19,63 @@ import (
// DetectKubeConfig detects the kubeconfig for the kubernetes cluster and returns it
func DetectKubeConfig(configfile []byte) (config *rest.Config, err error) {
if len(configfile) > 0 {
if err != nil {
return nil, err
}

models := &models.Kubeconfig{}
var cfgFile []byte

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

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

yash37158 marked this conversation as resolved.
Show resolved Hide resolved
config, err = processClustersAndConfig(models, cfgFile)
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
// Look for kubeconfig from the path mentioned in $KUBECONFIGZ
models := &models.Kubeconfig{}
var cfgFile []byte
kubeconfig := os.Getenv("KUBECONFIG")
if kubeconfig != "" {
if config, err = clientcmd.BuildConfigFromFlags("", kubeconfig); err == nil {

config, err = processClustersAndConfig(models, cfgFile)
return config, err

}
return
}

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

config, err = processClustersAndConfig(models, cfgFile)
return config, err
}

return
}

func publishEvent(event interface{}) {
eventStreamer := events.NewEventStreamer()
clientChannel := make(chan interface{})
eventStreamer.Subscribe(clientChannel)
eventStreamer.Publish(event)
}

func processConfig(configFile []byte) ([]byte, error) {
cfg, err := clientcmd.Load(configFile)
if err != nil {
Expand All @@ -69,3 +99,28 @@ func processConfig(configFile []byte) ([]byte, error) {

return clientcmd.Write(*cfg)
}

func processClustersAndConfig(models *models.Kubeconfig, cfgFile []byte) (*rest.Config, error) {
for _, clusters := range models.Clusters {
if config, err := clientcmd.RESTConfigFromKubeConfig(cfgFile); err == nil {
if insecureSkipTLSVerify := clusters.Cluster.InsecureSkipTLSVerify; insecureSkipTLSVerify != nil && *insecureSkipTLSVerify {
// Skip TLS verification if the field is set to true
config.TLSClientConfig.Insecure = *insecureSkipTLSVerify

clusters.Cluster.CertificateAuthorityData = ""

// Create an event to record the insecure connection
eventBuilder := event.NewEvent().WithCategory("connection").WithAction("insecure")
eventBuilder.WithSeverity(event.Warning).WithDescription("Insecure TLS connection to Kubernetes cluster detected")

// Publish the event directly using the events package
event := eventBuilder.Build()
publishEvent(event)

log.Println("SKIP TLS verification part was called")
}
return config, err
}
}
return nil, fmt.Errorf("unable to build Kubernetes configuration")
}
105 changes: 105 additions & 0 deletions utils/kubernetes/client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package kubernetes

import (
"fmt"
"testing"
)

func TestDetectKubeConfig(t *testing.T) {
yash37158 marked this conversation as resolved.
Show resolved Hide resolved
t.Parallel()
// Test case 1: Valid kubeconfig file with tls-skip-verify set to true
configfile := []byte(`
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: REDACTED
server: https://localhost:6443
insecure-skip-tls-verify: false
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
`)
config, err := DetectKubeConfig(configfile)
if err != nil {
t.Errorf("DetectKubeConfig() failed with error: %v", err)
}
if config == nil {
t.Errorf("DetectKubeConfig() returned nil config")
}
if config != nil && config.TLSClientConfig.CAData != nil {
fmt.Print("Test case 1: CertificateAuthorityData should be empty, but it's not")
}

// Test case 2: Valid kubeconfig file with tls-skip-verify set to false
configfile = []byte(`
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: REDACTED
server: https://localhost:6443
insecure-skip-tls-verify: false
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
`)
config, err = DetectKubeConfig(configfile)
if err != nil {
t.Errorf("DetectKubeConfig() failed with error: %v", err)
}
if config == nil {
t.Errorf("DetectKubeConfig() returned nil config")
}
if config != nil && config.TLSClientConfig.CAData == nil {
fmt.Print("Test case 2: CertificateAuthorityData should not be empty, but it is")
}

// Test case 3: Invalid kubeconfig file
configfile = []byte(`invalid kubeconfig`)
config, err = DetectKubeConfig(configfile)
if err == nil {
t.Errorf("DetectKubeConfig() did not return an error for invalid kubeconfig")
}
if config != nil {
t.Errorf("DetectKubeConfig() returned non-nil config for invalid kubeconfig")
}
if config != nil && config.TLSClientConfig.CAData != nil {
t.Errorf("Test case 3: CertificateAuthorityData should be empty, but it's not")
}
}

func TestPublishEventWithChannelLeak(t *testing.T) {
yash37158 marked this conversation as resolved.
Show resolved Hide resolved
t.Parallel()
// Simulate multiple subscribers
numSubscribers := 10
channels := make([]chan interface{}, numSubscribers)
for i := 0; i < numSubscribers; i++ {
channels[i] = make(chan interface{})
}

// Publish an event without closing the channels
event := "test event with channel leak"
publishEvent(event)

}
Loading