agent: setup grpc server with auto_encrypt certs and add -https-port (#7086)
* setup grpc server with TLS config used across consul. * add -https-port flag
This commit is contained in:
parent
f3a01e6a4a
commit
e00effa325
|
@ -723,9 +723,9 @@ func (a *Agent) listenAndServeGRPC() error {
|
||||||
if a.config.HTTPSPort > 0 {
|
if a.config.HTTPSPort > 0 {
|
||||||
// gRPC uses the same TLS settings as the HTTPS API. If HTTPS is
|
// gRPC uses the same TLS settings as the HTTPS API. If HTTPS is
|
||||||
// enabled then gRPC will require HTTPS as well.
|
// enabled then gRPC will require HTTPS as well.
|
||||||
a.grpcServer, err = a.xdsServer.GRPCServer(a.config.CertFile, a.config.KeyFile)
|
a.grpcServer, err = a.xdsServer.GRPCServer(a.tlsConfigurator)
|
||||||
} else {
|
} else {
|
||||||
a.grpcServer, err = a.xdsServer.GRPCServer("", "")
|
a.grpcServer, err = a.xdsServer.GRPCServer(nil)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -79,6 +79,7 @@ func AddFlags(fs *flag.FlagSet, f *Flags) {
|
||||||
add(&f.Config.EncryptKey, "encrypt", "Provides the gossip encryption key.")
|
add(&f.Config.EncryptKey, "encrypt", "Provides the gossip encryption key.")
|
||||||
add(&f.Config.Ports.GRPC, "grpc-port", "Sets the gRPC API port to listen on (currently needed for Envoy xDS only).")
|
add(&f.Config.Ports.GRPC, "grpc-port", "Sets the gRPC API port to listen on (currently needed for Envoy xDS only).")
|
||||||
add(&f.Config.Ports.HTTP, "http-port", "Sets the HTTP API port to listen on.")
|
add(&f.Config.Ports.HTTP, "http-port", "Sets the HTTP API port to listen on.")
|
||||||
|
add(&f.Config.Ports.HTTPS, "https-port", "Sets the HTTPS API port to listen on.")
|
||||||
add(&f.Config.StartJoinAddrsLAN, "join", "Address of an agent to join at start time. Can be specified multiple times.")
|
add(&f.Config.StartJoinAddrsLAN, "join", "Address of an agent to join at start time. Can be specified multiple times.")
|
||||||
add(&f.Config.StartJoinAddrsWAN, "join-wan", "Address of an agent to join -wan at start time. Can be specified multiple times.")
|
add(&f.Config.StartJoinAddrsWAN, "join-wan", "Address of an agent to join -wan at start time. Can be specified multiple times.")
|
||||||
add(&f.Config.LogLevel, "log-level", "Log level of the agent.")
|
add(&f.Config.LogLevel, "log-level", "Log level of the agent.")
|
||||||
|
|
|
@ -52,6 +52,14 @@ func TestParseFlags(t *testing.T) {
|
||||||
args: []string{`-grpc-port`, `1`},
|
args: []string{`-grpc-port`, `1`},
|
||||||
flags: Flags{Config: Config{Ports: Ports{GRPC: pInt(1)}}},
|
flags: Flags{Config: Config{Ports: Ports{GRPC: pInt(1)}}},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
args: []string{`-http-port`, `1`},
|
||||||
|
flags: Flags{Config: Config{Ports: Ports{HTTP: pInt(1)}}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
args: []string{`-https-port`, `1`},
|
||||||
|
flags: Flags{Config: Config{Ports: Ports{HTTPS: pInt(1)}}},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
args: []string{`-serf-lan-port`, `1`},
|
args: []string{`-serf-lan-port`, `1`},
|
||||||
flags: Flags{Config: Config{Ports: Ports{SerfLAN: pInt(1)}}},
|
flags: Flags{Config: Config{Ports: Ports{SerfLAN: pInt(1)}}},
|
||||||
|
|
|
@ -807,6 +807,7 @@ type RuntimeConfig struct {
|
||||||
// Setting this to a value <= 0 disables the endpoint.
|
// Setting this to a value <= 0 disables the endpoint.
|
||||||
//
|
//
|
||||||
// hcl: ports { https = int }
|
// hcl: ports { https = int }
|
||||||
|
// flags: -https-port int
|
||||||
HTTPSPort int
|
HTTPSPort int
|
||||||
|
|
||||||
// KeyFile is used to provide a TLS key that is used for serving TLS
|
// KeyFile is used to provide a TLS key that is used for serving TLS
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"github.com/hashicorp/consul/agent/connect"
|
"github.com/hashicorp/consul/agent/connect"
|
||||||
"github.com/hashicorp/consul/agent/proxycfg"
|
"github.com/hashicorp/consul/agent/proxycfg"
|
||||||
"github.com/hashicorp/consul/agent/structs"
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
|
"github.com/hashicorp/consul/tlsutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ADSStream is a shorter way of referring to this thing...
|
// ADSStream is a shorter way of referring to this thing...
|
||||||
|
@ -536,16 +537,15 @@ func (s *Server) Check(ctx context.Context, r *envoyauthz.CheckRequest) (*envoya
|
||||||
|
|
||||||
// GRPCServer returns a server instance that can handle XDS and ext_authz
|
// GRPCServer returns a server instance that can handle XDS and ext_authz
|
||||||
// requests.
|
// requests.
|
||||||
func (s *Server) GRPCServer(certFile, keyFile string) (*grpc.Server, error) {
|
func (s *Server) GRPCServer(tlsConfigurator *tlsutil.Configurator) (*grpc.Server, error) {
|
||||||
opts := []grpc.ServerOption{
|
opts := []grpc.ServerOption{
|
||||||
grpc.MaxConcurrentStreams(2048),
|
grpc.MaxConcurrentStreams(2048),
|
||||||
}
|
}
|
||||||
if certFile != "" && keyFile != "" {
|
if tlsConfigurator != nil {
|
||||||
creds, err := credentials.NewServerTLSFromFile(certFile, keyFile)
|
if tlsConfigurator.Cert() != nil {
|
||||||
if err != nil {
|
creds := credentials.NewTLS(tlsConfigurator.IncomingGRPCConfig())
|
||||||
return nil, err
|
opts = append(opts, grpc.Creds(creds))
|
||||||
}
|
}
|
||||||
opts = append(opts, grpc.Creds(creds))
|
|
||||||
}
|
}
|
||||||
srv := grpc.NewServer(opts...)
|
srv := grpc.NewServer(opts...)
|
||||||
envoydisco.RegisterAggregatedDiscoveryServiceServer(srv, s)
|
envoydisco.RegisterAggregatedDiscoveryServiceServer(srv, s)
|
||||||
|
|
|
@ -441,12 +441,7 @@ func (c *Configurator) commonTLSConfig(verifyIncoming bool) *tls.Config {
|
||||||
// autoEncrypt cert too so that a client can encrypt incoming
|
// autoEncrypt cert too so that a client can encrypt incoming
|
||||||
// connections without having a manual cert configured.
|
// connections without having a manual cert configured.
|
||||||
tlsConfig.GetCertificate = func(*tls.ClientHelloInfo) (*tls.Certificate, error) {
|
tlsConfig.GetCertificate = func(*tls.ClientHelloInfo) (*tls.Certificate, error) {
|
||||||
cert := c.manual.cert
|
return c.Cert(), nil
|
||||||
if cert == nil {
|
|
||||||
cert = c.autoEncrypt.cert
|
|
||||||
}
|
|
||||||
|
|
||||||
return cert, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetClientCertificate is used when acting as a client and responding
|
// GetClientCertificate is used when acting as a client and responding
|
||||||
|
@ -477,6 +472,17 @@ func (c *Configurator) commonTLSConfig(verifyIncoming bool) *tls.Config {
|
||||||
return tlsConfig
|
return tlsConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function acquires a read lock because it reads from the config.
|
||||||
|
func (c *Configurator) Cert() *tls.Certificate {
|
||||||
|
c.RLock()
|
||||||
|
defer c.RUnlock()
|
||||||
|
cert := c.manual.cert
|
||||||
|
if cert == nil {
|
||||||
|
cert = c.autoEncrypt.cert
|
||||||
|
}
|
||||||
|
return cert
|
||||||
|
}
|
||||||
|
|
||||||
// This function acquires a read lock because it reads from the config.
|
// This function acquires a read lock because it reads from the config.
|
||||||
func (c *Configurator) VerifyIncomingRPC() bool {
|
func (c *Configurator) VerifyIncomingRPC() bool {
|
||||||
c.RLock()
|
c.RLock()
|
||||||
|
@ -561,6 +567,22 @@ func (c *Configurator) VerifyServerHostname() bool {
|
||||||
return c.base.VerifyServerHostname || c.autoEncrypt.verifyServerHostname
|
return c.base.VerifyServerHostname || c.autoEncrypt.verifyServerHostname
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IncomingGRPCConfig generates a *tls.Config for incoming GRPC connections.
|
||||||
|
func (c *Configurator) IncomingGRPCConfig() *tls.Config {
|
||||||
|
c.log("IncomingGRPCConfig")
|
||||||
|
|
||||||
|
// false has the effect that this config doesn't require a client cert
|
||||||
|
// verification. This is because there is no verify_incoming_grpc
|
||||||
|
// configuration option. And using verify_incoming would be backwards
|
||||||
|
// incompatible, because even if it was set before, it didn't have an
|
||||||
|
// effect on the grpc server.
|
||||||
|
config := c.commonTLSConfig(false)
|
||||||
|
config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) {
|
||||||
|
return c.IncomingGRPCConfig(), nil
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
// IncomingRPCConfig generates a *tls.Config for incoming RPC connections.
|
// IncomingRPCConfig generates a *tls.Config for incoming RPC connections.
|
||||||
func (c *Configurator) IncomingRPCConfig() *tls.Config {
|
func (c *Configurator) IncomingRPCConfig() *tls.Config {
|
||||||
c.log("IncomingRPCConfig")
|
c.log("IncomingRPCConfig")
|
||||||
|
|
|
@ -277,6 +277,10 @@ The options below are all specified on the command-line.
|
||||||
to an environment which communicates the HTTP port through the environment e.g. PaaS like CloudFoundry, allowing
|
to an environment which communicates the HTTP port through the environment e.g. PaaS like CloudFoundry, allowing
|
||||||
you to set the port directly via a Procfile.
|
you to set the port directly via a Procfile.
|
||||||
|
|
||||||
|
* <a name="_https_port"></a><a href="#_https_port">`-https-port`</a> - the HTTPS API
|
||||||
|
port to listen on. Default -1 (https disabled). See [ports](#ports)
|
||||||
|
documentation for more detail.
|
||||||
|
|
||||||
* <a name="_log_file"></a><a href="#_log_file">`-log-file`</a> - to redirect all the Consul agent log messages to a file. This can be specified with the complete path along with the name of the log. In case the path doesn't have the filename, the filename defaults to `consul-{timestamp}.log`. Can be combined with <a href="#_log_rotate_bytes"> -log-rotate-bytes</a> and <a href="#_log_rotate_duration"> -log-rotate-duration </a> for a fine-grained log rotation experience.
|
* <a name="_log_file"></a><a href="#_log_file">`-log-file`</a> - to redirect all the Consul agent log messages to a file. This can be specified with the complete path along with the name of the log. In case the path doesn't have the filename, the filename defaults to `consul-{timestamp}.log`. Can be combined with <a href="#_log_rotate_bytes"> -log-rotate-bytes</a> and <a href="#_log_rotate_duration"> -log-rotate-duration </a> for a fine-grained log rotation experience.
|
||||||
|
|
||||||
* <a name="_log_rotate_bytes"></a><a href="#_log_rotate_bytes">`-log-rotate-bytes`</a> - to specify the number of bytes that should be written to a log before it needs to be rotated. Unless specified, there is no limit to the number of bytes that can be written to a log file.
|
* <a name="_log_rotate_bytes"></a><a href="#_log_rotate_bytes">`-log-rotate-bytes`</a> - to specify the number of bytes that should be written to a log before it needs to be rotated. Unless specified, there is no limit to the number of bytes that can be written to a log file.
|
||||||
|
|
Loading…
Reference in New Issue