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 transport
18
19import (
20	"context"
21	"crypto/tls"
22	"net"
23	"net/http"
24	"testing"
25)
26
27func TestTLSConfigKey(t *testing.T) {
28	// Make sure config fields that don't affect the tls config don't affect the cache key
29	identicalConfigurations := map[string]*Config{
30		"empty":          {},
31		"basic":          {Username: "bob", Password: "password"},
32		"bearer":         {BearerToken: "token"},
33		"user agent":     {UserAgent: "useragent"},
34		"transport":      {Transport: http.DefaultTransport},
35		"wrap transport": {WrapTransport: func(http.RoundTripper) http.RoundTripper { return nil }},
36	}
37	for nameA, valueA := range identicalConfigurations {
38		for nameB, valueB := range identicalConfigurations {
39			keyA, err := tlsConfigKey(valueA)
40			if err != nil {
41				t.Errorf("Unexpected error for %q: %v", nameA, err)
42				continue
43			}
44			keyB, err := tlsConfigKey(valueB)
45			if err != nil {
46				t.Errorf("Unexpected error for %q: %v", nameB, err)
47				continue
48			}
49			if keyA != keyB {
50				t.Errorf("Expected identical cache keys for %q and %q, got:\n\t%s\n\t%s", nameA, nameB, keyA, keyB)
51				continue
52			}
53		}
54	}
55
56	// Make sure config fields that affect the tls config affect the cache key
57	dialer := net.Dialer{}
58	getCert := func() (*tls.Certificate, error) { return nil, nil }
59	uniqueConfigurations := map[string]*Config{
60		"no tls":   {},
61		"dialer":   {Dial: dialer.DialContext},
62		"dialer2":  {Dial: func(ctx context.Context, network, address string) (net.Conn, error) { return nil, nil }},
63		"insecure": {TLS: TLSConfig{Insecure: true}},
64		"cadata 1": {TLS: TLSConfig{CAData: []byte{1}}},
65		"cadata 2": {TLS: TLSConfig{CAData: []byte{2}}},
66		"cert 1, key 1": {
67			TLS: TLSConfig{
68				CertData: []byte{1},
69				KeyData:  []byte{1},
70			},
71		},
72		"cert 1, key 1, servername 1": {
73			TLS: TLSConfig{
74				CertData:   []byte{1},
75				KeyData:    []byte{1},
76				ServerName: "1",
77			},
78		},
79		"cert 1, key 1, servername 2": {
80			TLS: TLSConfig{
81				CertData:   []byte{1},
82				KeyData:    []byte{1},
83				ServerName: "2",
84			},
85		},
86		"cert 1, key 2": {
87			TLS: TLSConfig{
88				CertData: []byte{1},
89				KeyData:  []byte{2},
90			},
91		},
92		"cert 2, key 1": {
93			TLS: TLSConfig{
94				CertData: []byte{2},
95				KeyData:  []byte{1},
96			},
97		},
98		"cert 2, key 2": {
99			TLS: TLSConfig{
100				CertData: []byte{2},
101				KeyData:  []byte{2},
102			},
103		},
104		"cadata 1, cert 1, key 1": {
105			TLS: TLSConfig{
106				CAData:   []byte{1},
107				CertData: []byte{1},
108				KeyData:  []byte{1},
109			},
110		},
111		"getCert1": {
112			TLS: TLSConfig{
113				KeyData: []byte{1},
114				GetCert: getCert,
115			},
116		},
117		"getCert2": {
118			TLS: TLSConfig{
119				KeyData: []byte{1},
120				GetCert: func() (*tls.Certificate, error) { return nil, nil },
121			},
122		},
123		"getCert1, key 2": {
124			TLS: TLSConfig{
125				KeyData: []byte{2},
126				GetCert: getCert,
127			},
128		},
129		"http2, http1.1": {TLS: TLSConfig{NextProtos: []string{"h2", "http/1.1"}}},
130		"http1.1-only":   {TLS: TLSConfig{NextProtos: []string{"http/1.1"}}},
131	}
132	for nameA, valueA := range uniqueConfigurations {
133		for nameB, valueB := range uniqueConfigurations {
134			keyA, err := tlsConfigKey(valueA)
135			if err != nil {
136				t.Errorf("Unexpected error for %q: %v", nameA, err)
137				continue
138			}
139			keyB, err := tlsConfigKey(valueB)
140			if err != nil {
141				t.Errorf("Unexpected error for %q: %v", nameB, err)
142				continue
143			}
144
145			// Make sure we get the same key on the same config
146			if nameA == nameB {
147				if keyA != keyB {
148					t.Errorf("Expected identical cache keys for %q and %q, got:\n\t%s\n\t%s", nameA, nameB, keyA, keyB)
149				}
150				continue
151			}
152
153			if keyA == keyB {
154				t.Errorf("Expected unique cache keys for %q and %q, got:\n\t%s\n\t%s", nameA, nameB, keyA, keyB)
155				continue
156			}
157		}
158	}
159}
160