Skip to content

Commit 77e2fca

Browse files
committed
Add new unit tests to check the values in Derived config
1 parent 00e4f18 commit 77e2fca

File tree

1 file changed

+215
-0
lines changed

1 file changed

+215
-0
lines changed

pkg/kubernetes/kubernetes_test.go

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
package kubernetes
2+
3+
import (
4+
"context"
5+
"os"
6+
"path"
7+
"testing"
8+
9+
"github.com/manusa/kubernetes-mcp-server/pkg/config"
10+
)
11+
12+
func TestManager_Derived(t *testing.T) {
13+
// Create a temporary kubeconfig file for testing
14+
tempDir := t.TempDir()
15+
kubeconfigPath := path.Join(tempDir, "config")
16+
kubeconfigContent := `
17+
apiVersion: v1
18+
kind: Config
19+
clusters:
20+
- cluster:
21+
server: https://test-cluster.example.com
22+
name: test-cluster
23+
contexts:
24+
- context:
25+
cluster: test-cluster
26+
user: test-user
27+
name: test-context
28+
current-context: test-context
29+
users:
30+
- name: test-user
31+
user:
32+
username: test-username
33+
password: test-password
34+
`
35+
if err := os.WriteFile(kubeconfigPath, []byte(kubeconfigContent), 0644); err != nil {
36+
t.Fatalf("failed to create kubeconfig file: %v", err)
37+
}
38+
39+
t.Run("without authorization header returns original manager", func(t *testing.T) {
40+
testStaticConfig := &config.StaticConfig{
41+
KubeConfig: kubeconfigPath,
42+
DisabledTools: []string{"configuration_view"},
43+
DeniedResources: []config.GroupVersionKind{
44+
{Group: "apps", Version: "v1", Kind: "Deployment"},
45+
},
46+
}
47+
48+
testManager, err := NewManager(kubeconfigPath, testStaticConfig)
49+
if err != nil {
50+
t.Fatalf("failed to create manager: %v", err)
51+
}
52+
defer testManager.Close()
53+
ctx := context.Background()
54+
derived := testManager.Derived(ctx)
55+
56+
if derived.manager != testManager {
57+
t.Errorf("expected original manager, got different manager")
58+
}
59+
})
60+
61+
t.Run("with invalid authorization header returns original manager", func(t *testing.T) {
62+
testStaticConfig := &config.StaticConfig{
63+
KubeConfig: kubeconfigPath,
64+
DisabledTools: []string{"configuration_view"},
65+
DeniedResources: []config.GroupVersionKind{
66+
{Group: "apps", Version: "v1", Kind: "Deployment"},
67+
},
68+
}
69+
70+
testManager, err := NewManager(kubeconfigPath, testStaticConfig)
71+
if err != nil {
72+
t.Fatalf("failed to create manager: %v", err)
73+
}
74+
defer testManager.Close()
75+
ctx := context.WithValue(context.Background(), OAuthAuthorizationHeader, "invalid-token")
76+
derived := testManager.Derived(ctx)
77+
78+
if derived.manager != testManager {
79+
t.Errorf("expected original manager, got different manager")
80+
}
81+
})
82+
83+
t.Run("with valid bearer token creates derived manager with correct configuration", func(t *testing.T) {
84+
testStaticConfig := &config.StaticConfig{
85+
KubeConfig: kubeconfigPath,
86+
DisabledTools: []string{"configuration_view"},
87+
DeniedResources: []config.GroupVersionKind{
88+
{Group: "apps", Version: "v1", Kind: "Deployment"},
89+
},
90+
}
91+
92+
testManager, err := NewManager(kubeconfigPath, testStaticConfig)
93+
if err != nil {
94+
t.Fatalf("failed to create manager: %v", err)
95+
}
96+
defer testManager.Close()
97+
testBearerToken := "test-bearer-token-123"
98+
ctx := context.WithValue(context.Background(), OAuthAuthorizationHeader, "Bearer "+testBearerToken)
99+
derived := testManager.Derived(ctx)
100+
101+
if derived.manager == testManager {
102+
t.Errorf("expected new derived manager, got original manager")
103+
}
104+
105+
if derived.manager.staticConfig != testStaticConfig {
106+
t.Errorf("staticConfig not properly wired to derived manager")
107+
}
108+
109+
if derived.manager.Kubeconfig != testManager.Kubeconfig {
110+
t.Errorf("expected Kubeconfig %s, got %s", testManager.Kubeconfig, derived.manager.Kubeconfig)
111+
}
112+
113+
derivedCfg := derived.manager.cfg
114+
if derivedCfg == nil {
115+
t.Fatalf("derived config is nil")
116+
}
117+
118+
originalCfg := testManager.cfg
119+
if derivedCfg.Host != originalCfg.Host {
120+
t.Errorf("expected Host %s, got %s", originalCfg.Host, derivedCfg.Host)
121+
}
122+
if derivedCfg.APIPath != originalCfg.APIPath {
123+
t.Errorf("expected APIPath %s, got %s", originalCfg.APIPath, derivedCfg.APIPath)
124+
}
125+
if derivedCfg.QPS != originalCfg.QPS {
126+
t.Errorf("expected QPS %f, got %f", originalCfg.QPS, derivedCfg.QPS)
127+
}
128+
if derivedCfg.Burst != originalCfg.Burst {
129+
t.Errorf("expected Burst %d, got %d", originalCfg.Burst, derivedCfg.Burst)
130+
}
131+
if derivedCfg.Timeout != originalCfg.Timeout {
132+
t.Errorf("expected Timeout %v, got %v", originalCfg.Timeout, derivedCfg.Timeout)
133+
}
134+
135+
if derivedCfg.TLSClientConfig.Insecure != originalCfg.TLSClientConfig.Insecure {
136+
t.Errorf("expected TLS Insecure %v, got %v", originalCfg.TLSClientConfig.Insecure, derivedCfg.TLSClientConfig.Insecure)
137+
}
138+
if derivedCfg.TLSClientConfig.ServerName != originalCfg.TLSClientConfig.ServerName {
139+
t.Errorf("expected TLS ServerName %s, got %s", originalCfg.TLSClientConfig.ServerName, derivedCfg.TLSClientConfig.ServerName)
140+
}
141+
if derivedCfg.TLSClientConfig.CAFile != originalCfg.TLSClientConfig.CAFile {
142+
t.Errorf("expected TLS CAFile %s, got %s", originalCfg.TLSClientConfig.CAFile, derivedCfg.TLSClientConfig.CAFile)
143+
}
144+
if string(derivedCfg.TLSClientConfig.CAData) != string(originalCfg.TLSClientConfig.CAData) {
145+
t.Errorf("expected TLS CAData %s, got %s", string(originalCfg.TLSClientConfig.CAData), string(derivedCfg.TLSClientConfig.CAData))
146+
}
147+
148+
if derivedCfg.BearerToken != testBearerToken {
149+
t.Errorf("expected BearerToken %s, got %s", testBearerToken, derivedCfg.BearerToken)
150+
}
151+
if derivedCfg.UserAgent != CustomUserAgent {
152+
t.Errorf("expected UserAgent %s, got %s", CustomUserAgent, derivedCfg.UserAgent)
153+
}
154+
155+
// Verify that sensitive fields are NOT copied to prevent credential leakage
156+
// The derived config should only use the bearer token from the Authorization header
157+
// and not inherit any authentication credentials from the original kubeconfig
158+
if derivedCfg.TLSClientConfig.CertFile != "" {
159+
t.Errorf("expected TLS CertFile to be empty, got %s", derivedCfg.TLSClientConfig.CertFile)
160+
}
161+
if derivedCfg.TLSClientConfig.KeyFile != "" {
162+
t.Errorf("expected TLS KeyFile to be empty, got %s", derivedCfg.TLSClientConfig.KeyFile)
163+
}
164+
if len(derivedCfg.TLSClientConfig.CertData) != 0 {
165+
t.Errorf("expected TLS CertData to be empty, got %v", derivedCfg.TLSClientConfig.CertData)
166+
}
167+
if len(derivedCfg.TLSClientConfig.KeyData) != 0 {
168+
t.Errorf("expected TLS KeyData to be empty, got %v", derivedCfg.TLSClientConfig.KeyData)
169+
}
170+
171+
if derivedCfg.Username != "" {
172+
t.Errorf("expected Username to be empty, got %s", derivedCfg.Username)
173+
}
174+
if derivedCfg.Password != "" {
175+
t.Errorf("expected Password to be empty, got %s", derivedCfg.Password)
176+
}
177+
if derivedCfg.AuthProvider != nil {
178+
t.Errorf("expected AuthProvider to be nil, got %v", derivedCfg.AuthProvider)
179+
}
180+
if derivedCfg.ExecProvider != nil {
181+
t.Errorf("expected ExecProvider to be nil, got %v", derivedCfg.ExecProvider)
182+
}
183+
if derivedCfg.BearerTokenFile != "" {
184+
t.Errorf("expected BearerTokenFile to be empty, got %s", derivedCfg.BearerTokenFile)
185+
}
186+
if derivedCfg.Impersonate.UserName != "" {
187+
t.Errorf("expected Impersonate.UserName to be empty, got %s", derivedCfg.Impersonate.UserName)
188+
}
189+
190+
// Verify that the original manager still has the sensitive data
191+
if originalCfg.Username == "" && originalCfg.Password == "" {
192+
t.Logf("original kubeconfig shouldn't be modified")
193+
}
194+
195+
// Verify that the derived manager has proper clients initialized
196+
if derived.manager.accessControlClientSet != nil {
197+
t.Error("expected accessControlClientSet to be initialized")
198+
}
199+
if derived.manager.accessControlClientSet.staticConfig != testStaticConfig {
200+
t.Errorf("staticConfig not properly wired to derived manager")
201+
}
202+
if derived.manager.discoveryClient == nil {
203+
t.Error("expected discoveryClient to be initialized")
204+
}
205+
if derived.manager.accessControlRESTMapper == nil {
206+
t.Error("expected accessControlRESTMapper to be initialized")
207+
}
208+
if derived.manager.accessControlRESTMapper.staticConfig != testStaticConfig {
209+
t.Errorf("staticConfig not properly wired to derived manager")
210+
}
211+
if derived.manager.dynamicClient == nil {
212+
t.Error("expected dynamicClient to be initialized")
213+
}
214+
})
215+
}

0 commit comments

Comments
 (0)