mirror of
https://github.com/pomerium/pomerium.git
synced 2025-04-29 10:26:29 +02:00
config: add support for downstream TLS server name (#3243)
* config: add support for downstream TLS server name * fix whitespace * fix whitespace * add docs * add tls_upstream_server_name and tls_downstream_server_name to config * Update docs/reference/settings.yaml Co-authored-by: Alex Fornuto <afornuto@pomerium.com> * Update docs/reference/readme.md Co-authored-by: Alex Fornuto <afornuto@pomerium.com> * add deprecation notice Co-authored-by: Alex Fornuto <afornuto@pomerium.com>
This commit is contained in:
parent
e1403e33b4
commit
b79f1e379f
12 changed files with 837 additions and 614 deletions
|
@ -267,6 +267,9 @@ func (b *Builder) buildPolicyTransportSocket(
|
||||||
if policy.TLSServerName != "" {
|
if policy.TLSServerName != "" {
|
||||||
sni = policy.TLSServerName
|
sni = policy.TLSServerName
|
||||||
}
|
}
|
||||||
|
if policy.TLSUpstreamServerName != "" {
|
||||||
|
sni = policy.TLSUpstreamServerName
|
||||||
|
}
|
||||||
tlsContext := &envoy_extensions_transport_sockets_tls_v3.UpstreamTlsContext{
|
tlsContext := &envoy_extensions_transport_sockets_tls_v3.UpstreamTlsContext{
|
||||||
CommonTlsContext: &envoy_extensions_transport_sockets_tls_v3.CommonTlsContext{
|
CommonTlsContext: &envoy_extensions_transport_sockets_tls_v3.CommonTlsContext{
|
||||||
TlsParams: &envoy_extensions_transport_sockets_tls_v3.TlsParameters{
|
TlsParams: &envoy_extensions_transport_sockets_tls_v3.TlsParameters{
|
||||||
|
@ -320,9 +323,16 @@ func (b *Builder) buildPolicyValidationContext(
|
||||||
policy *config.Policy,
|
policy *config.Policy,
|
||||||
dst url.URL,
|
dst url.URL,
|
||||||
) (*envoy_extensions_transport_sockets_tls_v3.CertificateValidationContext, error) {
|
) (*envoy_extensions_transport_sockets_tls_v3.CertificateValidationContext, error) {
|
||||||
|
overrideName := ""
|
||||||
|
if policy.TLSServerName != "" {
|
||||||
|
overrideName = policy.TLSServerName
|
||||||
|
}
|
||||||
|
if policy.TLSUpstreamServerName != "" {
|
||||||
|
overrideName = policy.TLSUpstreamServerName
|
||||||
|
}
|
||||||
validationContext := &envoy_extensions_transport_sockets_tls_v3.CertificateValidationContext{
|
validationContext := &envoy_extensions_transport_sockets_tls_v3.CertificateValidationContext{
|
||||||
MatchTypedSubjectAltNames: []*envoy_extensions_transport_sockets_tls_v3.SubjectAltNameMatcher{
|
MatchTypedSubjectAltNames: []*envoy_extensions_transport_sockets_tls_v3.SubjectAltNameMatcher{
|
||||||
b.buildSubjectAltNameMatcher(&dst, policy.TLSServerName),
|
b.buildSubjectAltNameMatcher(&dst, overrideName),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if policy.TLSCustomCAFile != "" {
|
if policy.TLSCustomCAFile != "" {
|
||||||
|
|
|
@ -111,21 +111,75 @@ func Test_buildPolicyTransportSocket(t *testing.T) {
|
||||||
"alpnProtocols": ["h2", "http/1.1"],
|
"alpnProtocols": ["h2", "http/1.1"],
|
||||||
"tlsParams": {
|
"tlsParams": {
|
||||||
"cipherSuites": [
|
"cipherSuites": [
|
||||||
"ECDHE-ECDSA-AES256-GCM-SHA384",
|
"ECDHE-ECDSA-AES256-GCM-SHA384",
|
||||||
"ECDHE-RSA-AES256-GCM-SHA384",
|
"ECDHE-RSA-AES256-GCM-SHA384",
|
||||||
"ECDHE-ECDSA-AES128-GCM-SHA256",
|
"ECDHE-ECDSA-AES128-GCM-SHA256",
|
||||||
"ECDHE-RSA-AES128-GCM-SHA256",
|
"ECDHE-RSA-AES128-GCM-SHA256",
|
||||||
"ECDHE-ECDSA-CHACHA20-POLY1305",
|
"ECDHE-ECDSA-CHACHA20-POLY1305",
|
||||||
"ECDHE-RSA-CHACHA20-POLY1305",
|
"ECDHE-RSA-CHACHA20-POLY1305",
|
||||||
"ECDHE-ECDSA-AES128-SHA",
|
"ECDHE-ECDSA-AES128-SHA",
|
||||||
"ECDHE-RSA-AES128-SHA",
|
"ECDHE-RSA-AES128-SHA",
|
||||||
"AES128-GCM-SHA256",
|
"AES128-GCM-SHA256",
|
||||||
"AES128-SHA",
|
"AES128-SHA",
|
||||||
"ECDHE-ECDSA-AES256-SHA",
|
"ECDHE-ECDSA-AES256-SHA",
|
||||||
"ECDHE-RSA-AES256-SHA",
|
"ECDHE-RSA-AES256-SHA",
|
||||||
"AES256-GCM-SHA384",
|
"AES256-GCM-SHA384",
|
||||||
"AES256-SHA"
|
"AES256-SHA"
|
||||||
],
|
],
|
||||||
|
"ecdhCurves": [
|
||||||
|
"X25519",
|
||||||
|
"P-256",
|
||||||
|
"P-384",
|
||||||
|
"P-521"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"validationContext": {
|
||||||
|
"matchTypedSubjectAltNames": [{
|
||||||
|
"sanType": "DNS",
|
||||||
|
"matcher": {
|
||||||
|
"exact": "use-this-name.example.com"
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"trustedCa": {
|
||||||
|
"filename": "`+rootCA+`"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sni": "use-this-name.example.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`, ts)
|
||||||
|
})
|
||||||
|
t.Run("tls_upstream_server_name as sni", func(t *testing.T) {
|
||||||
|
ts, err := b.buildPolicyTransportSocket(ctx, o1, &config.Policy{
|
||||||
|
To: mustParseWeightedURLs(t, "https://example.com"),
|
||||||
|
TLSUpstreamServerName: "use-this-name.example.com",
|
||||||
|
}, *mustParseURL(t, "https://example.com"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
testutil.AssertProtoJSONEqual(t, `
|
||||||
|
{
|
||||||
|
"name": "tls",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
|
||||||
|
"commonTlsContext": {
|
||||||
|
"alpnProtocols": ["h2", "http/1.1"],
|
||||||
|
"tlsParams": {
|
||||||
|
"cipherSuites": [
|
||||||
|
"ECDHE-ECDSA-AES256-GCM-SHA384",
|
||||||
|
"ECDHE-RSA-AES256-GCM-SHA384",
|
||||||
|
"ECDHE-ECDSA-AES128-GCM-SHA256",
|
||||||
|
"ECDHE-RSA-AES128-GCM-SHA256",
|
||||||
|
"ECDHE-ECDSA-CHACHA20-POLY1305",
|
||||||
|
"ECDHE-RSA-CHACHA20-POLY1305",
|
||||||
|
"ECDHE-ECDSA-AES128-SHA",
|
||||||
|
"ECDHE-RSA-AES128-SHA",
|
||||||
|
"AES128-GCM-SHA256",
|
||||||
|
"AES128-SHA",
|
||||||
|
"ECDHE-ECDSA-AES256-SHA",
|
||||||
|
"ECDHE-RSA-AES256-SHA",
|
||||||
|
"AES256-GCM-SHA384",
|
||||||
|
"AES256-SHA"
|
||||||
|
],
|
||||||
"ecdhCurves": [
|
"ecdhCurves": [
|
||||||
"X25519",
|
"X25519",
|
||||||
"P-256",
|
"P-256",
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
"sort"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
envoy_config_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
|
envoy_config_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
|
||||||
|
@ -20,7 +19,6 @@ import (
|
||||||
envoy_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3"
|
envoy_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3"
|
||||||
"github.com/golang/protobuf/ptypes/any"
|
"github.com/golang/protobuf/ptypes/any"
|
||||||
"github.com/golang/protobuf/ptypes/wrappers"
|
"github.com/golang/protobuf/ptypes/wrappers"
|
||||||
"github.com/scylladb/go-set"
|
|
||||||
"google.golang.org/protobuf/types/known/durationpb"
|
"google.golang.org/protobuf/types/known/durationpb"
|
||||||
"google.golang.org/protobuf/types/known/emptypb"
|
"google.golang.org/protobuf/types/known/emptypb"
|
||||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||||
|
@ -28,7 +26,7 @@ import (
|
||||||
"github.com/pomerium/pomerium/config"
|
"github.com/pomerium/pomerium/config"
|
||||||
"github.com/pomerium/pomerium/internal/hashutil"
|
"github.com/pomerium/pomerium/internal/hashutil"
|
||||||
"github.com/pomerium/pomerium/internal/log"
|
"github.com/pomerium/pomerium/internal/log"
|
||||||
"github.com/pomerium/pomerium/internal/urlutil"
|
"github.com/pomerium/pomerium/internal/sets"
|
||||||
"github.com/pomerium/pomerium/pkg/cryptutil"
|
"github.com/pomerium/pomerium/pkg/cryptutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -268,7 +266,7 @@ func (b *Builder) buildFilterChains(
|
||||||
|
|
||||||
var chains []*envoy_config_listener_v3.FilterChain
|
var chains []*envoy_config_listener_v3.FilterChain
|
||||||
for _, domain := range tlsDomains {
|
for _, domain := range tlsDomains {
|
||||||
routeableDomains, err := getRouteableDomainsForTLSDomain(options, addr, domain)
|
routeableDomains, err := getRouteableDomainsForTLSServerName(options, addr, domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -718,23 +716,30 @@ func (b *Builder) buildDownstreamValidationContext(ctx context.Context,
|
||||||
return vc
|
return vc
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRouteableDomainsForTLSDomain(options *config.Options, addr string, tlsDomain string) ([]string, error) {
|
func getRouteableDomainsForTLSServerName(options *config.Options, addr string, tlsServerName string) ([]string, error) {
|
||||||
allDomains, err := getAllRouteableDomains(options, addr)
|
allDomains := sets.NewSortedString()
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
if addr == options.Addr {
|
||||||
|
domains, err := options.GetAllRouteableHTTPDomainsForTLSServerName(tlsServerName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
allDomains.Add(domains...)
|
||||||
}
|
}
|
||||||
|
|
||||||
var filtered []string
|
if addr == options.GetGRPCAddr() {
|
||||||
for _, domain := range allDomains {
|
domains, err := options.GetAllRouteableGRPCDomainsForTLSServerName(tlsServerName)
|
||||||
if urlutil.StripPort(domain) == tlsDomain {
|
if err != nil {
|
||||||
filtered = append(filtered, domain)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
allDomains.Add(domains...)
|
||||||
}
|
}
|
||||||
return filtered, nil
|
|
||||||
|
return allDomains.ToSlice(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllRouteableDomains(options *config.Options, addr string) ([]string, error) {
|
func getAllRouteableDomains(options *config.Options, addr string) ([]string, error) {
|
||||||
allDomains := set.NewStringSet()
|
allDomains := sets.NewSortedString()
|
||||||
|
|
||||||
if addr == options.Addr {
|
if addr == options.Addr {
|
||||||
domains, err := options.GetAllRouteableHTTPDomains()
|
domains, err := options.GetAllRouteableHTTPDomains()
|
||||||
|
@ -752,10 +757,7 @@ func getAllRouteableDomains(options *config.Options, addr string) ([]string, err
|
||||||
allDomains.Add(domains...)
|
allDomains.Add(domains...)
|
||||||
}
|
}
|
||||||
|
|
||||||
domains := allDomains.List()
|
return allDomains.ToSlice(), nil
|
||||||
sort.Strings(domains)
|
|
||||||
|
|
||||||
return domains, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllTLSDomains(options *config.Options, addr string) ([]string, error) {
|
func getAllTLSDomains(options *config.Options, addr string) ([]string, error) {
|
||||||
|
@ -764,22 +766,16 @@ func getAllTLSDomains(options *config.Options, addr string) ([]string, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
lookup := map[string]struct{}{}
|
domains := sets.NewSortedString()
|
||||||
for _, hp := range allDomains {
|
for _, hp := range allDomains {
|
||||||
if d, _, err := net.SplitHostPort(hp); err == nil {
|
if d, _, err := net.SplitHostPort(hp); err == nil {
|
||||||
lookup[d] = struct{}{}
|
domains.Add(d)
|
||||||
} else {
|
} else {
|
||||||
lookup[hp] = struct{}{}
|
domains.Add(hp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
domains := make([]string, 0, len(lookup))
|
return domains.ToSlice(), nil
|
||||||
for domain := range lookup {
|
|
||||||
domains = append(domains, domain)
|
|
||||||
}
|
|
||||||
sort.Strings(domains)
|
|
||||||
|
|
||||||
return domains, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func hostsMatchDomain(urls []*url.URL, host string) bool {
|
func hostsMatchDomain(urls []*url.URL, host string) bool {
|
||||||
|
|
|
@ -117,6 +117,10 @@ func NewPolicyHTTPTransport(options *Options, policy *Policy, disableHTTP2 bool)
|
||||||
tlsClientConfig.ServerName = policy.TLSServerName
|
tlsClientConfig.ServerName = policy.TLSServerName
|
||||||
isCustomClientConfig = true
|
isCustomClientConfig = true
|
||||||
}
|
}
|
||||||
|
if policy.TLSUpstreamServerName != "" {
|
||||||
|
tlsClientConfig.ServerName = policy.TLSUpstreamServerName
|
||||||
|
isCustomClientConfig = true
|
||||||
|
}
|
||||||
|
|
||||||
// We avoid setting a custom client config unless we have to as
|
// We avoid setting a custom client config unless we have to as
|
||||||
// if TLSClientConfig is nil, the default configuration is used.
|
// if TLSClientConfig is nil, the default configuration is used.
|
||||||
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
@ -29,6 +28,7 @@ import (
|
||||||
"github.com/pomerium/pomerium/internal/hashutil"
|
"github.com/pomerium/pomerium/internal/hashutil"
|
||||||
"github.com/pomerium/pomerium/internal/identity/oauth"
|
"github.com/pomerium/pomerium/internal/identity/oauth"
|
||||||
"github.com/pomerium/pomerium/internal/log"
|
"github.com/pomerium/pomerium/internal/log"
|
||||||
|
"github.com/pomerium/pomerium/internal/sets"
|
||||||
"github.com/pomerium/pomerium/internal/telemetry"
|
"github.com/pomerium/pomerium/internal/telemetry"
|
||||||
"github.com/pomerium/pomerium/internal/telemetry/metrics"
|
"github.com/pomerium/pomerium/internal/telemetry/metrics"
|
||||||
"github.com/pomerium/pomerium/internal/urlutil"
|
"github.com/pomerium/pomerium/internal/urlutil"
|
||||||
|
@ -1041,7 +1041,13 @@ func (o *Options) GetCodecType() CodecType {
|
||||||
|
|
||||||
// GetAllRouteableGRPCDomains returns all the possible gRPC domains handled by the Pomerium options.
|
// GetAllRouteableGRPCDomains returns all the possible gRPC domains handled by the Pomerium options.
|
||||||
func (o *Options) GetAllRouteableGRPCDomains() ([]string, error) {
|
func (o *Options) GetAllRouteableGRPCDomains() ([]string, error) {
|
||||||
lookup := map[string]struct{}{}
|
return o.GetAllRouteableGRPCDomainsForTLSServerName("")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAllRouteableGRPCDomainsForTLSServerName returns all the possible gRPC domains handled by the Pomerium options
|
||||||
|
// for the given TLS server name.
|
||||||
|
func (o *Options) GetAllRouteableGRPCDomainsForTLSServerName(tlsServerName string) ([]string, error) {
|
||||||
|
domains := sets.NewSortedString()
|
||||||
|
|
||||||
// authorize urls
|
// authorize urls
|
||||||
if IsAll(o.Services) {
|
if IsAll(o.Services) {
|
||||||
|
@ -1051,7 +1057,9 @@ func (o *Options) GetAllRouteableGRPCDomains() ([]string, error) {
|
||||||
}
|
}
|
||||||
for _, u := range authorizeURLs {
|
for _, u := range authorizeURLs {
|
||||||
for _, h := range urlutil.GetDomainsForURL(*u) {
|
for _, h := range urlutil.GetDomainsForURL(*u) {
|
||||||
lookup[h] = struct{}{}
|
if tlsServerName == "" || urlutil.StripPort(h) == tlsServerName {
|
||||||
|
domains.Add(h)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if IsAuthorize(o.Services) {
|
} else if IsAuthorize(o.Services) {
|
||||||
|
@ -1061,7 +1069,9 @@ func (o *Options) GetAllRouteableGRPCDomains() ([]string, error) {
|
||||||
}
|
}
|
||||||
for _, u := range authorizeURLs {
|
for _, u := range authorizeURLs {
|
||||||
for _, h := range urlutil.GetDomainsForURL(*u) {
|
for _, h := range urlutil.GetDomainsForURL(*u) {
|
||||||
lookup[h] = struct{}{}
|
if tlsServerName == "" || urlutil.StripPort(h) == tlsServerName {
|
||||||
|
domains.Add(h)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1074,7 +1084,9 @@ func (o *Options) GetAllRouteableGRPCDomains() ([]string, error) {
|
||||||
}
|
}
|
||||||
for _, u := range dataBrokerURLs {
|
for _, u := range dataBrokerURLs {
|
||||||
for _, h := range urlutil.GetDomainsForURL(*u) {
|
for _, h := range urlutil.GetDomainsForURL(*u) {
|
||||||
lookup[h] = struct{}{}
|
if tlsServerName == "" || urlutil.StripPort(h) == tlsServerName {
|
||||||
|
domains.Add(h)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if IsDataBroker(o.Services) {
|
} else if IsDataBroker(o.Services) {
|
||||||
|
@ -1084,35 +1096,39 @@ func (o *Options) GetAllRouteableGRPCDomains() ([]string, error) {
|
||||||
}
|
}
|
||||||
for _, u := range dataBrokerURLs {
|
for _, u := range dataBrokerURLs {
|
||||||
for _, h := range urlutil.GetDomainsForURL(*u) {
|
for _, h := range urlutil.GetDomainsForURL(*u) {
|
||||||
lookup[h] = struct{}{}
|
if tlsServerName == "" || urlutil.StripPort(h) == tlsServerName {
|
||||||
|
domains.Add(h)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
domains := make([]string, 0, len(lookup))
|
return domains.ToSlice(), nil
|
||||||
for domain := range lookup {
|
|
||||||
domains = append(domains, domain)
|
|
||||||
}
|
|
||||||
sort.Strings(domains)
|
|
||||||
|
|
||||||
return domains, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllRouteableHTTPDomains returns all the possible HTTP domains handled by the Pomerium options.
|
// GetAllRouteableHTTPDomains returns all the possible HTTP domains handled by the Pomerium options.
|
||||||
func (o *Options) GetAllRouteableHTTPDomains() ([]string, error) {
|
func (o *Options) GetAllRouteableHTTPDomains() ([]string, error) {
|
||||||
|
return o.GetAllRouteableHTTPDomainsForTLSServerName("")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAllRouteableHTTPDomainsForTLSServerName returns all the possible HTTP domains handled by the Pomerium options
|
||||||
|
// for the given TLS server name.
|
||||||
|
func (o *Options) GetAllRouteableHTTPDomainsForTLSServerName(tlsServerName string) ([]string, error) {
|
||||||
forwardAuthURL, err := o.GetForwardAuthURL()
|
forwardAuthURL, err := o.GetForwardAuthURL()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
lookup := map[string]struct{}{}
|
domains := sets.NewSortedString()
|
||||||
if IsAuthenticate(o.Services) {
|
if IsAuthenticate(o.Services) {
|
||||||
authenticateURL, err := o.GetInternalAuthenticateURL()
|
authenticateURL, err := o.GetInternalAuthenticateURL()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, h := range urlutil.GetDomainsForURL(*authenticateURL) {
|
for _, h := range urlutil.GetDomainsForURL(*authenticateURL) {
|
||||||
lookup[h] = struct{}{}
|
if tlsServerName == "" || urlutil.StripPort(h) == tlsServerName {
|
||||||
|
domains.Add(h)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1120,23 +1136,32 @@ func (o *Options) GetAllRouteableHTTPDomains() ([]string, error) {
|
||||||
if IsProxy(o.Services) {
|
if IsProxy(o.Services) {
|
||||||
for _, policy := range o.GetAllPolicies() {
|
for _, policy := range o.GetAllPolicies() {
|
||||||
for _, h := range urlutil.GetDomainsForURL(*policy.Source.URL) {
|
for _, h := range urlutil.GetDomainsForURL(*policy.Source.URL) {
|
||||||
lookup[h] = struct{}{}
|
if tlsServerName == "" ||
|
||||||
|
policy.TLSDownstreamServerName == tlsServerName ||
|
||||||
|
urlutil.StripPort(h) == tlsServerName {
|
||||||
|
domains.Add(h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if policy.TLSDownstreamServerName != "" {
|
||||||
|
tlsURL := policy.Source.URL.ResolveReference(&url.URL{Host: policy.TLSDownstreamServerName})
|
||||||
|
for _, h := range urlutil.GetDomainsForURL(*tlsURL) {
|
||||||
|
if tlsServerName == "" ||
|
||||||
|
urlutil.StripPort(h) == tlsServerName {
|
||||||
|
domains.Add(h)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if forwardAuthURL != nil {
|
if forwardAuthURL != nil {
|
||||||
for _, h := range urlutil.GetDomainsForURL(*forwardAuthURL) {
|
for _, h := range urlutil.GetDomainsForURL(*forwardAuthURL) {
|
||||||
lookup[h] = struct{}{}
|
if tlsServerName == "" || urlutil.StripPort(h) == tlsServerName {
|
||||||
|
domains.Add(h)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
domains := make([]string, 0, len(lookup))
|
return domains.ToSlice(), nil
|
||||||
for domain := range lookup {
|
|
||||||
domains = append(domains, domain)
|
|
||||||
}
|
|
||||||
sort.Strings(domains)
|
|
||||||
|
|
||||||
return domains, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checksum returns the checksum of the current options struct
|
// Checksum returns the checksum of the current options struct
|
||||||
|
|
|
@ -707,12 +707,14 @@ func TestOptions_GetAllRouteableHTTPDomains(t *testing.T) {
|
||||||
p1.Validate()
|
p1.Validate()
|
||||||
p2 := Policy{From: "https://from2.example.com"}
|
p2 := Policy{From: "https://from2.example.com"}
|
||||||
p2.Validate()
|
p2.Validate()
|
||||||
|
p3 := Policy{From: "https://from3.example.com", TLSDownstreamServerName: "from.example.com"}
|
||||||
|
p3.Validate()
|
||||||
|
|
||||||
opts := &Options{
|
opts := &Options{
|
||||||
AuthenticateURLString: "https://authenticate.example.com",
|
AuthenticateURLString: "https://authenticate.example.com",
|
||||||
AuthorizeURLString: "https://authorize.example.com",
|
AuthorizeURLString: "https://authorize.example.com",
|
||||||
DataBrokerURLString: "https://databroker.example.com",
|
DataBrokerURLString: "https://databroker.example.com",
|
||||||
Policies: []Policy{p1, p2},
|
Policies: []Policy{p1, p2, p3},
|
||||||
Services: "all",
|
Services: "all",
|
||||||
}
|
}
|
||||||
domains, err := opts.GetAllRouteableHTTPDomains()
|
domains, err := opts.GetAllRouteableHTTPDomains()
|
||||||
|
@ -721,10 +723,14 @@ func TestOptions_GetAllRouteableHTTPDomains(t *testing.T) {
|
||||||
assert.Equal(t, []string{
|
assert.Equal(t, []string{
|
||||||
"authenticate.example.com",
|
"authenticate.example.com",
|
||||||
"authenticate.example.com:443",
|
"authenticate.example.com:443",
|
||||||
|
"from.example.com",
|
||||||
|
"from.example.com:443",
|
||||||
"from1.example.com",
|
"from1.example.com",
|
||||||
"from1.example.com:443",
|
"from1.example.com:443",
|
||||||
"from2.example.com",
|
"from2.example.com",
|
||||||
"from2.example.com:443",
|
"from2.example.com:443",
|
||||||
|
"from3.example.com",
|
||||||
|
"from3.example.com:443",
|
||||||
}, domains)
|
}, domains)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,9 @@ type Policy struct {
|
||||||
// if your backend is an HTTPS server with a valid certificate, but you
|
// if your backend is an HTTPS server with a valid certificate, but you
|
||||||
// want to communicate to the backend with an internal hostname (e.g.
|
// want to communicate to the backend with an internal hostname (e.g.
|
||||||
// Docker container name).
|
// Docker container name).
|
||||||
TLSServerName string `mapstructure:"tls_server_name" yaml:"tls_server_name,omitempty"`
|
TLSServerName string `mapstructure:"tls_server_name" yaml:"tls_server_name,omitempty"`
|
||||||
|
TLSDownstreamServerName string `mapstructure:"tls_downstream_server_name" yaml:"tls_downstream_server_name,omitempty"`
|
||||||
|
TLSUpstreamServerName string `mapstructure:"tls_upstream_server_name" yaml:"tls_upstream_server_name,omitempty"`
|
||||||
|
|
||||||
// TLSCustomCA defines the root certificate to use with a given
|
// TLSCustomCA defines the root certificate to use with a given
|
||||||
// route when verifying server certificates.
|
// route when verifying server certificates.
|
||||||
|
@ -239,6 +241,8 @@ func NewPolicyFromProto(pb *configpb.Route) (*Policy, error) {
|
||||||
AllowSPDY: pb.GetAllowSpdy(),
|
AllowSPDY: pb.GetAllowSpdy(),
|
||||||
TLSSkipVerify: pb.GetTlsSkipVerify(),
|
TLSSkipVerify: pb.GetTlsSkipVerify(),
|
||||||
TLSServerName: pb.GetTlsServerName(),
|
TLSServerName: pb.GetTlsServerName(),
|
||||||
|
TLSDownstreamServerName: pb.GetTlsDownstreamServerName(),
|
||||||
|
TLSUpstreamServerName: pb.GetTlsUpstreamServerName(),
|
||||||
TLSCustomCA: pb.GetTlsCustomCa(),
|
TLSCustomCA: pb.GetTlsCustomCa(),
|
||||||
TLSCustomCAFile: pb.GetTlsCustomCaFile(),
|
TLSCustomCAFile: pb.GetTlsCustomCaFile(),
|
||||||
TLSClientCert: pb.GetTlsClientCert(),
|
TLSClientCert: pb.GetTlsClientCert(),
|
||||||
|
@ -360,6 +364,8 @@ func (p *Policy) ToProto() (*configpb.Route, error) {
|
||||||
AllowSpdy: p.AllowSPDY,
|
AllowSpdy: p.AllowSPDY,
|
||||||
TlsSkipVerify: p.TLSSkipVerify,
|
TlsSkipVerify: p.TLSSkipVerify,
|
||||||
TlsServerName: p.TLSServerName,
|
TlsServerName: p.TLSServerName,
|
||||||
|
TlsUpstreamServerName: p.TLSUpstreamServerName,
|
||||||
|
TlsDownstreamServerName: p.TLSDownstreamServerName,
|
||||||
TlsCustomCa: p.TLSCustomCA,
|
TlsCustomCa: p.TLSCustomCA,
|
||||||
TlsCustomCaFile: p.TLSCustomCAFile,
|
TlsCustomCaFile: p.TLSCustomCAFile,
|
||||||
TlsClientCert: p.TLSClientCert,
|
TlsClientCert: p.TLSClientCert,
|
||||||
|
|
|
@ -1725,7 +1725,23 @@ TLS Skip Verification controls whether the Pomerium Proxy Service verifies the u
|
||||||
- Type: `string`
|
- Type: `string`
|
||||||
- Optional
|
- Optional
|
||||||
|
|
||||||
TLS Server Name overrides the hostname specified in the `to` field. If set, this server name will be used to verify the certificate name. This is useful when the backend of your service is an TLS server with a valid certificate, but mismatched name.
|
**Deprecated**: this key has been replaced with `tls_upstream_server_name`.
|
||||||
|
|
||||||
|
|
||||||
|
### TLS Upstream Server Name
|
||||||
|
- Config File Key: `tls_upstream_server_name`
|
||||||
|
- Type: `string`
|
||||||
|
- Optional
|
||||||
|
|
||||||
|
TLS Upstream Server Name overrides the hostname specified in the `to` field. If set, this server name will be used to verify the certificate name. This is useful when the backend of your service is a TLS server with a valid certificate, but mismatched name.
|
||||||
|
|
||||||
|
|
||||||
|
### TLS Downstream Server Name
|
||||||
|
- Config File Key: `tls_downstream_server_name`
|
||||||
|
- Type: `string`
|
||||||
|
- Optional
|
||||||
|
|
||||||
|
TLS Downstream Server Name overrides the hostname specified in the `from` field. When a connection to Pomerium is made via TLS the `tls_downstream_server_name` will be used as the expected Server Name Indication, whereas the host part of the `from` field, will be expected to match the `Host` or `:authority` headers of the HTTP request.
|
||||||
|
|
||||||
|
|
||||||
### To
|
### To
|
||||||
|
|
|
@ -1882,7 +1882,23 @@ settings:
|
||||||
- Type: `string`
|
- Type: `string`
|
||||||
- Optional
|
- Optional
|
||||||
doc: |
|
doc: |
|
||||||
TLS Server Name overrides the hostname specified in the `to` field. If set, this server name will be used to verify the certificate name. This is useful when the backend of your service is an TLS server with a valid certificate, but mismatched name.
|
**Deprecated**: this key has been replaced with `tls_upstream_server_name`.
|
||||||
|
- name: "TLS Upstream Server Name"
|
||||||
|
keys: ["tls_upstream_server_name"]
|
||||||
|
attributes: |
|
||||||
|
- Config File Key: `tls_upstream_server_name`
|
||||||
|
- Type: `string`
|
||||||
|
- Optional
|
||||||
|
doc: |
|
||||||
|
TLS Upstream Server Name overrides the hostname specified in the `to` field. If set, this server name will be used to verify the certificate name. This is useful when the backend of your service is a TLS server with a valid certificate, but mismatched name.
|
||||||
|
- name: "TLS Downstream Server Name"
|
||||||
|
keys: ["tls_downstream_server_name"]
|
||||||
|
attributes: |
|
||||||
|
- Config File Key: `tls_downstream_server_name`
|
||||||
|
- Type: `string`
|
||||||
|
- Optional
|
||||||
|
doc: |
|
||||||
|
TLS Downstream Server Name overrides the hostname specified in the `from` field. When a connection to Pomerium is made via TLS the `tls_downstream_server_name` will be used as the expected Server Name Indication, whereas the host part of the `from` field, will be expected to match the `Host` or `:authority` headers of the HTTP request.
|
||||||
- name: "To"
|
- name: "To"
|
||||||
keys: ["to"]
|
keys: ["to"]
|
||||||
attributes: |
|
attributes: |
|
||||||
|
|
65
internal/sets/sorted.go
Normal file
65
internal/sets/sorted.go
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
package sets
|
||||||
|
|
||||||
|
import "github.com/google/btree"
|
||||||
|
|
||||||
|
type stringItem string
|
||||||
|
|
||||||
|
func (item stringItem) Less(than btree.Item) bool {
|
||||||
|
return item < than.(stringItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A SortedString is a set of strings with sorted iteration.
|
||||||
|
type SortedString struct {
|
||||||
|
b *btree.BTree
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSortedString creates a new sorted string set.
|
||||||
|
func NewSortedString() *SortedString {
|
||||||
|
return &SortedString{
|
||||||
|
b: btree.New(8),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds a string to the set.
|
||||||
|
func (s *SortedString) Add(elements ...string) {
|
||||||
|
for _, element := range elements {
|
||||||
|
s.b.ReplaceOrInsert(stringItem(element))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear clears the set.
|
||||||
|
func (s *SortedString) Clear() {
|
||||||
|
s.b = btree.New(8)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete deletes an element from the set.
|
||||||
|
func (s *SortedString) Delete(element string) {
|
||||||
|
s.b.Delete(stringItem(element))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ForEach iterates over the set in ascending order.
|
||||||
|
func (s *SortedString) ForEach(callback func(element string) bool) {
|
||||||
|
s.b.Ascend(func(i btree.Item) bool {
|
||||||
|
return callback(string(i.(stringItem)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Has returns true if the elment is in the set.
|
||||||
|
func (s *SortedString) Has(element string) bool {
|
||||||
|
return s.b.Has(stringItem(element))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns the size of the set.
|
||||||
|
func (s *SortedString) Size() int {
|
||||||
|
return s.b.Len()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToSlice returns a slice of all the elements in the set.
|
||||||
|
func (s *SortedString) ToSlice() []string {
|
||||||
|
arr := make([]string, 0, s.Size())
|
||||||
|
s.b.Ascend(func(i btree.Item) bool {
|
||||||
|
arr = append(arr, string(i.(stringItem)))
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return arr
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -78,6 +78,8 @@ message Route {
|
||||||
|
|
||||||
bool tls_skip_verify = 14;
|
bool tls_skip_verify = 14;
|
||||||
string tls_server_name = 15;
|
string tls_server_name = 15;
|
||||||
|
string tls_upstream_server_name = 57;
|
||||||
|
string tls_downstream_server_name = 58;
|
||||||
string tls_custom_ca = 16;
|
string tls_custom_ca = 16;
|
||||||
string tls_custom_ca_file = 17;
|
string tls_custom_ca_file = 17;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue