1/*
2Copyright 2015 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package api
18
19import (
20	"fmt"
21	"io/ioutil"
22	"os"
23	"reflect"
24	"testing"
25
26	"sigs.k8s.io/yaml"
27)
28
29func newMergedConfig(certFile, certContent, keyFile, keyContent, caFile, caContent string, t *testing.T) Config {
30	if err := ioutil.WriteFile(certFile, []byte(certContent), 0644); err != nil {
31		t.Errorf("unexpected error: %v", err)
32	}
33	if err := ioutil.WriteFile(keyFile, []byte(keyContent), 0600); err != nil {
34		t.Errorf("unexpected error: %v", err)
35	}
36	if err := ioutil.WriteFile(caFile, []byte(caContent), 0644); err != nil {
37		t.Errorf("unexpected error: %v", err)
38	}
39
40	return Config{
41		AuthInfos: map[string]*AuthInfo{
42			"red-user":  {Token: "red-token", ClientCertificateData: []byte(certContent), ClientKeyData: []byte(keyContent)},
43			"blue-user": {Token: "blue-token", ClientCertificate: certFile, ClientKey: keyFile}},
44		Clusters: map[string]*Cluster{
45			"cow-cluster":     {Server: "http://cow.org:8080", CertificateAuthorityData: []byte(caContent)},
46			"chicken-cluster": {Server: "http://chicken.org:8080", CertificateAuthority: caFile}},
47		Contexts: map[string]*Context{
48			"federal-context": {AuthInfo: "red-user", Cluster: "cow-cluster"},
49			"shaker-context":  {AuthInfo: "blue-user", Cluster: "chicken-cluster"}},
50		CurrentContext: "federal-context",
51	}
52}
53
54func TestMinifySuccess(t *testing.T) {
55	certFile, _ := ioutil.TempFile("", "")
56	defer os.Remove(certFile.Name())
57	keyFile, _ := ioutil.TempFile("", "")
58	defer os.Remove(keyFile.Name())
59	caFile, _ := ioutil.TempFile("", "")
60	defer os.Remove(caFile.Name())
61
62	mutatingConfig := newMergedConfig(certFile.Name(), "cert", keyFile.Name(), "key", caFile.Name(), "ca", t)
63
64	if err := MinifyConfig(&mutatingConfig); err != nil {
65		t.Errorf("unexpected error: %v", err)
66	}
67
68	if len(mutatingConfig.Contexts) > 1 {
69		t.Errorf("unexpected contexts: %v", mutatingConfig.Contexts)
70	}
71	if _, exists := mutatingConfig.Contexts["federal-context"]; !exists {
72		t.Errorf("missing context")
73	}
74
75	if len(mutatingConfig.Clusters) > 1 {
76		t.Errorf("unexpected clusters: %v", mutatingConfig.Clusters)
77	}
78	if _, exists := mutatingConfig.Clusters["cow-cluster"]; !exists {
79		t.Errorf("missing cluster")
80	}
81
82	if len(mutatingConfig.AuthInfos) > 1 {
83		t.Errorf("unexpected users: %v", mutatingConfig.AuthInfos)
84	}
85	if _, exists := mutatingConfig.AuthInfos["red-user"]; !exists {
86		t.Errorf("missing user")
87	}
88}
89
90func TestMinifyMissingContext(t *testing.T) {
91	certFile, _ := ioutil.TempFile("", "")
92	defer os.Remove(certFile.Name())
93	keyFile, _ := ioutil.TempFile("", "")
94	defer os.Remove(keyFile.Name())
95	caFile, _ := ioutil.TempFile("", "")
96	defer os.Remove(caFile.Name())
97
98	mutatingConfig := newMergedConfig(certFile.Name(), "cert", keyFile.Name(), "key", caFile.Name(), "ca", t)
99	mutatingConfig.CurrentContext = "missing"
100
101	errMsg := "cannot locate context missing"
102
103	if err := MinifyConfig(&mutatingConfig); err == nil || err.Error() != errMsg {
104		t.Errorf("expected %v, got %v", errMsg, err)
105	}
106}
107
108func TestMinifyMissingCluster(t *testing.T) {
109	certFile, _ := ioutil.TempFile("", "")
110	defer os.Remove(certFile.Name())
111	keyFile, _ := ioutil.TempFile("", "")
112	defer os.Remove(keyFile.Name())
113	caFile, _ := ioutil.TempFile("", "")
114	defer os.Remove(caFile.Name())
115
116	mutatingConfig := newMergedConfig(certFile.Name(), "cert", keyFile.Name(), "key", caFile.Name(), "ca", t)
117	delete(mutatingConfig.Clusters, mutatingConfig.Contexts[mutatingConfig.CurrentContext].Cluster)
118
119	errMsg := "cannot locate cluster cow-cluster"
120
121	if err := MinifyConfig(&mutatingConfig); err == nil || err.Error() != errMsg {
122		t.Errorf("expected %v, got %v", errMsg, err)
123	}
124}
125
126func TestMinifyMissingAuthInfo(t *testing.T) {
127	certFile, _ := ioutil.TempFile("", "")
128	defer os.Remove(certFile.Name())
129	keyFile, _ := ioutil.TempFile("", "")
130	defer os.Remove(keyFile.Name())
131	caFile, _ := ioutil.TempFile("", "")
132	defer os.Remove(caFile.Name())
133
134	mutatingConfig := newMergedConfig(certFile.Name(), "cert", keyFile.Name(), "key", caFile.Name(), "ca", t)
135	delete(mutatingConfig.AuthInfos, mutatingConfig.Contexts[mutatingConfig.CurrentContext].AuthInfo)
136
137	errMsg := "cannot locate user red-user"
138
139	if err := MinifyConfig(&mutatingConfig); err == nil || err.Error() != errMsg {
140		t.Errorf("expected %v, got %v", errMsg, err)
141	}
142}
143
144func TestFlattenSuccess(t *testing.T) {
145	certFile, _ := ioutil.TempFile("", "")
146	defer os.Remove(certFile.Name())
147	keyFile, _ := ioutil.TempFile("", "")
148	defer os.Remove(keyFile.Name())
149	caFile, _ := ioutil.TempFile("", "")
150	defer os.Remove(caFile.Name())
151
152	certData := "cert"
153	keyData := "key"
154	caData := "ca"
155
156	unchangingCluster := "cow-cluster"
157	unchangingAuthInfo := "red-user"
158	changingCluster := "chicken-cluster"
159	changingAuthInfo := "blue-user"
160
161	startingConfig := newMergedConfig(certFile.Name(), certData, keyFile.Name(), keyData, caFile.Name(), caData, t)
162	mutatingConfig := startingConfig
163
164	if err := FlattenConfig(&mutatingConfig); err != nil {
165		t.Errorf("unexpected error: %v", err)
166	}
167
168	if len(mutatingConfig.Contexts) != 2 {
169		t.Errorf("unexpected contexts: %v", mutatingConfig.Contexts)
170	}
171	if !reflect.DeepEqual(startingConfig.Contexts, mutatingConfig.Contexts) {
172		t.Errorf("expected %v, got %v", startingConfig.Contexts, mutatingConfig.Contexts)
173	}
174
175	if len(mutatingConfig.Clusters) != 2 {
176		t.Errorf("unexpected clusters: %v", mutatingConfig.Clusters)
177	}
178	if !reflect.DeepEqual(startingConfig.Clusters[unchangingCluster], mutatingConfig.Clusters[unchangingCluster]) {
179		t.Errorf("expected %v, got %v", startingConfig.Clusters[unchangingCluster], mutatingConfig.Clusters[unchangingCluster])
180	}
181	if len(mutatingConfig.Clusters[changingCluster].CertificateAuthority) != 0 {
182		t.Errorf("unexpected caFile")
183	}
184	if string(mutatingConfig.Clusters[changingCluster].CertificateAuthorityData) != caData {
185		t.Errorf("expected %v, got %v", caData, string(mutatingConfig.Clusters[changingCluster].CertificateAuthorityData))
186	}
187
188	if len(mutatingConfig.AuthInfos) != 2 {
189		t.Errorf("unexpected users: %v", mutatingConfig.AuthInfos)
190	}
191	if !reflect.DeepEqual(startingConfig.AuthInfos[unchangingAuthInfo], mutatingConfig.AuthInfos[unchangingAuthInfo]) {
192		t.Errorf("expected %v, got %v", startingConfig.AuthInfos[unchangingAuthInfo], mutatingConfig.AuthInfos[unchangingAuthInfo])
193	}
194	if len(mutatingConfig.AuthInfos[changingAuthInfo].ClientCertificate) != 0 {
195		t.Errorf("unexpected caFile")
196	}
197	if string(mutatingConfig.AuthInfos[changingAuthInfo].ClientCertificateData) != certData {
198		t.Errorf("expected %v, got %v", certData, string(mutatingConfig.AuthInfos[changingAuthInfo].ClientCertificateData))
199	}
200	if len(mutatingConfig.AuthInfos[changingAuthInfo].ClientKey) != 0 {
201		t.Errorf("unexpected caFile")
202	}
203	if string(mutatingConfig.AuthInfos[changingAuthInfo].ClientKeyData) != keyData {
204		t.Errorf("expected %v, got %v", keyData, string(mutatingConfig.AuthInfos[changingAuthInfo].ClientKeyData))
205	}
206
207}
208
209func Example_minifyAndShorten() {
210	certFile, _ := ioutil.TempFile("", "")
211	defer os.Remove(certFile.Name())
212	keyFile, _ := ioutil.TempFile("", "")
213	defer os.Remove(keyFile.Name())
214	caFile, _ := ioutil.TempFile("", "")
215	defer os.Remove(caFile.Name())
216
217	certData := "cert"
218	keyData := "key"
219	caData := "ca"
220
221	config := newMergedConfig(certFile.Name(), certData, keyFile.Name(), keyData, caFile.Name(), caData, nil)
222
223	MinifyConfig(&config)
224	ShortenConfig(&config)
225
226	output, _ := yaml.Marshal(config)
227	fmt.Printf("%s", string(output))
228	// Output:
229	// clusters:
230	//   cow-cluster:
231	//     LocationOfOrigin: ""
232	//     certificate-authority-data: DATA+OMITTED
233	//     server: http://cow.org:8080
234	// contexts:
235	//   federal-context:
236	//     LocationOfOrigin: ""
237	//     cluster: cow-cluster
238	//     user: red-user
239	// current-context: federal-context
240	// preferences: {}
241	// users:
242	//   red-user:
243	//     LocationOfOrigin: ""
244	//     client-certificate-data: REDACTED
245	//     client-key-data: REDACTED
246	//     token: red-token
247}
248
249func TestShortenSuccess(t *testing.T) {
250	certFile, _ := ioutil.TempFile("", "")
251	defer os.Remove(certFile.Name())
252	keyFile, _ := ioutil.TempFile("", "")
253	defer os.Remove(keyFile.Name())
254	caFile, _ := ioutil.TempFile("", "")
255	defer os.Remove(caFile.Name())
256
257	certData := "cert"
258	keyData := "key"
259	caData := "ca"
260
261	unchangingCluster := "chicken-cluster"
262	unchangingAuthInfo := "blue-user"
263	changingCluster := "cow-cluster"
264	changingAuthInfo := "red-user"
265
266	startingConfig := newMergedConfig(certFile.Name(), certData, keyFile.Name(), keyData, caFile.Name(), caData, t)
267	mutatingConfig := startingConfig
268
269	ShortenConfig(&mutatingConfig)
270
271	if len(mutatingConfig.Contexts) != 2 {
272		t.Errorf("unexpected contexts: %v", mutatingConfig.Contexts)
273	}
274	if !reflect.DeepEqual(startingConfig.Contexts, mutatingConfig.Contexts) {
275		t.Errorf("expected %v, got %v", startingConfig.Contexts, mutatingConfig.Contexts)
276	}
277
278	redacted := string(redactedBytes)
279	dataOmitted := string(dataOmittedBytes)
280	if len(mutatingConfig.Clusters) != 2 {
281		t.Errorf("unexpected clusters: %v", mutatingConfig.Clusters)
282	}
283	if !reflect.DeepEqual(startingConfig.Clusters[unchangingCluster], mutatingConfig.Clusters[unchangingCluster]) {
284		t.Errorf("expected %v, got %v", startingConfig.Clusters[unchangingCluster], mutatingConfig.Clusters[unchangingCluster])
285	}
286	if string(mutatingConfig.Clusters[changingCluster].CertificateAuthorityData) != dataOmitted {
287		t.Errorf("expected %v, got %v", dataOmitted, string(mutatingConfig.Clusters[changingCluster].CertificateAuthorityData))
288	}
289
290	if len(mutatingConfig.AuthInfos) != 2 {
291		t.Errorf("unexpected users: %v", mutatingConfig.AuthInfos)
292	}
293	if !reflect.DeepEqual(startingConfig.AuthInfos[unchangingAuthInfo], mutatingConfig.AuthInfos[unchangingAuthInfo]) {
294		t.Errorf("expected %v, got %v", startingConfig.AuthInfos[unchangingAuthInfo], mutatingConfig.AuthInfos[unchangingAuthInfo])
295	}
296	if string(mutatingConfig.AuthInfos[changingAuthInfo].ClientCertificateData) != redacted {
297		t.Errorf("expected %v, got %v", redacted, string(mutatingConfig.AuthInfos[changingAuthInfo].ClientCertificateData))
298	}
299	if string(mutatingConfig.AuthInfos[changingAuthInfo].ClientKeyData) != redacted {
300		t.Errorf("expected %v, got %v", redacted, string(mutatingConfig.AuthInfos[changingAuthInfo].ClientKeyData))
301	}
302}
303