mirror of
https://github.com/pomerium/pomerium.git
synced 2025-04-28 09:56:31 +02:00
169 lines
4.3 KiB
Go
169 lines
4.3 KiB
Go
package envoyconfig
|
|
|
|
import (
|
|
"cmp"
|
|
"context"
|
|
"net/url"
|
|
"strings"
|
|
|
|
envoy_config_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
|
|
"github.com/hashicorp/go-set/v3"
|
|
"google.golang.org/protobuf/types/known/wrapperspb"
|
|
|
|
"github.com/pomerium/pomerium/config"
|
|
"github.com/pomerium/pomerium/internal/urlutil"
|
|
"github.com/pomerium/pomerium/pkg/telemetry/trace"
|
|
)
|
|
|
|
// 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) {
|
|
ctx, span := trace.Continue(ctx, "envoyconfig.Builder.BuildRouteConfigurations")
|
|
defer span.End()
|
|
|
|
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(
|
|
_ context.Context,
|
|
cfg *config.Config,
|
|
) (*envoy_config_route_v3.RouteConfiguration, error) {
|
|
authorizeURLs, err := cfg.Options.GetInternalAuthorizeURLs()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
dataBrokerURLs, err := cfg.Options.GetInternalDataBrokerURLs()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
allHosts, mcpHosts, err := getAllRouteableHosts(cfg.Options, cfg.Options.Addr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var virtualHosts []*envoy_config_route_v3.VirtualHost
|
|
for _, host := range allHosts {
|
|
vh, err := b.buildVirtualHost(cfg.Options, host, host, mcpHosts[host])
|
|
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.buildRoutesForPoliciesWithHost(cfg, 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
|
|
}
|
|
if config.IsProxy(cfg.Options.Services) {
|
|
rs, err := b.buildRoutesForPoliciesWithCatchAll(cfg)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
vh.Routes = append(vh.Routes, rs...)
|
|
}
|
|
|
|
virtualHosts = append(virtualHosts, vh)
|
|
|
|
rc := newRouteConfiguration("main", virtualHosts)
|
|
return rc, nil
|
|
}
|
|
|
|
func getAllRouteableHosts(options *config.Options, addr string) ([]string, map[string]bool, error) {
|
|
allHosts := set.NewTreeSet(cmp.Compare[string])
|
|
mcpHosts := make(map[string]bool)
|
|
|
|
if addr == options.Addr {
|
|
hosts, hostsMCP, err := options.GetAllRouteableHTTPHosts()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
allHosts.InsertSlice(hosts)
|
|
// Merge any MCP hosts
|
|
for host, isMCP := range hostsMCP {
|
|
if isMCP {
|
|
mcpHosts[host] = true
|
|
}
|
|
}
|
|
}
|
|
|
|
if addr == options.GetGRPCAddr() {
|
|
hosts, err := options.GetAllRouteableGRPCHosts()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
allHosts.InsertSlice(hosts)
|
|
}
|
|
|
|
var filtered []string
|
|
for host := range allHosts.Items() {
|
|
if !strings.Contains(host, "*") {
|
|
filtered = append(filtered, host)
|
|
}
|
|
}
|
|
return filtered, mcpHosts, nil
|
|
}
|
|
|
|
func newRouteConfiguration(name string, virtualHosts []*envoy_config_route_v3.VirtualHost) *envoy_config_route_v3.RouteConfiguration {
|
|
return &envoy_config_route_v3.RouteConfiguration{
|
|
Name: name,
|
|
VirtualHosts: virtualHosts,
|
|
// disable cluster validation since the order of LDS/CDS updates isn't guaranteed
|
|
ValidateClusters: &wrapperspb.BoolValue{Value: false},
|
|
}
|
|
}
|
|
|
|
func urlsMatchHost(urls []*url.URL, host string) bool {
|
|
for _, u := range urls {
|
|
if urlMatchesHost(u, host) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func urlMatchesHost(u *url.URL, host string) bool {
|
|
for _, h := range urlutil.GetDomainsForURL(u, true) {
|
|
if h == host {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|