Skip to content

Commit

Permalink
Add option to disable client certificate requesting.
Browse files Browse the repository at this point in the history
Fixes #3372
  • Loading branch information
jefferai committed Sep 25, 2017
1 parent b741332 commit 67c3082
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 15 deletions.
1 change: 1 addition & 0 deletions command/server/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,7 @@ func parseListeners(result *Config, list *ast.ObjectList) error {
"tls_cipher_suites",
"tls_prefer_server_cipher_suites",
"tls_require_and_verify_client_cert",
"tls_disable_client_certs",
"tls_client_ca_file",
"token",
}
Expand Down
4 changes: 3 additions & 1 deletion command/server/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,8 @@ listener "tcp" {
tls_key_file = "./certs/server.key"
tls_client_ca_file = "./certs/rootca.crt"
tls_min_version = "tls12"
tls_require_and_verify_client_cert = true
tls_require_and_verify_client_cert = true
tls_disable_client_certs = true
}`))

var config Config
Expand Down Expand Up @@ -298,6 +299,7 @@ listener "tcp" {
"tls_client_ca_file": "./certs/rootca.crt",
"tls_min_version": "tls12",
"tls_require_and_verify_client_cert": true,
"tls_disable_client_certs": true,
},
},
},
Expand Down
16 changes: 14 additions & 2 deletions command/server/listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,14 @@ func listenerWrapTLS(
}
tlsConf.PreferServerCipherSuites = preferServer
}
var requireVerifyCerts bool
var err error
if v, ok := config["tls_require_and_verify_client_cert"]; ok {
requireClient, err := parseutil.ParseBool(v)
requireVerifyCerts, err = parseutil.ParseBool(v)
if err != nil {
return nil, nil, nil, fmt.Errorf("invalid value for 'tls_require_and_verify_client_cert': %v", err)
}
if requireClient {
if requireVerifyCerts {
tlsConf.ClientAuth = tls.RequireAndVerifyClientCert
}
if tlsClientCaFile, ok := config["tls_client_ca_file"]; ok {
Expand All @@ -151,6 +153,16 @@ func listenerWrapTLS(
tlsConf.ClientCAs = caPool
}
}
if v, ok := config["tls_disable_client_certs"]; ok {
disableClientCerts, err := parseutil.ParseBool(v)
if err != nil {
return nil, nil, nil, fmt.Errorf("invalid value for 'tls_disable_client_certs': %v", err)
}
if disableClientCerts && requireVerifyCerts {
return nil, nil, nil, fmt.Errorf("'tls_disable_client_certs' and 'tls_require_and_verify_client_cert' are mutually exclusive")
}
tlsConf.ClientAuth = tls.NoClientCert
}

ln = tls.NewListener(ln, tlsConf)
props["tls"] = "enabled"
Expand Down
54 changes: 42 additions & 12 deletions command/server/listener_tcp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,50 @@ func TestTCPListener_tls(t *testing.T) {
cwd+"/test-fixtures/reload/reload_foo.pem",
cwd+"/test-fixtures/reload/reload_foo.key")

connFn := func(lnReal net.Listener) (net.Conn, error) {
conn, err := tls.Dial("tcp", ln.Addr().String(), &tls.Config{
RootCAs: certPool,
Certificates: []tls.Certificate{clientCert},
})
connFn := func(clientCerts bool) func(net.Listener) (net.Conn, error) {
return func(lnReal net.Listener) (net.Conn, error) {
conf := &tls.Config{
RootCAs: certPool,
}
if clientCerts {
conf.Certificates = []tls.Certificate{clientCert}
}
conn, err := tls.Dial("tcp", ln.Addr().String(), conf)

if err != nil {
return nil, err
}
if err = conn.Handshake(); err != nil {
return nil, err
if err != nil {
return nil, err
}
if err = conn.Handshake(); err != nil {
return nil, err
}
return conn, nil
}
return conn, nil
}

testListenerImpl(t, ln, connFn, "foo.example.com")
testListenerImpl(t, ln, connFn(true), "foo.example.com")

ln, _, _, err = tcpListenerFactory(map[string]interface{}{
"address": "127.0.0.1:0",
"tls_cert_file": wd + "reload_foo.pem",
"tls_key_file": wd + "reload_foo.key",
"tls_require_and_verify_client_cert": "true",
"tls_disable_client_certs": "true",
"tls_client_ca_file": wd + "reload_ca.pem",
}, nil)
if err == nil {
t.Fatal("expected error due to mutually exclusive client cert options")
}

ln, _, _, err = tcpListenerFactory(map[string]interface{}{
"address": "127.0.0.1:0",
"tls_cert_file": wd + "reload_foo.pem",
"tls_key_file": wd + "reload_foo.key",
"tls_disable_client_certs": "true",
"tls_client_ca_file": wd + "reload_ca.pem",
}, nil)
if err != nil {
t.Fatalf("err: %s", err)
}

testListenerImpl(t, ln, connFn(false), "foo.example.com")
}
4 changes: 4 additions & 0 deletions website/source/docs/configuration/listener/tcp.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ listener "tcp" {
- `tls_client_ca_file` `(string: "")` – PEM-encoded Certificate Authority file
used for checking the authenticity of client.

- `tls_disable_client_certs` `(string: "false")` – Turns off client
authentication for this listener. The default behavior (when this is false)
is for Vault to request client certificates when available.

## `tcp` Listener Examples

### Configuring TLS
Expand Down

0 comments on commit 67c3082

Please sign in to comment.