@@ -21,13 +21,21 @@ import (
21
21
// sign certificate, and a new certificate pool with the sign root certificate.
22
22
// The client certificate will automatically rotate before expiring.
23
23
func (c * Client ) GetClientTLSConfig (ctx context.Context , sign * api.SignResponse , pk crypto.PrivateKey , options ... TLSOption ) (* tls.Config , error ) {
24
- cert , err := TLSCertificate ( sign , pk )
24
+ tlsConfig , _ , err := c . getClientTLSConfig ( ctx , sign , pk , options )
25
25
if err != nil {
26
26
return nil , err
27
27
}
28
+ return tlsConfig , nil
29
+ }
30
+
31
+ func (c * Client ) getClientTLSConfig (ctx context.Context , sign * api.SignResponse , pk crypto.PrivateKey , options []TLSOption ) (* tls.Config , * http.Transport , error ) {
32
+ cert , err := TLSCertificate (sign , pk )
33
+ if err != nil {
34
+ return nil , nil , err
35
+ }
28
36
renewer , err := NewTLSRenewer (cert , nil )
29
37
if err != nil {
30
- return nil , err
38
+ return nil , nil , err
31
39
}
32
40
33
41
tlsConfig := getDefaultTLSConfig (sign )
@@ -43,22 +51,24 @@ func (c *Client) GetClientTLSConfig(ctx context.Context, sign *api.SignResponse,
43
51
// Apply options if given
44
52
tlsCtx := newTLSOptionCtx (c , tlsConfig )
45
53
if err := tlsCtx .apply (options ); err != nil {
46
- return nil , err
54
+ return nil , nil , err
47
55
}
48
56
49
57
// Update renew function with transport
50
58
tr , err := getDefaultTransport (tlsConfig )
51
59
if err != nil {
52
- return nil , err
60
+ return nil , nil , err
53
61
}
62
+ // Use mutable tls.Config on renew
63
+ tr .DialTLS = c .buildDialTLS (tlsCtx )
54
64
renewer .RenewCertificate = getRenewFunc (tlsCtx , c , tr , pk )
55
65
56
66
// Update client transport
57
67
c .client .Transport = tr
58
68
59
69
// Start renewer
60
70
renewer .RunContext (ctx )
61
- return tlsConfig , nil
71
+ return tlsConfig , tr , nil
62
72
}
63
73
64
74
// GetServerTLSConfig returns a tls.Config for server use configured with the
@@ -96,11 +106,18 @@ func (c *Client) GetServerTLSConfig(ctx context.Context, sign *api.SignResponse,
96
106
return nil , err
97
107
}
98
108
109
+ // GetConfigForClient allows seamless root and federated roots rotation.
110
+ // If the return of the callback is not-nil, it will use the returned
111
+ // tls.Config instead of the default one.
112
+ tlsConfig .GetConfigForClient = c .buildGetConfigForClient (tlsCtx )
113
+
99
114
// Update renew function with transport
100
115
tr , err := getDefaultTransport (tlsConfig )
101
116
if err != nil {
102
117
return nil , err
103
118
}
119
+ // Use mutable tls.Config on renew
120
+ tr .DialTLS = c .buildDialTLS (tlsCtx )
104
121
renewer .RenewCertificate = getRenewFunc (tlsCtx , c , tr , pk )
105
122
106
123
// Update client transport
@@ -113,11 +130,34 @@ func (c *Client) GetServerTLSConfig(ctx context.Context, sign *api.SignResponse,
113
130
114
131
// Transport returns an http.Transport configured to use the client certificate from the sign response.
115
132
func (c * Client ) Transport (ctx context.Context , sign * api.SignResponse , pk crypto.PrivateKey , options ... TLSOption ) (* http.Transport , error ) {
116
- tlsConfig , err := c .GetClientTLSConfig (ctx , sign , pk , options ... )
133
+ _ , tr , err := c .getClientTLSConfig (ctx , sign , pk , options )
117
134
if err != nil {
118
135
return nil , err
119
136
}
120
- return getDefaultTransport (tlsConfig )
137
+ return tr , nil
138
+ }
139
+
140
+ // buildGetConfigForClient returns an implementation of GetConfigForClient
141
+ // callback in tls.Config.
142
+ //
143
+ // If the implementation returns a nil tls.Config, the original Config will be
144
+ // used, but if it's non-nil, the returned Config will be used to handle this
145
+ // connection.
146
+ func (c * Client ) buildGetConfigForClient (ctx * TLSOptionCtx ) func (* tls.ClientHelloInfo ) (* tls.Config , error ) {
147
+ return func (* tls.ClientHelloInfo ) (* tls.Config , error ) {
148
+ return ctx .mutableConfig .TLSConfig (), nil
149
+ }
150
+ }
151
+
152
+ // buildDialTLS returns an implementation of DialTLS callback in http.Transport.
153
+ func (c * Client ) buildDialTLS (ctx * TLSOptionCtx ) func (network , addr string ) (net.Conn , error ) {
154
+ return func (network , addr string ) (net.Conn , error ) {
155
+ return tls .DialWithDialer (& net.Dialer {
156
+ Timeout : 30 * time .Second ,
157
+ KeepAlive : 30 * time .Second ,
158
+ DualStack : true ,
159
+ }, network , addr , ctx .mutableConfig .TLSConfig ())
160
+ }
121
161
}
122
162
123
163
// Certificate returns the server or client certificate from the sign response.
0 commit comments