Merge branch 'main' into dependabot/go_modules/golang.org/x/crypto-0.9.0

This commit is contained in:
Denis Mishin 2023-05-23 11:52:17 -04:00 committed by GitHub
commit 3830b2c67b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 42 additions and 139 deletions

View file

@ -12,7 +12,6 @@ import (
"github.com/pomerium/pomerium/internal/fileutil" "github.com/pomerium/pomerium/internal/fileutil"
"github.com/pomerium/pomerium/internal/hashutil" "github.com/pomerium/pomerium/internal/hashutil"
"github.com/pomerium/pomerium/internal/httputil" "github.com/pomerium/pomerium/internal/httputil"
"github.com/pomerium/pomerium/internal/log"
"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"
"github.com/pomerium/pomerium/pkg/cryptutil" "github.com/pomerium/pomerium/pkg/cryptutil"
@ -149,24 +148,9 @@ func (cfg *Config) GetTLSClientConfig() (*tls.Config, error) {
}, nil }, nil
} }
// GetCertificateForServerName gets the certificate for the server name. If no certificate is found and there // GenerateCatchAllCertificate generates a catch-all certificate. If no derived CA is defined a
// is a derived CA one will be generated using that CA. If no derived CA is defined a self-signed certificate // self-signed certificate will be generated.
// will be generated. func (cfg *Config) GenerateCatchAllCertificate() (*tls.Certificate, error) {
func (cfg *Config) GetCertificateForServerName(serverName string) (*tls.Certificate, error) {
certificates, err := cfg.AllCertificates()
if err != nil {
return nil, err
}
// first try a direct name match
for i := range certificates {
if cryptutil.MatchesServerName(&certificates[i], serverName) {
return &certificates[i], nil
}
}
log.WarnNoTLSCertificate(serverName)
if cfg.Options.DeriveInternalDomainCert != nil { if cfg.Options.DeriveInternalDomainCert != nil {
sharedKey, err := cfg.Options.GetSharedKey() sharedKey, err := cfg.Options.GetSharedKey()
if err != nil { if err != nil {
@ -178,7 +162,7 @@ func (cfg *Config) GetCertificateForServerName(serverName string) (*tls.Certific
return nil, fmt.Errorf("failed to generate cert, invalid derived CA: %w", err) return nil, fmt.Errorf("failed to generate cert, invalid derived CA: %w", err)
} }
pem, err := ca.NewServerCert([]string{serverName}) pem, err := ca.NewServerCert([]string{"*"})
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to generate cert, error creating server certificate: %w", err) return nil, fmt.Errorf("failed to generate cert, error creating server certificate: %w", err)
} }
@ -196,7 +180,7 @@ func (cfg *Config) GetCertificateForServerName(serverName string) (*tls.Certific
} }
// finally fall back to a generated, self-signed certificate // finally fall back to a generated, self-signed certificate
return cryptutil.GenerateCertificate(sharedKey, serverName) return cryptutil.GenerateCertificate(sharedKey, "*")
} }
// WillHaveCertificateForServerName returns true if there will be a certificate for the given server name. // WillHaveCertificateForServerName returns true if there will be a certificate for the given server name.

View file

@ -1,94 +0,0 @@
package config
import (
"crypto/tls"
"crypto/x509"
"testing"
"github.com/golang/protobuf/proto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/pomerium/pomerium/pkg/cryptutil"
)
func TestConfig_GetCertificateForServerName(t *testing.T) {
gen := func(t *testing.T, serverName string) *tls.Certificate {
cert, err := cryptutil.GenerateCertificate(nil, serverName)
if !assert.NoError(t, err, "error generating certificate for: %s", serverName) {
t.FailNow()
}
return cert
}
t.Run("exact match", func(t *testing.T) {
cfg := &Config{Options: NewDefaultOptions(), AutoCertificates: []tls.Certificate{
*gen(t, "a.example.com"),
*gen(t, "b.example.com"),
}}
found, err := cfg.GetCertificateForServerName("b.example.com")
if !assert.NoError(t, err) {
return
}
assert.Equal(t, &cfg.AutoCertificates[1], found)
})
t.Run("wildcard match", func(t *testing.T) {
cfg := &Config{Options: NewDefaultOptions(), AutoCertificates: []tls.Certificate{
*gen(t, "a.example.com"),
*gen(t, "*.example.com"),
}}
found, err := cfg.GetCertificateForServerName("b.example.com")
if !assert.NoError(t, err) {
return
}
assert.Equal(t, &cfg.AutoCertificates[1], found)
})
t.Run("no name match", func(t *testing.T) {
cfg := &Config{Options: NewDefaultOptions(), AutoCertificates: []tls.Certificate{
*gen(t, "a.example.com"),
}}
found, err := cfg.GetCertificateForServerName("b.example.com")
if !assert.NoError(t, err) {
return
}
assert.NotNil(t, found)
assert.NotEqual(t, &cfg.AutoCertificates[0], found)
})
t.Run("generate", func(t *testing.T) {
cfg := &Config{Options: NewDefaultOptions()}
found, err := cfg.GetCertificateForServerName("b.example.com")
if !assert.NoError(t, err) {
return
}
assert.NotNil(t, found)
})
t.Run("generate for specific name", func(t *testing.T) {
cfg := &Config{Options: NewDefaultOptions()}
cfg.Options.DeriveInternalDomainCert = proto.String("databroker.int.example.com")
ok, err := cfg.WillHaveCertificateForServerName("databroker.int.example.com")
require.NoError(t, err)
assert.True(t, ok)
found, err := cfg.GetCertificateForServerName("databroker.int.example.com")
require.NoError(t, err)
assert.True(t, cryptutil.MatchesServerName(found, "databroker.int.example.com"))
certPool, err := cfg.GetCertificatePool()
require.NoError(t, err)
xc, err := x509.ParseCertificate(found.Certificate[0])
require.NoError(t, err)
_, err = xc.Verify(x509.VerifyOptions{
DNSName: "databroker.int.example.com",
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
Roots: certPool,
})
require.NoError(t, err)
})
}

