support loading route configuration via rds

This commit is contained in:
Caleb Doxsey 2023-04-04 13:45:19 -06:00
parent 850a903341
commit d23a110e6e
3 changed files with 131 additions and 64 deletions

View file

@ -257,61 +257,6 @@ func (b *Builder) buildMainHTTPConnectionManagerFilter(
options *config.Options,
certs ...tls.Certificate,
) (*envoy_config_listener_v3.Filter, error) {
authorizeURLs, err := options.GetInternalAuthorizeURLs()
if err != nil {
return nil, err
}
dataBrokerURLs, err := options.GetInternalDataBrokerURLs()
if err != nil {
return nil, err
}
allHosts, err := getAllRouteableHosts(options, options.Addr)
if err != nil {
return nil, err
}
var virtualHosts []*envoy_config_route_v3.VirtualHost
for _, host := range allHosts {
requireStrictTransportSecurity := cryptutil.HasCertificateForServerName(certs, host)
vh, err := b.buildVirtualHost(options, host, host, requireStrictTransportSecurity)
if err != nil {
return nil, err
}
if options.Addr == options.GetGRPCAddr() {
// if this is a gRPC service domain and we're supposed to handle that, add those routes
if (config.IsAuthorize(options.Services) && urlsMatchHost(authorizeURLs, host)) ||
(config.IsDataBroker(options.Services) && urlsMatchHost(dataBrokerURLs, host)) {
rs, err := b.buildGRPCRoutes()
if err != nil {
return nil, err
}
vh.Routes = append(vh.Routes, rs...)
}
}
// if we're the proxy, add all the policy routes
if config.IsProxy(options.Services) {
rs, err := b.buildPolicyRoutes(options, host)
if err != nil {
return nil, err
}
vh.Routes = append(vh.Routes, rs...)
}
if len(vh.Routes) > 0 {
virtualHosts = append(virtualHosts, vh)
}
}
vh, err := b.buildVirtualHost(options, "catch-all", "*", false)
if err != nil {
return nil, err
}
virtualHosts = append(virtualHosts, vh)
var grpcClientTimeout *durationpb.Duration
if options.GRPCClientTimeout != 0 {
grpcClientTimeout = durationpb.New(options.GRPCClientTimeout)
@ -333,10 +278,6 @@ func (b *Builder) buildMainHTTPConnectionManagerFilter(
maxStreamDuration = durationpb.New(options.WriteTimeout)
}
rc, err := b.buildRouteConfiguration("main", virtualHosts)
if err != nil {
return nil, err
}
tracingProvider, err := buildTracingHTTP(options)
if err != nil {
return nil, err
@ -347,8 +288,14 @@ func (b *Builder) buildMainHTTPConnectionManagerFilter(
CodecType: options.GetCodecType().ToEnvoy(),
StatPrefix: "ingress",
RouteSpecifier: &envoy_http_connection_manager.HttpConnectionManager_RouteConfig{
RouteConfig: rc,
RouteSpecifier: &envoy_http_connection_manager.HttpConnectionManager_Rds{
Rds: &envoy_http_connection_manager.Rds{
ConfigSource: &envoy_config_core_v3.ConfigSource{
ResourceApiVersion: envoy_config_core_v3.ApiVersion_V3,
ConfigSourceSpecifier: &envoy_config_core_v3.ConfigSource_Ads{},
},
RouteConfigName: "main",
},
},
HttpFilters: filters,
AccessLog: buildAccessLogs(options),
@ -546,7 +493,8 @@ func (b *Builder) buildDownstreamTLSContextMulti(
TlsCertificates: envoyCerts,
AlpnProtocols: getALPNProtos(cfg.Options),
ValidationContextType: b.buildDownstreamValidationContext(ctx, cfg),
}}, nil
},
}, nil
}
func getALPNProtos(opts *config.Options) []string {

View file

@ -0,0 +1,105 @@
package envoyconfig
import (
"context"
"crypto/tls"
envoy_config_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
"github.com/pomerium/pomerium/config"
"github.com/pomerium/pomerium/pkg/cryptutil"
)
// BuildRouteConfigurations builds the route configurations for the RDS service.
func (b *Builder) BuildRouteConfigurations(
ctx context.Context,
cfg *config.Config,
) ([]*envoy_config_route_v3.RouteConfiguration, error) {
var routeConfigurations []*envoy_config_route_v3.RouteConfiguration
if config.IsAuthenticate(cfg.Options.Services) || config.IsProxy(cfg.Options.Services) {
rc, err := b.buildMainRouteConfiguration(ctx, cfg)
if err != nil {
return nil, err
}
routeConfigurations = append(routeConfigurations, rc)
}
return routeConfigurations, nil
}
func (b *Builder) buildMainRouteConfiguration(
ctx context.Context,
cfg *config.Config,
) (*envoy_config_route_v3.RouteConfiguration, error) {
var certs []tls.Certificate
if !cfg.Options.InsecureServer {
var err error
certs, err = getAllCertificates(cfg)
if err != nil {
return nil, err
}
}
authorizeURLs, err := cfg.Options.GetInternalAuthorizeURLs()
if err != nil {
return nil, err
}
dataBrokerURLs, err := cfg.Options.GetInternalDataBrokerURLs()
if err != nil {
return nil, err
}
allHosts, err := getAllRouteableHosts(cfg.Options, cfg.Options.Addr)
if err != nil {
return nil, err
}
var virtualHosts []*envoy_config_route_v3.VirtualHost
for _, host := range allHosts {
requireStrictTransportSecurity := cryptutil.HasCertificateForServerName(certs, host)
vh, err := b.buildVirtualHost(cfg.Options, host, host, requireStrictTransportSecurity)
if err != nil {
return nil, err
}
if cfg.Options.Addr == cfg.Options.GetGRPCAddr() {
// if this is a gRPC service domain and we're supposed to handle that, add those routes
if (config.IsAuthorize(cfg.Options.Services) && urlsMatchHost(authorizeURLs, host)) ||
(config.IsDataBroker(cfg.Options.Services) && urlsMatchHost(dataBrokerURLs, host)) {
rs, err := b.buildGRPCRoutes()
if err != nil {
return nil, err
}
vh.Routes = append(vh.Routes, rs...)
}
}
// if we're the proxy, add all the policy routes
if config.IsProxy(cfg.Options.Services) {
rs, err := b.buildPolicyRoutes(cfg.Options, host)
if err != nil {
return nil, err
}
vh.Routes = append(vh.Routes, rs...)
}
if len(vh.Routes) > 0 {
virtualHosts = append(virtualHosts, vh)
}
}
vh, err := b.buildVirtualHost(cfg.Options, "catch-all", "*", false)
if err != nil {
return nil, err
}
virtualHosts = append(virtualHosts, vh)
rc, err := b.buildRouteConfiguration("main", virtualHosts)
if err != nil {
return nil, err
}
return rc, nil
}

View file

@ -11,8 +11,9 @@ import (
)
const (
clusterTypeURL = "type.googleapis.com/envoy.config.cluster.v3.Cluster"
listenerTypeURL = "type.googleapis.com/envoy.config.listener.v3.Listener"
clusterTypeURL = "type.googleapis.com/envoy.config.cluster.v3.Cluster"
listenerTypeURL = "type.googleapis.com/envoy.config.listener.v3.Listener"
routeConfigurationTypeURL = "type.googleapis.com/envoy.config.route.v3.RouteConfiguration"
)
func (srv *Server) buildDiscoveryResources(ctx context.Context) (map[string][]*envoy_service_discovery_v3.Resource, error) {
@ -44,5 +45,18 @@ func (srv *Server) buildDiscoveryResources(ctx context.Context) (map[string][]*e
Resource: any,
})
}
routeConfigurations, err := srv.Builder.BuildRouteConfigurations(ctx, cfg.Config)
if err != nil {
return nil, err
}
for _, routeConfiguration := range routeConfigurations {
resources[routeConfigurationTypeURL] = append(resources[routeConfigurationTypeURL], &envoy_service_discovery_v3.Resource{
Name: routeConfiguration.Name,
Version: hex.EncodeToString(cryptutil.HashProto(routeConfiguration)),
Resource: protoutil.NewAny(routeConfiguration),
})
}
return resources, nil
}