diff --git a/api/api.go b/api/api.go index f6fe5a1bde..a2a9e89b68 100644 --- a/api/api.go +++ b/api/api.go @@ -4,11 +4,9 @@ import ( "bytes" "context" "crypto/tls" - "crypto/x509" "encoding/json" "fmt" "io" - "io/ioutil" "log" "net" "net/http" @@ -19,6 +17,7 @@ import ( "time" "github.com/hashicorp/go-cleanhttp" + "github.com/hashicorp/go-rootcerts" ) const ( @@ -38,6 +37,26 @@ const ( // whether or not to use HTTPS. HTTPSSLEnvName = "CONSUL_HTTP_SSL" + // HTTPCAFile defines an environment variable name which sets the + // CA file to use for talking to Consul over TLS. + HTTPCAFile = "CONSUL_CACERT" + + // HTTPCAPath defines an environment variable name which sets the + // path to a directory of CA certs to use for talking to Consul over TLS. + HTTPCAPath = "CONSUL_CAPATH" + + // HTTPClientCert defines an environment variable name which sets the + // client cert file to use for talking to Consul over TLS. + HTTPClientCert = "CONSUL_CLIENT_CERT" + + // HTTPClientKey defines an environment variable name which sets the + // client key file to use for talking to Consul over TLS. + HTTPClientKey = "CONSUL_CLIENT_KEY" + + // HTTPTLSServerName defines an environment variable name which sets the + // server name to use as the SNI host when connecting via TLS + HTTPTLSServerName = "CONSUL_TLS_SERVER_NAME" + // HTTPSSLVerifyEnvName defines an environment variable name which sets // whether or not to disable certificate checking. HTTPSSLVerifyEnvName = "CONSUL_HTTP_SSL_VERIFY" @@ -163,6 +182,8 @@ type Config struct { // Token is used to provide a per-request ACL token // which overrides the agent's default token. Token string + + TLSConfig TLSConfig } // TLSConfig is used to generate a TLSClientConfig that's useful for talking to @@ -177,6 +198,10 @@ type TLSConfig struct { // communication, defaults to the system bundle if not specified. CAFile string + // CAPath is the optional path to a directory of CA certificates to use for + // Consul communication, defaults to the system bundle if not specified. + CAPath string + // CertFile is the optional path to the certificate for Consul // communication. If this is set then you need to also set KeyFile. CertFile string @@ -254,27 +279,28 @@ func defaultConfig(transportFn func() *http.Transport) *Config { } } - if verify := os.Getenv(HTTPSSLVerifyEnvName); verify != "" { - doVerify, err := strconv.ParseBool(verify) + if v := os.Getenv(HTTPTLSServerName); v != "" { + config.TLSConfig.Address = v + } + if v := os.Getenv(HTTPCAFile); v != "" { + config.TLSConfig.CAFile = v + } + if v := os.Getenv(HTTPCAPath); v != "" { + config.TLSConfig.CAPath = v + } + if v := os.Getenv(HTTPClientCert); v != "" { + config.TLSConfig.CertFile = v + } + if v := os.Getenv(HTTPClientKey); v != "" { + config.TLSConfig.KeyFile = v + } + if v := os.Getenv(HTTPSSLVerifyEnvName); v != "" { + doVerify, err := strconv.ParseBool(v) if err != nil { log.Printf("[WARN] client: could not parse %s: %s", HTTPSSLVerifyEnvName, err) } - if !doVerify { - tlsClientConfig, err := SetupTLSConfig(&TLSConfig{ - InsecureSkipVerify: true, - }) - - // We don't expect this to fail given that we aren't - // parsing any of the input, but we panic just in case - // since this doesn't have an error return. - if err != nil { - panic(err) - } - - transport := transportFn() - transport.TLSClientConfig = tlsClientConfig - config.HttpClient.Transport = transport + config.TLSConfig.InsecureSkipVerify = true } } @@ -309,17 +335,12 @@ func SetupTLSConfig(tlsConfig *TLSConfig) (*tls.Config, error) { tlsClientConfig.Certificates = []tls.Certificate{tlsCert} } - if tlsConfig.CAFile != "" { - data, err := ioutil.ReadFile(tlsConfig.CAFile) - if err != nil { - return nil, fmt.Errorf("failed to read CA file: %v", err) - } - - caPool := x509.NewCertPool() - if !caPool.AppendCertsFromPEM(data) { - return nil, fmt.Errorf("failed to parse CA certificate") - } - tlsClientConfig.RootCAs = caPool + rootConfig := &rootcerts.Config{ + CAFile: tlsConfig.CAFile, + CAPath: tlsConfig.CAPath, + } + if err := rootcerts.ConfigureTLS(tlsClientConfig, rootConfig); err != nil { + return nil, err } return tlsClientConfig, nil @@ -347,6 +368,41 @@ func NewClient(config *Config) (*Client, error) { config.HttpClient = defConfig.HttpClient } + if config.TLSConfig.Address == "" { + config.TLSConfig.Address = defConfig.TLSConfig.Address + } + + if config.TLSConfig.CAFile == "" { + config.TLSConfig.CAFile = defConfig.TLSConfig.CAFile + } + + if config.TLSConfig.CAPath == "" { + config.TLSConfig.CAPath = defConfig.TLSConfig.CAPath + } + + if config.TLSConfig.CertFile == "" { + config.TLSConfig.CertFile = defConfig.TLSConfig.CertFile + } + + if config.TLSConfig.KeyFile == "" { + config.TLSConfig.KeyFile = defConfig.TLSConfig.KeyFile + } + + if !config.TLSConfig.InsecureSkipVerify { + config.TLSConfig.InsecureSkipVerify = defConfig.TLSConfig.InsecureSkipVerify + } + + tlsClientConfig, err := SetupTLSConfig(&config.TLSConfig) + + // We don't expect this to fail given that we aren't + // parsing any of the input, but we panic just in case + // since this doesn't have an error return. + if err != nil { + return nil, err + } + + config.HttpClient.Transport.(*http.Transport).TLSClientConfig = tlsClientConfig + parts := strings.SplitN(config.Address, "://", 2) if len(parts) == 2 { switch parts[0] { diff --git a/api/api_test.go b/api/api_test.go index 85a2f9e626..8e6a40ee5d 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -14,6 +14,7 @@ import ( "time" "github.com/hashicorp/consul/testutil" + "strings" ) type configCallback func(c *Config) @@ -86,6 +87,16 @@ func TestDefaultConfig_env(t *testing.T) { defer os.Setenv(HTTPAuthEnvName, "") os.Setenv(HTTPSSLEnvName, "1") defer os.Setenv(HTTPSSLEnvName, "") + os.Setenv(HTTPCAFile, "ca.pem") + defer os.Setenv(HTTPCAFile, "") + os.Setenv(HTTPCAPath, "certs/") + defer os.Setenv(HTTPCAPath, "") + os.Setenv(HTTPClientCert, "client.crt") + defer os.Setenv(HTTPClientCert, "") + os.Setenv(HTTPClientKey, "client.key") + defer os.Setenv(HTTPClientKey, "") + os.Setenv(HTTPTLSServerName, "consul.test") + defer os.Setenv(HTTPTLSServerName, "") os.Setenv(HTTPSSLVerifyEnvName, "0") defer os.Setenv(HTTPSSLVerifyEnvName, "") @@ -108,7 +119,22 @@ func TestDefaultConfig_env(t *testing.T) { if config.Scheme != "https" { t.Errorf("expected %q to be %q", config.Scheme, "https") } - if !config.HttpClient.Transport.(*http.Transport).TLSClientConfig.InsecureSkipVerify { + if config.TLSConfig.CAFile != "ca.pem" { + t.Errorf("expected %q to be %q", config.TLSConfig.CAFile, "ca.pem") + } + if config.TLSConfig.CAPath != "certs/" { + t.Errorf("expected %q to be %q", config.TLSConfig.CAPath, "certs/") + } + if config.TLSConfig.CertFile != "client.crt" { + t.Errorf("expected %q to be %q", config.TLSConfig.CertFile, "client.crt") + } + if config.TLSConfig.KeyFile != "client.key" { + t.Errorf("expected %q to be %q", config.TLSConfig.KeyFile, "client.key") + } + if config.TLSConfig.Address != "consul.test" { + t.Errorf("expected %q to be %q", config.TLSConfig.Address, "consul.test") + } + if !config.TLSConfig.InsecureSkipVerify { t.Errorf("expected SSL verification to be off") } @@ -132,9 +158,9 @@ func TestSetupTLSConfig(t *testing.T) { if err != nil { t.Fatalf("err: %v", err) } - expected := &tls.Config{} + expected := &tls.Config{RootCAs: cc.RootCAs} if !reflect.DeepEqual(cc, expected) { - t.Fatalf("bad: %v", cc) + t.Fatalf("bad: \n%v, \n%v", cc, expected) } // Try some address variations with and without ports. @@ -215,6 +241,68 @@ func TestSetupTLSConfig(t *testing.T) { if cc.RootCAs == nil { t.Fatalf("didn't load root CAs") } + + // Use a directory to load the certs instead + cc, err = SetupTLSConfig(&TLSConfig{ + CAPath: "../test/ca_path", + }) + if err != nil { + t.Fatalf("err: %v", err) + } + if len(cc.RootCAs.Subjects()) != 2 { + t.Fatalf("didn't load root CAs") + } +} + +func TestClientTLSOptions(t *testing.T) { + t.Parallel() + _, s := makeClientWithConfig(t, nil, func(conf *testutil.TestServerConfig) { + conf.CAFile = "../test/client_certs/rootca.crt" + conf.CertFile = "../test/client_certs/server.crt" + conf.KeyFile = "../test/client_certs/server.key" + conf.VerifyIncoming = true + }) + defer s.Stop() + + // Set up a client without certs + clientWithoutCerts, err := NewClient(&Config{ + Address: s.HTTPSAddr, + Scheme: "https", + TLSConfig: TLSConfig{ + Address: "consul.test", + CAFile: "../test/client_certs/rootca.crt", + }, + }) + if err != nil { + t.Fatal(err) + } + + // Should fail + _, err = clientWithoutCerts.Agent().Self() + if err == nil || !strings.Contains(err.Error(), "bad certificate") { + t.Fatal(err) + } + + // Set up a client with valid certs + clientWithCerts, err := NewClient(&Config{ + Address: s.HTTPSAddr, + Scheme: "https", + TLSConfig: TLSConfig{ + Address: "consul.test", + CAFile: "../test/client_certs/rootca.crt", + CertFile: "../test/client_certs/client.crt", + KeyFile: "../test/client_certs/client.key", + }, + }) + if err != nil { + t.Fatal(err) + } + + // Should succeed + _, err = clientWithCerts.Agent().Self() + if err != nil { + t.Fatal(err) + } } func TestSetQueryOptions(t *testing.T) { diff --git a/command/base/command.go b/command/base/command.go index 9e3ecc85e1..b6fe698fd8 100644 --- a/command/base/command.go +++ b/command/base/command.go @@ -36,8 +36,14 @@ type Command struct { hidden *flag.FlagSet // These are the options which correspond to the HTTP API options - httpAddr StringValue - token StringValue + httpAddr StringValue + token StringValue + caFile StringValue + caPath StringValue + certFile StringValue + keyFile StringValue + tlsServerName StringValue + datacenter StringValue stale BoolValue } @@ -55,6 +61,11 @@ func (c *Command) HTTPClient() (*api.Client, error) { config := api.DefaultConfig() c.httpAddr.Merge(&config.Address) c.token.Merge(&config.Token) + c.caFile.Merge(&config.TLSConfig.CAFile) + c.caPath.Merge(&config.TLSConfig.CAPath) + c.certFile.Merge(&config.TLSConfig.CertFile) + c.keyFile.Merge(&config.TLSConfig.KeyFile) + c.tlsServerName.Merge(&config.TLSConfig.Address) c.datacenter.Merge(&config.Datacenter) return api.NewClient(config) } @@ -83,6 +94,19 @@ func (c *Command) httpFlagsClient(f *flag.FlagSet) *flag.FlagSet { f = flag.NewFlagSet("", flag.ContinueOnError) } + f.Var(&c.caFile, "ca-file", + "Path to a CA file to use for TLS when communicating with Consul. This "+ + "can also be specified via the CONSUL_CACERT environment variable.") + f.Var(&c.caPath, "ca-path", + "Path to a directory of CA certificates to use for TLS when communicating "+ + "with Consul. is enabled. This can also be specified via the CONSUL_CAPATH "+ + "environment variable.") + f.Var(&c.certFile, "client-cert", + "Path to a client cert file to use for TLS when `verify_incoming` is enabled. This "+ + "can also be specified via the CONSUL_CLIENT_CERT environment variable.") + f.Var(&c.keyFile, "client-key", + "Path to a client key file to use for TLS when `verify_incoming` is enabled. This "+ + "can also be specified via the CONSUL_CLIENT_KEY environment variable.") f.Var(&c.httpAddr, "http-addr", "The `address` and port of the Consul HTTP agent. The value can be an IP "+ "address or DNS address, but it must also include the port. This can "+ @@ -93,6 +117,9 @@ func (c *Command) httpFlagsClient(f *flag.FlagSet) *flag.FlagSet { "ACL token to use in the request. This can also be specified via the "+ "CONSUL_HTTP_TOKEN environment variable. If unspecified, the query will "+ "default to the token of the Consul agent at the HTTP address.") + f.Var(&c.tlsServerName, "tls-server-name", + "The server name to use as the SNI host when connecting via TLS. This "+ + "can also be specified via the CONSUL_TLS_SERVER_NAME environment variable.") return f } diff --git a/test/ca_path/cert1.crt b/test/ca_path/cert1.crt new file mode 100644 index 0000000000..6c9d01ed06 --- /dev/null +++ b/test/ca_path/cert1.crt @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIFADCCAuqgAwIBAgIBATALBgkqhkiG9w0BAQswEzERMA8GA1UEAxMIQ2VydEF1 +dGgwHhcNMTUwNTExMjI0NjQzWhcNMjUwNTExMjI0NjU0WjATMREwDwYDVQQDEwhD +ZXJ0QXV0aDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALcMByyynHsA ++K4PJwo5+XHygaEZAhPGvHiKQK2Cbc9NDm0ZTzx0rA/dRTZlvouhDyzcJHm+6R1F +j6zQv7iaSC3qQtJiPnPsfZ+/0XhFZ3fQWMnfDiGbZpF1kJF01ofB6vnsuocFC0zG +aGC+SZiLAzs+QMP3Bebw1elCBIeoN+8NWnRYmLsYIaYGJGBSbNo/lCpLTuinofUn +L3ehWEGv1INwpHnSVeN0Ml2GFe23d7PUlj/wNIHgUdpUR+KEJxIP3klwtsI3QpSH +c4VjWdf4aIcka6K3IFuw+K0PUh3xAAPnMpAQOtCZk0AhF5rlvUbevC6jADxpKxLp +OONmvCTer4LtyNURAoBH52vbK0r/DNcTpPEFV0IP66nXUFgkk0mRKsu8HTb4IOkC +X3K4mp18EiWUUtrHZAnNct0iIniDBqKK0yhSNhztG6VakVt/1WdQY9Ey3mNtxN1O +thqWFKdpKUzPKYC3P6PfVpiE7+VbWTLLXba+8BPe8BxWPsVkjJqGSGnCte4COusz +M8/7bbTgifwJfsepwFtZG53tvwjWlO46Exl30VoDNTaIGvs1fO0GqJlh2A7FN5F2 +S1rS5VYHtPK8QdmUSvyq+7JDBc1HNT5I2zsIQbNcLwDTZ5EsbU6QR7NHDJKxjv/w +bs3eTXJSSNcFD74wRU10pXjgE5wOFu9TAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIA +BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQHazgZ3Puiuc6K2LzgcX5b6fAC +PzAfBgNVHSMEGDAWgBQHazgZ3Puiuc6K2LzgcX5b6fACPzALBgkqhkiG9w0BAQsD +ggIBAEmeNrSUhpHg1I8dtfqu9hCU/6IZThjtcFA+QcPkkMa+Z1k0SOtsgW8MdlcA +gCf5g5yQZ0DdpWM9nDB6xDIhQdccm91idHgf8wmpEHUj0an4uyn2ESCt8eqrAWf7 +AClYORCASTYfguJCxcfvwtI1uqaOeCxSOdmFay79UVitVsWeonbCRGsVgBDifJxw +G2oCQqoYAmXPM4J6syk5GHhB1O9MMq+g1+hOx9s+XHyTui9FL4V+IUO1ygVqEQB5 +PSiRBvcIsajSGVao+vK0gf2XfcXzqr3y3NhBky9rFMp1g+ykb2yWekV4WiROJlCj +TsWwWZDRyjiGahDbho/XW8JciouHZhJdjhmO31rqW3HdFviCTdXMiGk3GQIzz/Jg +P+enOaHXoY9lcxzDvY9z1BysWBgNvNrMnVge/fLP9o+a0a0PRIIVl8T0Ef3zeg1O +CLCSy/1Vae5Tx63ZTFvGFdOSusYkG9rlAUHXZE364JRCKzM9Bz0bM+t+LaO0MaEb +YoxcXEPU+gB2IvmARpInN3oHexR6ekuYHVTRGdWrdmuHFzc7eFwygRqTFdoCCU+G +QZEkd+lOEyv0zvQqYg+Jp0AEGz2B2zB53uBVECtn0EqrSdPtRzUBSByXVs6QhSXn +eVmy+z3U3MecP63X6oSPXekqSyZFuegXpNNuHkjNoL4ep2ix +-----END CERTIFICATE----- diff --git a/test/ca_path/cert2.crt b/test/ca_path/cert2.crt new file mode 100644 index 0000000000..ae9fb00b1c --- /dev/null +++ b/test/ca_path/cert2.crt @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEtzCCA5+gAwIBAgIJAIewRMI8OnvTMA0GCSqGSIb3DQEBBQUAMIGYMQswCQYD +VQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xHDAa +BgNVBAoTE0hhc2hpQ29ycCBUZXN0IENlcnQxDDAKBgNVBAsTA0RldjEWMBQGA1UE +AxMNdGVzdC5pbnRlcm5hbDEgMB4GCSqGSIb3DQEJARYRdGVzdEBpbnRlcm5hbC5j +b20wHhcNMTQwNDA3MTkwMTA4WhcNMjQwNDA0MTkwMTA4WjCBmDELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRwwGgYDVQQK +ExNIYXNoaUNvcnAgVGVzdCBDZXJ0MQwwCgYDVQQLEwNEZXYxFjAUBgNVBAMTDXRl +c3QuaW50ZXJuYWwxIDAeBgkqhkiG9w0BCQEWEXRlc3RAaW50ZXJuYWwuY29tMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrs6JK4NpiOItxrpNR/1ppUU +mH7p2BgLCBZ6eHdclle9J56i68adt8J85zaqphCfz6VDP58DsFx+N50PZyjQaDsU +d0HejRqfHRMtg2O+UQkv4Z66+Vo+gc6uGuANi2xMtSYDVTAqqzF48OOPQDgYkzcG +xcFZzTRFFZt2vPnyHj8cHcaFo/NMNVh7C3yTXevRGNm9u2mrbxCEeiHzFC2WUnvg +U2jQuC7Fhnl33Zd3B6d3mQH6O23ncmwxTcPUJe6xZaIRrDuzwUcyhLj5Z3faag/f +pFIIcHSiHRfoqHLGsGg+3swId/zVJSSDHr7pJUu7Cre+vZa63FqDaooqvnisrQID +AQABo4IBADCB/TAdBgNVHQ4EFgQUo/nrOfqvbee2VklVKIFlyQEbuJUwgc0GA1Ud +IwSBxTCBwoAUo/nrOfqvbee2VklVKIFlyQEbuJWhgZ6kgZswgZgxCzAJBgNVBAYT +AlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEcMBoGA1UE +ChMTSGFzaGlDb3JwIFRlc3QgQ2VydDEMMAoGA1UECxMDRGV2MRYwFAYDVQQDEw10 +ZXN0LmludGVybmFsMSAwHgYJKoZIhvcNAQkBFhF0ZXN0QGludGVybmFsLmNvbYIJ +AIewRMI8OnvTMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADa9fV9h +gjapBlkNmu64WX0Ufub5dsJrdHS8672P30S7ILB7Mk0W8sL65IezRsZnG898yHf9 +2uzmz5OvNTM9K380g7xFlyobSVq+6yqmmSAlA/ptAcIIZT727P5jig/DB7fzJM3g +jctDlEGOmEe50GQXc25VKpcpjAsNQi5ER5gowQ0v3IXNZs+yU+LvxLHc0rUJ/XSp +lFCAMOqd5uRoMOejnT51G6krvLNzPaQ3N9jQfNVY4Q0zfs0M+6dRWvqfqB9Vyq8/ +POLMld+HyAZEBk9zK3ZVIXx6XS4dkDnSNR91njLq7eouf6M7+7s/oMQZZRtAfQ6r +wlW975rYa1ZqEdA= +-----END CERTIFICATE----- diff --git a/test/client_certs/client.crt b/test/client_certs/client.crt new file mode 100644 index 0000000000..293727b38d --- /dev/null +++ b/test/client_certs/client.crt @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIFADCCAugCCQCPPTSu2adkQzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB +VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 +cyBQdHkgTHRkMB4XDTE3MDQxNDE5MTE0MVoXDTIyMDMxOTE5MTE0MVowPzELMAkG +A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxGzAZBgNVBAoMEkNvbnN1bCBU +ZXN0IENsaWVudDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOyJwuXC +N+8sOnFmWDx6w5Xs+ADd905EKkfrdLc0qIcrndZwdCx9zOeArLhUS1aoh0ctwz5x +wBsmUgwIQwr/V6Q1+sAEDmPmnuAiR/m3lxE+ZPr1CyNhrrTqs7jXkRRDNtZevw6d +mTE0FC4Tho016NVXckVZRRJL8Svfk2GvZbZ+1HAIi1a/Du7VQPbd1HOLKPkpb0JU +AksdAaks/avzKhRUoHQBR/T4S9GK95WrCqJIZG6iOVK2cymfZ9t/qYdm5czdq8ho +kWNqOtVb+yBx4/zs8JZI3/TZ/K4nSFcpZNZmPI7xsBL0/GG7nqWyAFWFsn/+4q0a +FIBVUe+ydONKoXKZI080b9CLkNXIp1P8rJsodjKZO/xr+/JCeo6D7ZAJymFe1QXJ +aGt7ac08s9scU97n0iuCRn6RXLdii9pbiAlArmAE1zXQKA/hcyVtjfUdeq0kA1RE +308gUab552XstQUHH0/+JcoPhn1UN+D6UOw7CxVQrq6FBDeDt7S/WtJNGM3GYrQW +tbvTQhDW0jBp0Tr+BwIDXYN5QLM6rcnB2GR3+aYVuvre6DrvisA6yKO+0F29n2LM +DdcUu8ZGzoEyFOZAgcw943VlU8bSxWkANoO0e3gKub4AvOaRqvVKyeFuFnwzKjSE +jiZTHVWs/1XVTnK51b9H33uK976O0q9qGlERAgMBAAEwDQYJKoZIhvcNAQELBQAD +ggIBAAGb44gmBikP4KJOLDDQWUX+l6kfIEobKzulmUcZ5puNS68fnQrWYUXTk5MK +IKBfuQSrxux/CEx1nBIZS/IcAnxG6GpxIcVdtzrZ/2yhDsmT3ZlgMo0+kNgqPnB2 +hVe19HO44KAkjKpbjzqya2YX5CY83WBbB0kLvbRtBraU74LDyPD8Nb2YgCKkKZuC +WHtvMw/3bGQ74FXRIjLBv1moOiWaOvaMpztn4GzChZuU8Ikyps3YiRKES2gSvPIj +tynzyoED/ddNA6Q/NeLYaCqwzIVScuqBsDCNTvFqZztS4J7VJxxnRztXb/og2yE4 +xqXezVV/O+6HhRPnxInYNiMRS++C/cyeKt150t/YS718KlebL4Pd+fQ4fDQzMyYl +ixEOVFLZiT07heUBkNA//Y0thBr/VbMvvcnMKmm3wLKsL/VGznI5akZhBa0DRj/0 +y+dSNJ2CL4I11SQ5yIaVgggqVEJ6wUWpE5woLQuvg+P+QVgkBtGR7H5dmREMq06L +dPWFoBNBil5MNDLAt2eoOauoVdba1XWWW6HZJP9lR/qgFeE9yWAFUB0BwonkYJYM +0Tm9+Jv87nJAy+a1RDszjAMV/N1RvCOb9+2g4NnHSXNVqH+gP0BsVYP5e2A31GX0 +aftVp7tPN1bSFt7nFZNbbsFhRD/fQvOpCOC/7pTnXx8zhl/2 +-----END CERTIFICATE----- diff --git a/test/client_certs/client.csr b/test/client_certs/client.csr new file mode 100644 index 0000000000..ad59cd7de8 --- /dev/null +++ b/test/client_certs/client.csr @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIEhDCCAmwCAQAwPzELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx +GzAZBgNVBAoMEkNvbnN1bCBUZXN0IENsaWVudDCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAOyJwuXCN+8sOnFmWDx6w5Xs+ADd905EKkfrdLc0qIcrndZw +dCx9zOeArLhUS1aoh0ctwz5xwBsmUgwIQwr/V6Q1+sAEDmPmnuAiR/m3lxE+ZPr1 +CyNhrrTqs7jXkRRDNtZevw6dmTE0FC4Tho016NVXckVZRRJL8Svfk2GvZbZ+1HAI +i1a/Du7VQPbd1HOLKPkpb0JUAksdAaks/avzKhRUoHQBR/T4S9GK95WrCqJIZG6i +OVK2cymfZ9t/qYdm5czdq8hokWNqOtVb+yBx4/zs8JZI3/TZ/K4nSFcpZNZmPI7x +sBL0/GG7nqWyAFWFsn/+4q0aFIBVUe+ydONKoXKZI080b9CLkNXIp1P8rJsodjKZ +O/xr+/JCeo6D7ZAJymFe1QXJaGt7ac08s9scU97n0iuCRn6RXLdii9pbiAlArmAE +1zXQKA/hcyVtjfUdeq0kA1RE308gUab552XstQUHH0/+JcoPhn1UN+D6UOw7CxVQ +rq6FBDeDt7S/WtJNGM3GYrQWtbvTQhDW0jBp0Tr+BwIDXYN5QLM6rcnB2GR3+aYV +uvre6DrvisA6yKO+0F29n2LMDdcUu8ZGzoEyFOZAgcw943VlU8bSxWkANoO0e3gK +ub4AvOaRqvVKyeFuFnwzKjSEjiZTHVWs/1XVTnK51b9H33uK976O0q9qGlERAgMB +AAGgADANBgkqhkiG9w0BAQsFAAOCAgEARWD26zR/JuyER2SmCq0GYc4i5bTmQOZw +BcToQsYQcfTrdZspzKhb4EM560tVqE8V6Ckkl2V97ZbbD7KIRgY6LEsCcr6VCfU5 +rSiyHo1M/PDnK6FqYE0qTqqu3jOGmh97RAZi8REy8gfT/PrE8kDaEVfm0nCB8aaW +8wg6ncmStRLKJB4QP1YDpcQH568MMY/0E7xUixp1KjaA4VwE4QEFNoxmpp/Dwpzw +BB6kjlKM2tsjkbm0EHCPU5creAoqPNVQNCIVTDBUgkwhUrU2ljAjlC24tL66L0FP +RKmyk8yWR2PQkkkWlRwarypGmOAE0GMVMICNh5WTaPaa1XTTpZme3ctpZQZO3LRT +Bao4tXM3pA8vApCbkqExR1ow86HvOHv50Y+LQpD1fk7cj18npCR831f1cr/jQw6V +p4Z6bdftF38ZCsCdjUHXbtc3tA0220I+0e8ng1znAfMPQC+KVrHaapt1OFWGHPFk +KDLyxtZN1IOEOkjtI23KOUlEtG4jnm5UjFG43EXA3qmbUrHNCsHhRpHhMBqu4a0Z +ifPQ5+YFyUCmgVUSGeGmpnyxWalmwOT2Ygd/uhn7TnZ0GAv+x1tLHNe78Q8YKi9a +gw4zZcDFJmCPnVkfQ+lVSSY5GjSPI8DZCfr+IJBIPOiknTGP9g2dEbUX8xVyEfK6 +18IjYxoATJE= +-----END CERTIFICATE REQUEST----- diff --git a/test/client_certs/client.key b/test/client_certs/client.key new file mode 100644 index 0000000000..d8f34460f3 --- /dev/null +++ b/test/client_certs/client.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/test/client_certs/rootca.crt b/test/client_certs/rootca.crt new file mode 100644 index 0000000000..e6c1c238a6 --- /dev/null +++ b/test/client_certs/rootca.crt @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFXTCCA0WgAwIBAgIJAKkYXwqUpHWIMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQwHhcNMTcwNDE0MTkwNjIwWhcNMjIwNDE0MTkwNjIwWjBF +MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 +ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC +CgKCAgEA0pMZRBhBHaYG1FttDzt+rctrM8NtslfbAbHflM4ly7mibCmrnh/sGYSP +Y/QcrGnCWrjXspUM0dxtmXGmXKj4yRpKhVYw16saDcn2t55dxMw23uEhgfrigtYS +/MoC78OaQryRGvYdxF5unrybBrXDrVfxA8ycYBOV04piS7NlN1/m3TkiNrqkl1up +paPscfFaY59yz3Lgq2vs8U1SLtph8ALwjJcz8O3BbBUQuiZYNuiLLnkRroxT3oSp +Zbdna2aXtdD/H9JJUoJLjoZp6x5fNOtc+5vF8QZ/jKeJDsxqwf4VT4Z6t8sUMFtO +YAR3QEV7wtOhWWfFVzdlCsKZhD8ryemlYSMJ7wfmXUeoiElSPRfvIHUTcJFx37VR +V6LmOzs1gjMpGZxGLk/GtaCbDlyCaT/hae8bqtRhngBy5bvGxmdSBQd0fjYRr2CP +Pz+Gzx3yQx8yb9VV7dTI3H4LWaTjuy2WooITzy3xY4bOvp4UwusFgbIdywwCpDFJ +zzy3FaqoMx06v5D3I9JCanlXk5FErA0GX45pPM4x3FWZfVwrXZtomBFDC6qlRMpH +FH8A/KrbpolwiDklSWUxHbfz32gpzf3kLW2nOVpnZPyAgSYudjSFGW00jRomCXOy +EOgQj/w+M3hKosvVqIE8IQgfMPNRCK9hn11gVqUvkdcYvo/2jUMCAwEAAaNQME4w +HQYDVR0OBBYEFMnRHZ6zGzu/N5MdNv4HKPP5rMqOMB8GA1UdIwQYMBaAFMnRHZ6z +Gzu/N5MdNv4HKPP5rMqOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIB +AFPWJZiQTupGr5B14PGPkiesyL1VCkO9D7nr6dXgQwAUTIdDuo9+nZg1HzOd1evY +tRWGTAYOsyGNLBIjdhvTZcZz625i1zXFRzkpu0iOUoaH77/XVGkAKyaeYc3oIe9i +bRke37/NQokmM3Eko+M/KoAk31osDxlmdQTOVqqoZN+ag6xsrpN6XUmhu3DNfw1j +xud6RMH6J+SamG/vUg+GyqKZ9WpKNcLliVPJgOfX1XI3wstOIqkhlw/qveIgIfPv +aUVf+rykdgqYMMQvR6qx0k5iHeqj+F1cZRp3P0Uao0hoxi+udgj0X3F7/s/Cbr9c +TPZrIlhicZgli9UOwrjZ4B4mEZ4aD8yDbYO3TZe2DnuhPI7uDFG8lvCuLYu8V/lA +0yRoBaJf5Z1IXI4190Ww6bmxYV/n5EAFi6o46hWRUiYROtKEcP9Rmabodgp+Jxw6 +fwzcYqUXTOXR8/gAFPxt5oEfhZ8VJ4nlB9PFTjDi7Gbz+2MnmJokqkxLAR7//FEz +Rdmyfl+CvnPZ4TXLk77tuhf3Os9zHSTLobBdDivrTOpc0LdYw5l9yN9s93bG2TBr +2T0aKInqAduReLE2nhkYCdlY+dbjbELEiLicqSaEiwr9WbaWuLMoy4tDY52pYgTR +lEclafi+O3Y35hEE6VAfZvM1TeR3gvnnQf4ThqIxkRVl +-----END CERTIFICATE----- diff --git a/test/client_certs/rootca.key b/test/client_certs/rootca.key new file mode 100644 index 0000000000..b5c7256ac9 --- /dev/null +++ b/test/client_certs/rootca.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/test/client_certs/rootca.srl b/test/client_certs/rootca.srl new file mode 100644 index 0000000000..3c4cf4a3bb --- /dev/null +++ b/test/client_certs/rootca.srl @@ -0,0 +1 @@ +8F3D34AED9A76443 diff --git a/test/client_certs/server.crt b/test/client_certs/server.crt new file mode 100644 index 0000000000..463c54c094 --- /dev/null +++ b/test/client_certs/server.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFHDCCAwQCCQCPPTSu2adkQjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB +VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 +cyBQdHkgTHRkMB4XDTE3MDQxNDE5MDkzOFoXDTIyMDMxOTE5MDkzOFowWzELMAkG +A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 +IFdpZGdpdHMgUHR5IEx0ZDEUMBIGA1UEAwwLY29uc3VsLnRlc3QwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQDI57K1LPlNXpK4ud6XbqhQAM9w6mym5d+5 +utGlq+ojNrnKdhaokzDOcEpELLguQlFevDrTGuBJLxInmDvRN8BmYshZAuwW+odw +iGa4IiT9rN0JeQIQr9DvNjRe7Rhzb3v0CIFIwaBWZyRSdEKuZORyDOvSudATI2p9 +Ux9HpWJKG9clHEiAjWeseLfEttkAZgojPgdz/7Nq2CT877QtdbbKO8h+IIKevhVM +JLIyWhwGMy5orlVP42om7wgAIonm8LFCHe84JUVlOjuJgMzfUvz/UuKJFbAku7Dt +UXKL+gZsJg5YHhtMMHQO40UDNTfxNEiIRNyOHaQv4ptRUJq7vIbBng+m1uyYFkJp +NvTf4+OApXzsfhb8bjt8QRn5fsCsYU94oUVy+DSw10EW+IR1F7pGJZX5dYZgm6H7 +E+cj0pYV1dKbdP/5L3mv6KJUTaGDRanLiNPQFOyhs6y6Qf1Y7a270oge9UpHAQ6D +KI5jvCuwzW2wDE7KEpo5SGRIjoK9KfouyhlYAaIiJNnVyjVXDXGhzJgH+/2cGW/n +TQAqKl4OtmzyNpihgv9Mhm86nro0XLnZHruJZ/SvZgpmSs8luo70CFK990j65JiM +UTvBdKADfjCZB4NxVo3yUC0UVaMsoMg8mbOGJPErY8WaFCqwsBHLPmbvbZvp8BYs +ve3dDhh+OQIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQABCbceu3dDQ+NSRN45vEiB +wiyq7NLVHoSw7UWN0RPg7SVOPNt7lOqQ5ZtYNJQ0XAuBdHzNAZ/sfUgfURJbYhs5 +MYalkkmMkpNWZQoMYxdj1sLX6KzLFFOtcACUSuZyOSGCBmuEDuDUTsQp1drZjNqb +fOtCWAuvSSbw8SnO6eTjUCwjcbe482kR5vnoaoRetmtTpIFdxwOXnegDXgkBnMMr +JSx+xIRVn2JzxJwaBmtn16P0/ksEMSPh0rKRvzE9zC7Jm2DvNOgEkdK8ae6DHFYY +zSonWjX3SlT+gpvuCwXC4ZmO2nV4CH34JDUUNRPub7o+t5XTGUxPGo0c/tdQYWZc +k0XTRzK6pLAq4X3NAF83nZ8pEi5z1u0Y+Dcx3AqBfhJSc2wg5++GZbELZGAmgiH2 +WZa2/9zkCUGPke4GoctYNNhTmquk6ysJjDO+xOtaEQNwk04mqBwvb7j85iRNBkYX ++9PDF4sumEkkuNFB9vRSEJVrn3onQuZ3n2k1IujR6S6Vojhvideo5aT1NVq+1SQ5 +bDe5E4IyrsFuxjYNIyA1hZmX2/qXYJ9U05QbyMs170lNhoKkdOf1voCxG3+sRTfz +yhGNJ2ks0MuEEiEjOFh9Za9lnk4/OHUG4yjWWdE5S/WH1xyyfokIM7xbo3Le8XgJ +ddL0E6Ag/Ow1ey1H7gsNOA== +-----END CERTIFICATE----- diff --git a/test/client_certs/server.csr b/test/client_certs/server.csr new file mode 100644 index 0000000000..0d7f51d6a7 --- /dev/null +++ b/test/client_certs/server.csr @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIEoDCCAogCAQAwWzELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx +ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEUMBIGA1UEAwwLY29u +c3VsLnRlc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDI57K1LPlN +XpK4ud6XbqhQAM9w6mym5d+5utGlq+ojNrnKdhaokzDOcEpELLguQlFevDrTGuBJ +LxInmDvRN8BmYshZAuwW+odwiGa4IiT9rN0JeQIQr9DvNjRe7Rhzb3v0CIFIwaBW +ZyRSdEKuZORyDOvSudATI2p9Ux9HpWJKG9clHEiAjWeseLfEttkAZgojPgdz/7Nq +2CT877QtdbbKO8h+IIKevhVMJLIyWhwGMy5orlVP42om7wgAIonm8LFCHe84JUVl +OjuJgMzfUvz/UuKJFbAku7DtUXKL+gZsJg5YHhtMMHQO40UDNTfxNEiIRNyOHaQv +4ptRUJq7vIbBng+m1uyYFkJpNvTf4+OApXzsfhb8bjt8QRn5fsCsYU94oUVy+DSw +10EW+IR1F7pGJZX5dYZgm6H7E+cj0pYV1dKbdP/5L3mv6KJUTaGDRanLiNPQFOyh +s6y6Qf1Y7a270oge9UpHAQ6DKI5jvCuwzW2wDE7KEpo5SGRIjoK9KfouyhlYAaIi +JNnVyjVXDXGhzJgH+/2cGW/nTQAqKl4OtmzyNpihgv9Mhm86nro0XLnZHruJZ/Sv +ZgpmSs8luo70CFK990j65JiMUTvBdKADfjCZB4NxVo3yUC0UVaMsoMg8mbOGJPEr +Y8WaFCqwsBHLPmbvbZvp8BYsve3dDhh+OQIDAQABoAAwDQYJKoZIhvcNAQELBQAD +ggIBAIq+JNjO/pixXFRwYUISRib68ya39C0VKj2T8L4HsAtpP2K7gkKGEoQ5AFhi +wxe0424myEBBZ4kS6y5BCETtKFb3C9K4c2l1Wp5GIR9QUrj2qrorGnZNJSEBrtHm +G4neTxPyepZ+n9C9K5RWC/S/l8nge4+oWU2F0nWIAFK+4GGGTyXFjbfGKtET8CKd +NQ4jcrabkRd49qPrXhEMTWzPkKdtZ4Gh7eFVAi5IrgJJlJPhb5/XnUQ+6L7NrIWG +D1nHCq8XNDm8Gg9KiMuB4/A7dcqyaoyYofojrnZ2HryGTeLbezpwQmMfVy1dM0ht +vueKQwOS7xjiglsV48G5mmql+0auYoBLes2yYGBJ4gLC+Gwokav+FtRhyyRUVZ3+ +lta2a8XpzdMpmESQrwvz+v37fC/eBsplhk8tTy0IQUzUp0KVCRkR40UHeH9YKsu1 +cvPwfzk3DPt2wHWjBw7b8RKSXQFyszP9QWODqxnOtE7BoNdHiyxF/W4RaysIVrAG +Vs2iRNVSPexiT30BgnfQN1i1HU4eXC/QuTWilo86vwDOjpHhr9FdjPghLk2TbV+g +iO3TX0zy0t6Un5rLGMt066pAFCIqynT1sf3CTVXbaeWpkHj1wjVmYOoG75xxWMsv +GKmSoKRex/SDko3s2pmfQ+vmkCTKQqabayUH5mh1Ron9B043 +-----END CERTIFICATE REQUEST----- diff --git a/test/client_certs/server.key b/test/client_certs/server.key new file mode 100644 index 0000000000..8da39d5e10 --- /dev/null +++ b/test/client_certs/server.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/testutil/server.go b/testutil/server.go index aa20670f7f..47c12c7094 100644 --- a/testutil/server.go +++ b/testutil/server.go @@ -39,6 +39,7 @@ type TestPerformanceConfig struct { type TestPortConfig struct { DNS int `json:"dns,omitempty"` HTTP int `json:"http,omitempty"` + HTTPS int `json:"https,omitempty"` SerfLan int `json:"serf_lan,omitempty"` SerfWan int `json:"serf_wan,omitempty"` Server int `json:"server,omitempty"` @@ -74,6 +75,11 @@ type TestServerConfig struct { ACLDefaultPolicy string `json:"acl_default_policy,omitempty"` ACLEnforceVersion8 bool `json:"acl_enforce_version_8"` Encrypt string `json:"encrypt,omitempty"` + CAFile string `json:"ca_file,omitempty"` + CertFile string `json:"cert_file,omitempty"` + KeyFile string `json:"key_file,omitempty"` + VerifyIncoming bool `json:"verify_incoming,omitempty"` + VerifyOutgoing bool `json:"verify_outgoing,omitempty"` Stdout, Stderr io.Writer `json:"-"` Args []string `json:"-"` } @@ -105,6 +111,7 @@ func defaultServerConfig() *TestServerConfig { Ports: &TestPortConfig{ DNS: randomPort(), HTTP: randomPort(), + HTTPS: randomPort(), SerfLan: randomPort(), SerfWan: randomPort(), Server: randomPort(), @@ -150,9 +157,10 @@ type TestServer struct { cmd *exec.Cmd Config *TestServerConfig - HTTPAddr string - LANAddr string - WANAddr string + HTTPAddr string + HTTPSAddr string + LANAddr string + WANAddr string HttpClient *http.Client } @@ -243,9 +251,10 @@ func NewTestServerConfig(cb ServerConfigCallback) (*TestServer, error) { Config: consulConfig, cmd: cmd, - HTTPAddr: httpAddr, - LANAddr: fmt.Sprintf("127.0.0.1:%d", consulConfig.Ports.SerfLan), - WANAddr: fmt.Sprintf("127.0.0.1:%d", consulConfig.Ports.SerfWan), + HTTPAddr: httpAddr, + HTTPSAddr: fmt.Sprintf("127.0.0.1:%d", consulConfig.Ports.HTTPS), + LANAddr: fmt.Sprintf("127.0.0.1:%d", consulConfig.Ports.SerfLan), + WANAddr: fmt.Sprintf("127.0.0.1:%d", consulConfig.Ports.SerfWan), HttpClient: client, } diff --git a/website/source/docs/commands/_http_api_options_client.html.markdown b/website/source/docs/commands/_http_api_options_client.html.markdown index 8e5f443eb1..1082ff0986 100644 --- a/website/source/docs/commands/_http_api_options_client.html.markdown +++ b/website/source/docs/commands/_http_api_options_client.html.markdown @@ -1,3 +1,18 @@ +* `-ca-file=` - Path to a CA file to use for TLS when communicating with Consul. + This can also be specified via the `CONSUL_CACERT` environment variable. + +* `-ca-path=` - Path to a directory of CA certificates to use for TLS when + communicating with Consul. This can also be specified via the `CONSUL_CAPATH` + environment variable. + +* `-client-cert=` - Path to a client cert file to use for TLS when + `verify_incoming` is enabled. This can also be specified via the `CONSUL_CLIENT_CERT` + environment variable. + +* `-client-key=` - Path to a client key file to use for TLS when + `verify_incoming` is enabled. This can also be specified via the `CONSUL_CLIENT_KEY` + environment variable. + * `-http-addr=` - Address of the Consul agent with the port. This can be an IP address or DNS address, but it must include the port. This can also be specified via the `CONSUL_HTTP_ADDR` environment variable. In Consul 0.8 and @@ -5,6 +20,10 @@ be used instead. The scheme can also be set to HTTPS by setting the environment variable `CONSUL_HTTP_SSL=true`. +* `-tls-server-name=` - The server name to use as the SNI host when + connecting via TLS. This can also be specified via the `CONSUL_TLS_SERVER_NAME` + environment variable. + * `-token=` - ACL token to use in the request. This can also be specified via the `CONSUL_HTTP_TOKEN` environment variable. If unspecified, the query will default to the token of the Consul agent at the HTTP address. diff --git a/website/source/docs/commands/index.html.markdown b/website/source/docs/commands/index.html.markdown index 435dc56995..a77cc06c3f 100644 --- a/website/source/docs/commands/index.html.markdown +++ b/website/source/docs/commands/index.html.markdown @@ -137,3 +137,43 @@ for development purposes: ``` CONSUL_HTTP_SSL_VERIFY=false ``` + +### `CONSUL_CACERT` + +Path to a CA file to use for TLS when communicating with Consul. + +``` +CONSUL_CACERT=ca.crt +``` + +### `CONSUL_CAPATH` + +Path to a directory of CA certificates to use for TLS when communicating with Consul. + +``` +CONSUL_CAPATH=ca_certs/ +``` + +### `CONSUL_CLIENT_CERT` + +Path to a client cert file to use for TLS when `verify_incoming` is enabled. + +``` +CONSUL_CLIENT_CERT=client.crt +``` + +### `CONSUL_CLIENT_KEY` + +Path to a client key file to use for TLS when `verify_incoming` is enabled. + +``` +CONSUL_CLIENT_KEY=client.key +``` + +### `CONSUL_TLS_SERVER_NAME` + +The server name to use as the SNI host when connecting via TLS. + +``` +CONSUL_TLS_SERVER_NAME=consulserver.domain +``` \ No newline at end of file