View file

@ -134,6 +134,12 @@ func (b *Builder) BuildBootstrapLayeredRuntime() (*envoy_config_bootstrap_v3.Lay
"overload": map[string]interface{}{ "overload": map[string]interface{}{
"global_downstream_max_connections": 50000, "global_downstream_max_connections": 50000,
}, },
"re2": map[string]any{
"max_program_size": map[string]any{
"error_level": 1024 * 1024,
"warn_level": 1024,
},
},
}) })
if err != nil { if err != nil {
return nil, fmt.Errorf("envoyconfig: failed to create layered runtime layer: %w", err) return nil, fmt.Errorf("envoyconfig: failed to create layered runtime layer: %w", err)

View file

@ -43,6 +43,12 @@ func TestBuilder_BuildBootstrapLayeredRuntime(t *testing.T) {
"staticLayer": { "staticLayer": {
"overload": { "overload": {
"global_downstream_max_connections": 50000 "global_downstream_max_connections": 50000
},
"re2": {
"max_program_size": {
"error_level": 1048576,
"warn_level": 1024
}
} }
} }
}] } }] }

View file

@ -109,7 +109,8 @@ func getAllCertificates(cfg *config.Config) ([]tls.Certificate, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("error collecting all certificates: %w", err) return nil, fmt.Errorf("error collecting all certificates: %w", err)
} }
wc, err := cfg.GetCertificateForServerName("*")
wc, err := cfg.GenerateCatchAllCertificate()
if err != nil { if err != nil {
return nil, fmt.Errorf("error getting wildcard certificate: %w", err) return nil, fmt.Errorf("error getting wildcard certificate: %w", err)
} }

View file

