Documentation ¶
Index ¶
- Constants
- func CertURIFromConn(conn net.Conn) (connect.CertURI, error)
- func CommonNamesFromCertPool(p *x509.CertPool) ([]string, error)
- func ConsulResolverFromAddrFunc(client *api.Client) func(addr string) (Resolver, error)
- func PKIXNameFromRawSubject(raw []byte) (*pkix.Name, error)
- func TestCAPool(t testing.T, cas ...*structs.CARoot) *x509.CertPool
- func TestPeerCertificates(t testing.T, service string, ca *structs.CARoot) []*x509.Certificate
- func TestSvcKeyPair(t testing.T, service string, ca *structs.CARoot) tls.Certificate
- func TestTLSConfig(t testing.T, service string, ca *structs.CARoot) *tls.Config
- type ConsulResolver
- type Resolver
- type Service
- func NewDevServiceFromCertFiles(serviceID string, logger *log.Logger, caFile, certFile, keyFile string) (*Service, error)
- func NewDevServiceWithTLSConfig(serviceName string, logger *log.Logger, tlsCfg *tls.Config) (*Service, error)
- func NewService(serviceName string, client *api.Client) (*Service, error)
- func NewServiceWithLogger(serviceName string, client *api.Client, logger *log.Logger) (*Service, error)
- func TestService(t testing.T, service string, ca *structs.CARoot) *Service
- func (s *Service) Close() error
- func (s *Service) Dial(ctx context.Context, resolver Resolver) (net.Conn, error)
- func (s *Service) HTTPClient() *http.Client
- func (s *Service) HTTPDialTLS(network, addr string) (net.Conn, error)
- func (s *Service) Name() string
- func (s *Service) Ready() bool
- func (s *Service) ReadyWait() <-chan struct{}
- func (s *Service) ServerTLSConfig() *tls.Config
- type StaticResolver
- type TestServer
Examples ¶
Constants ¶
const ( // ConsulResolverTypeService indicates resolving healthy service nodes. ConsulResolverTypeService int = iota // ConsulResolverTypePreparedQuery indicates resolving via prepared query. ConsulResolverTypePreparedQuery )
Variables ¶
This section is empty.
Functions ¶
func CertURIFromConn ¶
CertURIFromConn is a helper to extract the service identifier URI from a net.Conn. If the net.Conn is not a *tls.Conn then an error is always returned. If the *tls.Conn didn't present a valid connect certificate, or is not yet past the handshake, an error is returned.
func CommonNamesFromCertPool ¶ added in v1.3.0
CommonNamesFromCertPool returns the common names of the certificates in the cert pool.
func ConsulResolverFromAddrFunc ¶ added in v1.2.2
ConsulResolverFromAddrFunc returns a function for constructing ConsulResolver from a consul DNS formatted hostname (e.g. foo.service.consul or foo.query.consul).
Note, the returned ConsulResolver resolves the query via regular agent HTTP discovery API. DNS is not needed or used for discovery, only the hostname format re-used for consistency.
func PKIXNameFromRawSubject ¶ added in v1.3.0
PKIXNameFromRawSubject attempts to parse a DER encoded "Subject" as a PKIX Name. It's useful for inspecting root certificates in an x509.CertPool which only expose RawSubject via the Subjects method.
func TestCAPool ¶
TestCAPool returns an *x509.CertPool containing the passed CA's root(s)
func TestPeerCertificates ¶
TestPeerCertificates returns a []*x509.Certificate as you'd get from tls.Conn.ConnectionState().PeerCertificates including the named certificate.
func TestSvcKeyPair ¶
TestSvcKeyPair returns an tls.Certificate containing both cert and private key for a given service under a given CA from the testdata dir.
Types ¶
type ConsulResolver ¶
type ConsulResolver struct { // Client is the Consul API client to use. Must be non-nil or Resolve will // panic. Client *api.Client // Namespace of the query target. Namespace string // Name of the query target. Name string // Type of the query target. Should be one of the defined ConsulResolverType* // constants. Currently defaults to ConsulResolverTypeService. Type int // Datacenter to resolve in, empty indicates agent's local DC. Datacenter string }
ConsulResolver queries Consul for a service instance.
type Resolver ¶
type Resolver interface { // Resolve returns a single service instance to connect to. Implementations // may attempt to ensure the instance returned is currently available. It is // expected that a client will re-dial on a connection failure so making an // effort to return a different service instance each time where available // increases reliability. The context passed can be used to impose timeouts // which may or may not be respected by implementations that make network // calls to resolve the service. The addr returned is a string in any valid // form for passing directly to `net.Dial("tcp", addr)`. The certURI // represents the identity of the service instance. It will be matched against // the TLS certificate URI SAN presented by the server and the connection // rejected if they don't match. Resolve(ctx context.Context) (addr string, certURI connect.CertURI, err error) }
Resolver is the interface implemented by a service discovery mechanism to get the address and identity of an instance to connect to via Connect as a client.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service represents a Consul service that accepts and/or connects via Connect. This can represent a service that only is a server, only is a client, or both.
TODO(banks): Agent implicit health checks based on knowing which certs are available should prevent clients being routed until the agent knows the service has been delivered valid certificates. Once built, document that here too.
func NewDevServiceFromCertFiles ¶
func NewDevServiceFromCertFiles(serviceID string, logger *log.Logger, caFile, certFile, keyFile string) (*Service, error)
NewDevServiceFromCertFiles creates a Service using certificate and key files passed instead of fetching them from the client.
func NewDevServiceWithTLSConfig ¶
func NewDevServiceWithTLSConfig(serviceName string, logger *log.Logger, tlsCfg *tls.Config) (*Service, error)
NewDevServiceWithTLSConfig creates a Service using static TLS config passed. It's mostly useful for testing.
func NewService ¶
NewService creates and starts a Service. The caller must close the returned service to free resources and allow the program to exit normally. This is typically called in a signal handler.
Caller must provide client which is already configured to speak to the local Consul agent, and with an ACL token that has `service:write` privileges for the service specified.
func NewServiceWithLogger ¶
func NewServiceWithLogger(serviceName string, client *api.Client, logger *log.Logger) (*Service, error)
NewServiceWithLogger starts the service with a specified log.Logger.
func TestService ¶
TestService returns a Service instance based on a static TLS Config.
func (*Service) Dial ¶
Dial connects to a remote Connect-enabled server. The passed Resolver is used to discover a single candidate instance which will be dialed and have it's TLS certificate verified against the expected identity. Failures are returned directly with no retries. Repeated dials may use different instances depending on the Resolver implementation.
Timeout can be managed via the Context.
Calls to Dial made before the Service has loaded certificates from the agent will fail. You can prevent this by using Ready or ReadyWait in app during startup.
func (*Service) HTTPClient ¶
HTTPClient returns an *http.Client configured to dial remote Consul Connect HTTP services. The client will return an error if attempting to make requests to a non HTTPS hostname. It resolves the domain of the request with the same syntax as Consul DNS queries although it performs discovery directly via the API rather than just relying on Consul DNS. Hostnames that are not valid Consul DNS queries will fail.
Example ¶
Note: this assumes a suitable Consul ACL token with 'service:write' for service 'web' is set in CONSUL_HTTP_TOKEN ENV var.
client, _ := api.NewClient(api.DefaultConfig()) svc, _ := NewService("web", client) httpClient := svc.HTTPClient() resp, _ := httpClient.Get("https://web.service.consul/foo/bar") handleResponse(resp)
Output:
func (*Service) HTTPDialTLS ¶
HTTPDialTLS is compatible with http.Transport.DialTLS. It expects the addr hostname to be specified using Consul DNS query syntax, e.g. "web.service.consul". It converts that into the equivalent ConsulResolver and then call s.Dial with the resolver. This is low level, clients should typically use HTTPClient directly.
func (*Service) Name ¶
Name returns the name of the service this object represents. Note it is the service _name_ as used during discovery, not the ID used to uniquely identify an instance of the service with an agent.
func (*Service) Ready ¶
Ready returns whether or not both roots and a leaf certificate are configured. If both are non-nil, they are assumed to be valid and usable.
func (*Service) ReadyWait ¶
func (s *Service) ReadyWait() <-chan struct{}
ReadyWait returns a chan that is closed when the the Service becomes ready for use for the first time. Note that if the Service is ready when it is called it returns a nil chan. Ready means that it has root and leaf certificates configured which we assume are valid. The service may subsequently stop being "ready" if it's certificates expire or are revoked and an error prevents new ones being loaded but this method will not stop returning a nil chan in that case. It is only useful for initial startup. For ongoing health Ready() should be used.
func (*Service) ServerTLSConfig ¶
ServerTLSConfig returns a *tls.Config that allows any TCP listener to accept and authorize incoming Connect clients. It will return a single static config with hooks to dynamically load certificates, and perform Connect authorization during verification. Service implementations do not need to reload this to get new certificates.
At any time it may be possible that the Service instance does not have access to usable certificates due to not being initially setup yet or a prolonged error during renewal. The listener will be able to accept connections again once connectivity is restored provided the client's Token is valid.
To prevent routing traffic to the app instance while it's certificates are invalid or not populated yet you may use Ready in a health check endpoint and/or ReadyWait during startup before starting the TLS listener. The latter only prevents connections during initial bootstrap (including permission issues where certs can never be issued due to bad credentials) but won't handle the case that certificates expire and an error prevents timely renewal.
Example (HTTP) ¶
Note: this assumes a suitable Consul ACL token with 'service:write' for service 'web' is set in CONSUL_HTTP_TOKEN ENV var.
client, _ := api.NewClient(api.DefaultConfig()) svc, _ := NewService("web", client) server := &http.Server{ Addr: ":8080", Handler: apiHandler{}, TLSConfig: svc.ServerTLSConfig(), } // Cert and key files are blank since the tls.Config will handle providing // those dynamically. log.Fatal(server.ListenAndServeTLS("", ""))
Output:
Example (TLS) ¶
Note: this assumes a suitable Consul ACL token with 'service:write' for service 'web' is set in CONSUL_HTTP_TOKEN ENV var.
client, _ := api.NewClient(api.DefaultConfig()) svc, _ := NewService("web", client) l, _ := tls.Listen("tcp", ":8080", svc.ServerTLSConfig()) acceptLoop(l)
Output:
type StaticResolver ¶
type StaticResolver struct { // Addr is the network address (including port) of the instance. It must be // the connect-enabled mTLS listener and may be a proxy in front of the actual // target service process. It is a string in any valid form for passing // directly to net.Dial("tcp", addr). Addr string // CertURL is the identity we expect the server to present in it's TLS // certificate. It must be an exact URI string match or the connection will be // rejected. CertURI connect.CertURI }
StaticResolver is a statically defined resolver. This can be used to Dial a known Connect endpoint without performing service discovery.
type TestServer ¶
type TestServer struct { // The service name to serve. Service string // The (test) CA to use for generating certs. CA *structs.CARoot // TimeoutHandshake controls whether the listening server will complete a TLS // handshake quickly enough. TimeoutHandshake bool // TLSCfg is the tls.Config that will be used. By default it's set up from the // service and ca set. TLSCfg *tls.Config // Addr is the listen address. It is set to a random free port on `localhost` // by default. Addr string // Listening is closed when the listener is run. Listening chan struct{} // contains filtered or unexported fields }
TestServer runs a service listener that can be used to test clients. It's behavior can be controlled by the struct members.
func NewTestServer ¶
NewTestServer returns a TestServer. It should be closed when test is complete.
func (*TestServer) Serve ¶
func (s *TestServer) Serve() error
Serve runs a tcp echo server and blocks until it is closed or errors. If TimeoutHandshake is set it won't start TLS handshake on new connections.
func (*TestServer) ServeHTTPS ¶
func (s *TestServer) ServeHTTPS(h http.Handler) error
ServeHTTPS runs an HTTPS server with the given config. It invokes the passed Handler for all requests.
Directories ¶
Path | Synopsis |
---|---|
certgen: a tool for generating test certificates on disk for use as test-fixtures and for end-to-end testing and local development.
|
certgen: a tool for generating test certificates on disk for use as test-fixtures and for end-to-end testing and local development. |