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, canCache, err := tlsConfigKey(valueA)
40			if err != nil {
41				t.Errorf("Unexpected error for %q: %v", nameA, err)
42				continue
43			}
44			if !canCache {
45				t.Errorf("Unexpected canCache=false")
46				continue
47			}
48			keyB, canCache, err := tlsConfigKey(valueB)
49			if err != nil {
50				t.Errorf("Unexpected error for %q: %v", nameB, err)
51				continue
52			}
53			if !canCache {
54				t.Errorf("Unexpected canCache=false")
55				continue
56			}
57			if keyA != keyB {
58				t.Errorf("Expected identical cache keys for %q and %q, got:\n\t%s\n\t%s", nameA, nameB, keyA, keyB)
59				continue
60			}
61		}
62	}
63
64	// Make sure config fields that affect the tls config affect the cache key
65	dialer := net.Dialer{}
66	getCert := func() (*tls.Certificate, error) { return nil, nil }
67	uniqueConfigurations := map[string]*Config{
68		"no tls":   {},
69		"dialer":   {Dial: dialer.DialContext},
70		"dialer2":  {Dial: func(ctx context.Context, network, address string) (net.Conn, error) { return nil, nil }},
71		"insecure": {TLS: TLSConfig{Insecure: true}},
72		"cadata 1": {TLS: TLSConfig{CAData: []byte{1}}},
73		"cadata 2": {TLS: TLSConfig{CAData: []byte{2}}},
74		"cert 1, key 1": {
75			TLS: TLSConfig{
76				CertData: []byte{1},
77				KeyData:  []byte{1},
78			},
79		},
80		"cert 1, key 1, servername 1": {
81			TLS: TLSConfig{
82				CertData:   []byte{1},
83				KeyData:    []byte{1},
84				ServerName: "1",
85			},
86		},
87		"cert 1, key 1, servername 2": {
88			TLS: TLSConfig{
89				CertData:   []byte{1},
90				KeyData:    []byte{1},
91				ServerName: "2",
92			},
93		},
94		"cert 1, key 2": {
95			TLS: TLSConfig{
96				CertData: []byte{1},
97				KeyData:  []byte{2},
98			},
99		},
100		"cert 2, key 1": {
101			TLS: TLSConfig{
102				CertData: []byte{2},
103				KeyData:  []byte{1},
104			},
105		},
106		"cert 2, key 2": {
107			TLS: TLSConfig{
108				CertData: []byte{2},
109				KeyData:  []byte{2},
110			},
111		},
112		"cadata 1, cert 1, key 1": {
113			TLS: TLSConfig{
114				CAData:   []byte{1},
115				CertData: []byte{1},
116				KeyData:  []byte{1},
117			},
118		},
119		"getCert1": {
120			TLS: TLSConfig{
121				KeyData: []byte{1},
122				GetCert: getCert,
123			},
124		},
125		"getCert2": {
126			TLS: TLSConfig{
127				KeyData: []byte{1},
128				GetCert: func() (*tls.Certificate, error) { return nil, nil },
129			},
130		},
131		"getCert1, key 2": {
132			TLS: TLSConfig{
133				KeyData: []byte{2},
134				GetCert: getCert,
135			},
136		},
137		"http2, http1.1": {TLS: TLSConfig{NextProtos: []string{"h2", "http/1.1"}}},
138		"http1.1-only":   {TLS: TLSConfig{NextProtos: []string{"http/1.1"}}},
139	}
140	for nameA, valueA := range uniqueConfigurations {
141		for nameB, valueB := range uniqueConfigurations {
142			keyA, canCacheA, err := tlsConfigKey(valueA)
143			if err != nil {
144				t.Errorf("Unexpected error for %q: %v", nameA, err)
145				continue
146			}
147			keyB, canCacheB, err := tlsConfigKey(valueB)
148			if err != nil {
149				t.Errorf("Unexpected error for %q: %v", nameB, err)
150				continue
151			}
152
153			// Make sure we get the same key on the same config
154			if nameA == nameB {
155				if keyA != keyB {
156					t.Errorf("Expected identical cache keys for %q and %q, got:\n\t%s\n\t%s", nameA, nameB, keyA, keyB)
157				}
158				if canCacheA != canCacheB {
159					t.Errorf("Expected identical canCache %q and %q, got:\n\t%v\n\t%v", nameA, nameB, canCacheA, canCacheB)
160				}
161				continue
162			}
163
164			if canCacheA && canCacheB {
165				if keyA == keyB {
166					t.Errorf("Expected unique cache keys for %q and %q, got:\n\t%s\n\t%s", nameA, nameB, keyA, keyB)
167					continue
168				}
169			}
170		}
171	}
172}
173