@ -78,7 +78,7 @@ func (b *Builder) buildMainRouteConfiguration(
// if we're the proxy, add all the policy routes // if we're the proxy, add all the policy routes
if config.IsProxy(cfg.Options.Services) { if config.IsProxy(cfg.Options.Services) {
rs, err := b.buildRoutesForPoliciesWithHost(cfg, host) rs, err := b.buildRoutesForPoliciesWithHost(cfg, certs, host)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -95,7 +95,7 @@ func (b *Builder) buildMainRouteConfiguration(
return nil, err return nil, err
} }
if config.IsProxy(cfg.Options.Services) { if config.IsProxy(cfg.Options.Services) {
rs, err := b.buildRoutesForPoliciesWithCatchAll(cfg) rs, err := b.buildRoutesForPoliciesWithCatchAll(cfg, certs)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -1,6 +1,7 @@
package envoyconfig package envoyconfig
import ( import (
"crypto/tls"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/url" "net/url"
@ -193,6 +194,7 @@ func getClusterStatsName(policy *config.Policy) string {
func (b *Builder) buildRoutesForPoliciesWithHost( func (b *Builder) buildRoutesForPoliciesWithHost(
cfg *config.Config, cfg *config.Config,
certs []tls.Certificate,
host string, host string,
) ([]*envoy_config_route_v3.Route, error) { ) ([]*envoy_config_route_v3.Route, error) {
var routes []*envoy_config_route_v3.Route var routes []*envoy_config_route_v3.Route
@ -207,7 +209,7 @@ func (b *Builder) buildRoutesForPoliciesWithHost(
continue continue
} }
policyRoutes, err := b.buildRoutesForPolicy(cfg, &policy, fmt.Sprintf("policy-%d", i)) policyRoutes, err := b.buildRoutesForPolicy(cfg, certs, &policy, fmt.Sprintf("policy-%d", i))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -219,6 +221,7 @@ func (b *Builder) buildRoutesForPoliciesWithHost(
func (b *Builder) buildRoutesForPoliciesWithCatchAll( func (b *Builder) buildRoutesForPoliciesWithCatchAll(
cfg *config.Config, cfg *config.Config,
certs []tls.Certificate,
) ([]*envoy_config_route_v3.Route, error) { ) ([]*envoy_config_route_v3.Route, error) {
var routes []*envoy_config_route_v3.Route var routes []*envoy_config_route_v3.Route
for i, p := range cfg.Options.GetAllPolicies() { for i, p := range cfg.Options.GetAllPolicies() {
@ -232,7 +235,7 @@ func (b *Builder) buildRoutesForPoliciesWithCatchAll(
continue continue
} }
policyRoutes, err := b.buildRoutesForPolicy(cfg, &policy, fmt.Sprintf("policy-%d", i)) policyRoutes, err := b.buildRoutesForPolicy(cfg, certs, &policy, fmt.Sprintf("policy-%d", i))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -244,6 +247,7 @@ func (b *Builder) buildRoutesForPoliciesWithCatchAll(
func (b *Builder) buildRoutesForPolicy( func (b *Builder) buildRoutesForPolicy(
cfg *config.Config, cfg *config.Config,
certs []tls.Certificate,
policy *config.Policy, policy *config.Policy,
name string, name string,
) ([]*envoy_config_route_v3.Route, error) { ) ([]*envoy_config_route_v3.Route, error) {
@ -256,14 +260,14 @@ func (b *Builder) buildRoutesForPolicy(
if strings.Contains(fromURL.Host, "*") { if strings.Contains(fromURL.Host, "*") {
// we have to match '*.example.com' and '*.example.com:443', so there are two routes // we have to match '*.example.com' and '*.example.com:443', so there are two routes
for _, host := range urlutil.GetDomainsForURL(fromURL) { for _, host := range urlutil.GetDomainsForURL(fromURL) {
route, err := b.buildRouteForPolicyAndMatch(cfg, policy, name, mkRouteMatchForHost(policy, host)) route, err := b.buildRouteForPolicyAndMatch(cfg, certs, policy, name, mkRouteMatchForHost(policy, host))
if err != nil { if err != nil {
return nil, err return nil, err
} }
routes = append(routes, route) routes = append(routes, route)
} }
} else { } else {
route, err := b.buildRouteForPolicyAndMatch(cfg, policy, name, mkRouteMatch(policy)) route, err := b.buildRouteForPolicyAndMatch(cfg, certs, policy, name, mkRouteMatch(policy))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -274,6 +278,7 @@ func (b *Builder) buildRoutesForPolicy(
func (b *Builder) buildRouteForPolicyAndMatch( func (b *Builder) buildRouteForPolicyAndMatch(
cfg *config.Config, cfg *config.Config,
certs []tls.Certificate,
policy *config.Policy, policy *config.Policy,
name string, name string,
match *envoy_config_route_v3.RouteMatch, match *envoy_config_route_v3.RouteMatch,
@ -283,11 +288,6 @@ func (b *Builder) buildRouteForPolicyAndMatch(
return nil, err return nil, err
} }
certs, err := getAllCertificates(cfg)
if err != nil {
return nil, err
}
requireStrictTransportSecurity := cryptutil.HasCertificateForServerName(certs, fromURL.Hostname()) requireStrictTransportSecurity := cryptutil.HasCertificateForServerName(certs, fromURL.Hostname())
route := &envoy_config_route_v3.Route{ route := &envoy_config_route_v3.Route{

View file

@ -307,7 +307,7 @@ func TestTimeouts(t *testing.T) {
AllowWebsockets: tc.allowWebsockets, AllowWebsockets: tc.allowWebsockets,
}, },
}, },
}}, "example.com") }}, nil, "example.com")
if !assert.NoError(t, err, "%v", tc) || !assert.Len(t, routes, 1, tc) || !assert.NotNil(t, routes[0].GetRoute(), "%v", tc) { if !assert.NoError(t, err, "%v", tc) || !assert.Len(t, routes, 1, tc) || !assert.NotNil(t, routes[0].GetRoute(), "%v", tc) {
continue continue
} }
@ -412,7 +412,7 @@ func Test_buildPolicyRoutes(t *testing.T) {
UpstreamTimeout: &ten, UpstreamTimeout: &ten,
}, },
}, },
}}, "example.com") }}, nil, "example.com")
require.NoError(t, err) require.NoError(t, err)
testutil.AssertProtoJSONEqual(t, ` testutil.AssertProtoJSONEqual(t, `
@ -918,7 +918,7 @@ func Test_buildPolicyRoutes(t *testing.T) {
PassIdentityHeaders: true, PassIdentityHeaders: true,
}, },
}, },
}}, "authenticate.example.com") }}, nil, "authenticate.example.com")
require.NoError(t, err) require.NoError(t, err)
testutil.AssertProtoJSONEqual(t, ` testutil.AssertProtoJSONEqual(t, `
@ -1005,7 +1005,7 @@ func Test_buildPolicyRoutes(t *testing.T) {
UpstreamTimeout: &ten, UpstreamTimeout: &ten,
}, },
}, },
}}, "example.com:22") }}, nil, "example.com:22")
require.NoError(t, err) require.NoError(t, err)
testutil.AssertProtoJSONEqual(t, ` testutil.AssertProtoJSONEqual(t, `
@ -1151,7 +1151,7 @@ func Test_buildPolicyRoutes(t *testing.T) {
From: "https://from.example.com", From: "https://from.example.com",
}, },
}, },
}}, "from.example.com") }}, nil, "from.example.com")
require.NoError(t, err) require.NoError(t, err)
testutil.AssertProtoJSONEqual(t, ` testutil.AssertProtoJSONEqual(t, `
@ -1272,7 +1272,7 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) {
HostPathRegexRewriteSubstitution: "\\1", HostPathRegexRewriteSubstitution: "\\1",
}, },
}, },
}}, "example.com") }}, nil, "example.com")
require.NoError(t, err) require.NoError(t, err)
testutil.AssertProtoJSONEqual(t, ` testutil.AssertProtoJSONEqual(t, `

4
go.mod
View file

@ -16,9 +16,9 @@ require (
github.com/cespare/xxhash/v2 v2.2.0 github.com/cespare/xxhash/v2 v2.2.0
github.com/client9/misspell v0.3.4 github.com/client9/misspell v0.3.4
github.com/coreos/go-oidc/v3 v3.5.0 github.com/coreos/go-oidc/v3 v3.5.0
github.com/docker/docker v23.0.6+incompatible github.com/docker/docker v24.0.1+incompatible
github.com/envoyproxy/go-control-plane v0.11.0 github.com/envoyproxy/go-control-plane v0.11.0
github.com/envoyproxy/protoc-gen-validate v1.0.0 github.com/envoyproxy/protoc-gen-validate v1.0.1
github.com/fsnotify/fsnotify v1.6.0 github.com/fsnotify/fsnotify v1.6.0
github.com/go-chi/chi/v5 v5.0.8 github.com/go-chi/chi/v5 v5.0.8
github.com/go-jose/go-jose/v3 v3.0.0 github.com/go-jose/go-jose/v3 v3.0.0

8
go.sum
View file

@ -201,8 +201,8 @@ github.com/docker/cli v20.10.21+incompatible h1:qVkgyYUnOLQ98LtXBrwd/duVqPT2X4SH
github.com/docker/cli v20.10.21+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v20.10.21+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v23.0.6+incompatible h1:aBD4np894vatVX99UTx/GyOUOK4uEcROwA3+bQhEcoU= github.com/docker/docker v24.0.1+incompatible h1:NxN81beIxDlUaVt46iUQrYHD9/W3u9EGl52r86O/IGw=
github.com/docker/docker v23.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v24.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
@ -222,8 +222,8 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.
github.com/envoyproxy/go-control-plane v0.11.0 h1:jtLewhRR2vMRNnq2ZZUoCjUlgut+Y0+sDDWPOfwOi1o= github.com/envoyproxy/go-control-plane v0.11.0 h1:jtLewhRR2vMRNnq2ZZUoCjUlgut+Y0+sDDWPOfwOi1o=
github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v1.0.0 h1:FPFO7LWZ2pfphahSUMX8L5p/6FqSzRYRxq6V74eG8ZI= github.com/envoyproxy/protoc-gen-validate v1.0.1 h1:kt9FtLiooDc0vbwTLhdg3dyNX1K9Qwa1EK9LcD4jVUQ=
github.com/envoyproxy/protoc-gen-validate v1.0.0/go.mod h1:0vj8bNkYbSTNS2PIyH87KZaeN4x9zpL9Qt8fQC7d+vs= github.com/envoyproxy/protoc-gen-validate v1.0.1/go.mod h1:0vj8bNkYbSTNS2PIyH87KZaeN4x9zpL9Qt8fQC7d+vs=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/foxcpp/go-mockdns v1.0.0 h1:7jBqxd3WDWwi/6WhDvacvH1XsN3rOLXyHM1uhvIx6FI= github.com/foxcpp/go-mockdns v1.0.0 h1:7jBqxd3WDWwi/6WhDvacvH1XsN3rOLXyHM1uhvIx6FI=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=