pomerium/internal/controlplane/xds_clusters.go
Caleb Doxsey dccec1e646 envoy: support autocert (#695)
* envoy: support autocert

* envoy: fallback to http host routing if sni fails to match

* update comment

* envoy: renew certs when necessary

* fix tests
2020-05-18 17:10:10 -04:00

106 lines
3.2 KiB
Go

package controlplane
import (
"net"
"net/url"
"strings"
"time"
envoy_config_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
envoy_config_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
envoy_config_endpoint_v3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3"
"github.com/golang/protobuf/ptypes"
"github.com/pomerium/pomerium/config"
"github.com/pomerium/pomerium/internal/urlutil"
)
func (srv *Server) buildClusters(options *config.Options) []*envoy_config_cluster_v3.Cluster {
grpcURL := &url.URL{
Scheme: "grpc",
Host: srv.GRPCListener.Addr().String(),
}
httpURL := &url.URL{
Scheme: "http",
Host: srv.HTTPListener.Addr().String(),
}
authzURL := &url.URL{
Scheme: strings.Replace(options.AuthorizeURL.Scheme, "http", "grpc", -1),
Host: options.AuthorizeURL.Host,
}
clusters := []*envoy_config_cluster_v3.Cluster{
srv.buildCluster("pomerium-control-plane-grpc", grpcURL),
srv.buildCluster("pomerium-control-plane-http", httpURL),
srv.buildCluster("pomerium-authz", authzURL),
}
if config.IsProxy(options.Services) {
type clusterDestination struct {
name, scheme, hostport string
}
clusterDestinations := map[clusterDestination]struct{}{}
for _, policy := range options.Policies {
name, scheme, hostport := srv.getClusterDetails(policy.Destination)
clusterDestinations[clusterDestination{name, scheme, hostport}] = struct{}{}
}
for dst := range clusterDestinations {
name, scheme, hostport := dst.name, dst.scheme, dst.hostport
clusters = append(clusters, srv.buildCluster(name, &url.URL{
Scheme: scheme,
Host: hostport,
}))
}
}
return clusters
}
func (srv *Server) getClusterDetails(endpoint *url.URL) (name, scheme, hostport string) {
name = endpoint.Scheme + "-" + strings.Replace(endpoint.Host, ":", "--", -1)
return name, endpoint.Scheme, endpoint.Host
}
func (srv *Server) buildCluster(name string, endpoint *url.URL) *envoy_config_cluster_v3.Cluster {
defaultPort := 80
if endpoint.Scheme == "https" || endpoint.Scheme == "grpcs" {
defaultPort = 443
}
cluster := &envoy_config_cluster_v3.Cluster{
Name: name,
ConnectTimeout: ptypes.DurationProto(time.Second * 10),
LoadAssignment: &envoy_config_endpoint_v3.ClusterLoadAssignment{
ClusterName: name,
Endpoints: []*envoy_config_endpoint_v3.LocalityLbEndpoints{{
LbEndpoints: []*envoy_config_endpoint_v3.LbEndpoint{{
HostIdentifier: &envoy_config_endpoint_v3.LbEndpoint_Endpoint{
Endpoint: &envoy_config_endpoint_v3.Endpoint{
Address: buildAddress(endpoint.Host, defaultPort),
},
},
}},
}},
},
RespectDnsTtl: true,
}
if endpoint.Scheme == "grpc" {
cluster.Http2ProtocolOptions = &envoy_config_core_v3.Http2ProtocolOptions{}
}
if endpoint.Scheme == "https" || endpoint.Scheme == "grpcs" {
cluster.TransportSocket = &envoy_config_core_v3.TransportSocket{
Name: "tls",
}
}
if net.ParseIP(urlutil.StripPort(endpoint.Host)) == nil {
cluster.ClusterDiscoveryType = &envoy_config_cluster_v3.Cluster_Type{Type: envoy_config_cluster_v3.Cluster_LOGICAL_DNS}
} else {
cluster.ClusterDiscoveryType = &envoy_config_cluster_v3.Cluster_Type{Type: envoy_config_cluster_v3.Cluster_STATIC}
}
return cluster
}