open-consul/agent/structs/connect.go
Paul Banks 10af44006a Proxy Config Manager (#4729)
* Proxy Config Manager

This component watches for local state changes on the agent and ensures that each service registered locally with Kind == connect-proxy has it's state being actively populated in the cache.

This serves two purposes:
 1. For the built-in proxy, it ensures that the state needed to accept connections is available in RAM shortly after registration and likely before the proxy actually starts accepting traffic.
 2. For (future - next PR) xDS server and other possible future proxies that require _push_ based config discovery, this provides a mechanism to subscribe and be notified about updates to a proxy instance's config including upstream service discovery results.

* Address review comments

* Better comments; Better delivery of latest snapshot for slow watchers; Embed Config

* Comment typos

* Add upstream Stringer for funsies
2018-10-10 16:55:34 +01:00

142 lines
4.8 KiB
Go

package structs
import (
"fmt"
"github.com/mitchellh/mapstructure"
)
// ConnectAuthorizeRequest is the structure of a request to authorize
// a connection.
type ConnectAuthorizeRequest struct {
// Target is the name of the service that is being requested.
Target string
// ClientCertURI is a unique identifier for the requesting client. This
// is currently the URI SAN from the TLS client certificate.
//
// ClientCertSerial is a colon-hex-encoded of the serial number for
// the requesting client cert. This is used to check against revocation
// lists.
ClientCertURI string
ClientCertSerial string
}
// ProxyExecMode encodes the mode for running a managed connect proxy.
type ProxyExecMode int
const (
// ProxyExecModeUnspecified uses the global default proxy mode.
ProxyExecModeUnspecified ProxyExecMode = iota
// ProxyExecModeDaemon executes a proxy process as a supervised daemon.
ProxyExecModeDaemon
// ProxyExecModeScript executes a proxy config script on each change to it's
// config.
ProxyExecModeScript
// ProxyExecModeTest tracks the start/stop of the proxy in-memory
// and is only used for tests. This shouldn't be set outside of tests,
// but even if it is it has no external effect.
ProxyExecModeTest
)
// NewProxyExecMode returns the proper ProxyExecMode for the given string value.
func NewProxyExecMode(raw string) (ProxyExecMode, error) {
switch raw {
case "":
return ProxyExecModeUnspecified, nil
case "daemon":
return ProxyExecModeDaemon, nil
case "script":
return ProxyExecModeScript, nil
default:
return 0, fmt.Errorf("invalid exec mode: %s", raw)
}
}
// String implements Stringer
func (m ProxyExecMode) String() string {
switch m {
case ProxyExecModeUnspecified:
return "global_default"
case ProxyExecModeDaemon:
return "daemon"
case ProxyExecModeScript:
return "script"
case ProxyExecModeTest:
return "test"
default:
return "unknown"
}
}
// ConnectManagedProxy represents the agent-local state for a configured proxy
// instance. This is never stored or sent to the servers and is only used to
// store the config for the proxy that the agent needs to track. For now it's
// really generic with only the fields the agent needs to act on defined while
// the rest of the proxy config is passed as opaque bag of attributes to support
// arbitrary config params for third-party proxy integrations. "External"
// proxies by definition register themselves and manage their own config
// externally so are never represented in agent state.
type ConnectManagedProxy struct {
// ExecMode is one of daemon or script.
ExecMode ProxyExecMode
// Command is the command to execute. Empty defaults to self-invoking the same
// consul binary with proxy subcomand for ProxyExecModeDaemon and is an error
// for ProxyExecModeScript.
Command []string
// Config is the arbitrary configuration data provided with the registration.
Config map[string]interface{}
// Upstreams are the dependencies the proxy should setup outgoing listners for.
Upstreams Upstreams
// ProxyService is a pointer to the local proxy's service record for
// convenience. The proxies ID and name etc. can be read from there. It may be
// nil if the agent is starting up and hasn't registered the service yet. We
// ignore it when calculating the hash value since the only thing that effects
// the proxy's config is the ID of the target service which is already
// represented below.
ProxyService *NodeService `hash:"ignore"`
// TargetServiceID is the ID of the target service on the localhost. It may
// not exist yet since bootstrapping is allowed to happen in either order.
TargetServiceID string
}
// ConnectManagedProxyConfig represents the parts of the proxy config the agent
// needs to understand. It's bad UX to make the user specify these separately
// just to make parsing simpler for us so this encapsulates the fields in
// ConnectManagedProxy.Config that we care about. They are all optional anyway
// and this is used to decode them with mapstructure.
type ConnectManagedProxyConfig struct {
BindAddress string `mapstructure:"bind_address"`
BindPort int `mapstructure:"bind_port"`
LocalServiceAddress string `mapstructure:"local_service_address"`
LocalServicePort int `mapstructure:"local_service_port"`
}
// ParseConfig attempts to read the fields we care about from the otherwise
// opaque config map. They are all optional but it may fail if one is specified
// but an invalid value.
func (p *ConnectManagedProxy) ParseConfig() (*ConnectManagedProxyConfig, error) {
var cfg ConnectManagedProxyConfig
d, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
ErrorUnused: false,
WeaklyTypedInput: true, // allow string port etc.
Result: &cfg,
})
if err != nil {
return nil, err
}
err = d.Decode(p.Config)
if err != nil {
return nil, err
}
return &cfg, nil
}