@@ -19,7 +19,9 @@ package webhook
19
19
import (
20
20
"context"
21
21
"crypto/tls"
22
+ "crypto/x509"
22
23
"fmt"
24
+ "io/ioutil"
23
25
"net"
24
26
"net/http"
25
27
"os"
@@ -54,9 +56,13 @@ type Server struct {
54
56
// CertName is the server certificate name. Defaults to tls.crt.
55
57
CertName string
56
58
57
- // CertName is the server key name. Defaults to tls.key.
59
+ // KeyName is the server key name. Defaults to tls.key.
58
60
KeyName string
59
61
62
+ // ClientCAName is the CA certificate name which server used to verify remote(client)'s certificate.
63
+ // Defaults to "", which means server does not verify client's certificate.
64
+ ClientCAName string
65
+
60
66
// WebhookMux is the multiplexer that handles different webhooks.
61
67
WebhookMux * http.ServeMux
62
68
@@ -168,6 +174,23 @@ func (s *Server) Start(stop <-chan struct{}) error {
168
174
GetCertificate : certWatcher .GetCertificate ,
169
175
}
170
176
177
+ // load CA to verify client certificate
178
+ if s .ClientCAName != "" {
179
+ certPool := x509 .NewCertPool ()
180
+ clientCABytes , err := ioutil .ReadFile (filepath .Join (s .CertDir , s .ClientCAName ))
181
+ if err != nil {
182
+ return fmt .Errorf ("failed to read client CA cert: %v" , err )
183
+ }
184
+
185
+ ok := certPool .AppendCertsFromPEM (clientCABytes )
186
+ if ! ok {
187
+ return fmt .Errorf ("failed to append client CA cert to CA pool" )
188
+ }
189
+
190
+ cfg .ClientCAs = certPool
191
+ cfg .ClientAuth = tls .RequireAndVerifyClientCert
192
+ }
193
+
171
194
listener , err := tls .Listen ("tcp" , net .JoinHostPort (s .Host , strconv .Itoa (int (s .Port ))), cfg )
172
195
if err != nil {
173
196
return err
0 commit comments