Skip to content

Commit

Permalink
internal/envoy: switch to FilterChain.TransportSocket for upstream TLS
Browse files Browse the repository at this point in the history
Updates projectcontour#1351

Envoy 1.12 has deprecated the FilterChain.TLSContext field, instead the
DownstreamTLSContext must be provided via a typed config attached to a
TransportSocket.

ref: https://www.envoyproxy.io/docs/envoy/v1.12.0/api-v2/api/v2/listener/listener.proto#envoy-api-field-listener-filterchain-tls-context

Signed-off-by: Dave Cheney <dave@cheney.net>
  • Loading branch information
davecheney committed Nov 26, 2019
1 parent 147edfa commit 7d8c73b
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 41 deletions.
55 changes: 29 additions & 26 deletions internal/contour/listener_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (

v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2"
envoy_api_v2_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth"
envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core"
envoy_api_v2_listener "github.com/envoyproxy/go-control-plane/envoy/api/v2/listener"
"github.com/golang/protobuf/proto"
ingressroutev1 "github.com/projectcontour/contour/apis/contour/v1beta1"
Expand Down Expand Up @@ -263,8 +264,8 @@ func TestListenerVisit(t *testing.T) {
FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{
ServerNames: []string{"whatever.example.com"},
},
TlsContext: tlscontext(envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"),
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)),
TransportSocket: transportSocket(envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"),
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)),
}},
}),
},
Expand Down Expand Up @@ -350,14 +351,14 @@ func TestListenerVisit(t *testing.T) {
FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{
ServerNames: []string{"sortedfirst.example.com"},
},
TlsContext: tlscontext(envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"),
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)),
TransportSocket: transportSocket(envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"),
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)),
}, {
FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{
ServerNames: []string{"sortedsecond.example.com"},
},
TlsContext: tlscontext(envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"),
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)),
TransportSocket: transportSocket(envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"),
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)),
}},
}),
},
Expand Down Expand Up @@ -472,8 +473,8 @@ func TestListenerVisit(t *testing.T) {
FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{
ServerNames: []string{"www.example.com"},
},
TlsContext: tlscontext(envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"),
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)),
TransportSocket: transportSocket(envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"),
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)),
}},
ListenerFilters: envoy.ListenerFilters(
envoy.TLSInspector(),
Expand Down Expand Up @@ -553,8 +554,8 @@ func TestListenerVisit(t *testing.T) {
FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{
ServerNames: []string{"www.example.com"},
},
TlsContext: tlscontext(envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"),
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)),
TransportSocket: transportSocket(envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"),
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)),
}},
ListenerFilters: envoy.ListenerFilters(
envoy.TLSInspector(),
Expand Down Expand Up @@ -627,8 +628,8 @@ func TestListenerVisit(t *testing.T) {
FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{
ServerNames: []string{"whatever.example.com"},
},
TlsContext: tlscontext(envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"),
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)),
TransportSocket: transportSocket(envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"),
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)),
}},
}),
},
Expand Down Expand Up @@ -699,8 +700,8 @@ func TestListenerVisit(t *testing.T) {
FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{
ServerNames: []string{"whatever.example.com"},
},
TlsContext: tlscontext(envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"),
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)),
TransportSocket: transportSocket(envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"),
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)),
}},
}),
},
Expand Down Expand Up @@ -768,8 +769,8 @@ func TestListenerVisit(t *testing.T) {
FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{
ServerNames: []string{"whatever.example.com"},
},
TlsContext: tlscontext(envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"),
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy("/tmp/https_access.log"), 0)),
TransportSocket: transportSocket(envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"),
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy("/tmp/https_access.log"), 0)),
}},
}),
},
Expand Down Expand Up @@ -833,8 +834,8 @@ func TestListenerVisit(t *testing.T) {
FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{
ServerNames: []string{"whatever.example.com"},
},
TlsContext: tlscontext(envoy_api_v2_auth.TlsParameters_TLSv1_3, "h2", "http/1.1"),
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)),
TransportSocket: transportSocket(envoy_api_v2_auth.TlsParameters_TLSv1_3, "h2", "http/1.1"),
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)),
}},
ListenerFilters: envoy.ListenerFilters(
envoy.TLSInspector(),
Expand Down Expand Up @@ -904,8 +905,8 @@ func TestListenerVisit(t *testing.T) {
FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{
ServerNames: []string{"whatever.example.com"},
},
TlsContext: tlscontext(envoy_api_v2_auth.TlsParameters_TLSv1_3, "h2", "http/1.1"), // note, cannot downgrade from the configured version
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)),
TransportSocket: transportSocket(envoy_api_v2_auth.TlsParameters_TLSv1_3, "h2", "http/1.1"), // note, cannot downgrade from the configured version
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)),
}},
ListenerFilters: envoy.ListenerFilters(
envoy.TLSInspector(),
Expand Down Expand Up @@ -975,8 +976,8 @@ func TestListenerVisit(t *testing.T) {
FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{
ServerNames: []string{"whatever.example.com"},
},
TlsContext: tlscontext(envoy_api_v2_auth.TlsParameters_TLSv1_3, "h2", "http/1.1"), // note, cannot downgrade from the configured version
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)),
TransportSocket: transportSocket(envoy_api_v2_auth.TlsParameters_TLSv1_3, "h2", "http/1.1"), // note, cannot downgrade from the configured version
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)),
}},
ListenerFilters: envoy.ListenerFilters(
envoy.TLSInspector(),
Expand Down Expand Up @@ -1046,8 +1047,8 @@ func TestListenerVisit(t *testing.T) {
FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{
ServerNames: []string{"www.example.com"},
},
TlsContext: tlscontext(envoy_api_v2_auth.TlsParameters_TLSv1_3, "h2", "http/1.1"), // note, cannot downgrade from the configured version
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)),
TransportSocket: transportSocket(envoy_api_v2_auth.TlsParameters_TLSv1_3, "h2", "http/1.1"), // note, cannot downgrade from the configured version
Filters: envoy.Filters(envoy.HTTPConnectionManager(ENVOY_HTTPS_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)),
}},
ListenerFilters: envoy.ListenerFilters(
envoy.TLSInspector(),
Expand All @@ -1065,8 +1066,10 @@ func TestListenerVisit(t *testing.T) {
}
}

func tlscontext(tlsMinProtoVersion envoy_api_v2_auth.TlsParameters_TlsProtocol, alpnprotos ...string) *envoy_api_v2_auth.DownstreamTlsContext {
return envoy.DownstreamTLSContext("default/secret/28337303ac", tlsMinProtoVersion, alpnprotos...)
func transportSocket(tlsMinProtoVersion envoy_api_v2_auth.TlsParameters_TlsProtocol, alpnprotos ...string) *envoy_api_v2_core.TransportSocket {
return envoy.DownstreamTLSTransportSocket(
envoy.DownstreamTLSContext("default/secret/28337303ac", tlsMinProtoVersion, alpnprotos...),
)
}

func listenermap(listeners ...*v2.Listener) map[string]*v2.Listener {
Expand Down
4 changes: 2 additions & 2 deletions internal/contour/visitor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ func TestVisitListeners(t *testing.T) {
FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{
ServerNames: []string{"tcpproxy.example.com"},
},
TlsContext: tlscontext(envoy_api_v2_auth.TlsParameters_TLSv1_1),
Filters: envoy.Filters(envoy.TCPProxy(ENVOY_HTTPS_LISTENER, p1, envoy.FileAccessLogEnvoy(DEFAULT_HTTPS_ACCESS_LOG))),
TransportSocket: transportSocket(envoy_api_v2_auth.TlsParameters_TLSv1_1),
Filters: envoy.Filters(envoy.TCPProxy(ENVOY_HTTPS_LISTENER, p1, envoy.FileAccessLogEnvoy(DEFAULT_HTTPS_ACCESS_LOG))),
}},
ListenerFilters: envoy.ListenerFilters(
envoy.TLSInspector(),
Expand Down
42 changes: 33 additions & 9 deletions internal/e2e/lds_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,6 @@ func TestIngressRouteTLSListener(t *testing.T) {
FilterChains: filterchaintls("kuard.example.com", secret1, envoy.HTTPConnectionManager("ingress_https", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), "h2", "http/1.1"),
}

l1.FilterChains[0].TlsContext.CommonTlsContext.TlsParams.TlsMinimumProtocolVersion = envoy_api_v2_auth.TlsParameters_TLSv1_1

// add service
rh.OnAdd(svc1)

Expand Down Expand Up @@ -438,11 +436,19 @@ func TestIngressRouteTLSListener(t *testing.T) {
ListenerFilters: envoy.ListenerFilters(
envoy.TLSInspector(),
),
FilterChains: filterchaintls("kuard.example.com", secret1, envoy.HTTPConnectionManager("ingress_https", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), "h2", "http/1.1"),
FilterChains: []*envoy_api_v2_listener.FilterChain{
envoy.FilterChainTLS(
"kuard.example.com",
&dag.Secret{Object: secret1},
[]*envoy_api_v2_listener.Filter{
envoy.HTTPConnectionManager("ingress_https", envoy.FileAccessLogEnvoy("/dev/stdout"), 0),
},
envoy_api_v2_auth.TlsParameters_TLSv1_3,
"h2", "http/1.1",
),
},
}

l2.FilterChains[0].TlsContext.CommonTlsContext.TlsParams.TlsMinimumProtocolVersion = envoy_api_v2_auth.TlsParameters_TLSv1_3

// add ingress and assert the existence of ingress_http and ingres_https
rh.OnAdd(i2)
assert.Equal(t, &v2.DiscoveryResponse{
Expand Down Expand Up @@ -1211,9 +1217,18 @@ func TestIngressRouteMinimumTLSVersion(t *testing.T) {
ListenerFilters: envoy.ListenerFilters(
envoy.TLSInspector(),
),
FilterChains: filterchaintls("kuard.example.com", secret1, envoy.HTTPConnectionManager("ingress_https", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), "h2", "http/1.1"),
FilterChains: []*envoy_api_v2_listener.FilterChain{
envoy.FilterChainTLS(
"kuard.example.com",
&dag.Secret{Object: secret1},
[]*envoy_api_v2_listener.Filter{
envoy.HTTPConnectionManager("ingress_https", envoy.FileAccessLogEnvoy("/dev/stdout"), 0),
},
envoy_api_v2_auth.TlsParameters_TLSv1_2,
"h2", "http/1.1",
),
},
}
l1.FilterChains[0].TlsContext.CommonTlsContext.TlsParams.TlsMinimumProtocolVersion = envoy_api_v2_auth.TlsParameters_TLSv1_2

// verify that i1's TLS 1.1 minimum has been upgraded to 1.2
assert.Equal(t, &v2.DiscoveryResponse{
Expand Down Expand Up @@ -1264,9 +1279,18 @@ func TestIngressRouteMinimumTLSVersion(t *testing.T) {
ListenerFilters: envoy.ListenerFilters(
envoy.TLSInspector(),
),
FilterChains: filterchaintls("kuard.example.com", secret1, envoy.HTTPConnectionManager("ingress_https", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), "h2", "http/1.1"),
FilterChains: []*envoy_api_v2_listener.FilterChain{
envoy.FilterChainTLS(
"kuard.example.com",
&dag.Secret{Object: secret1},
[]*envoy_api_v2_listener.Filter{
envoy.HTTPConnectionManager("ingress_https", envoy.FileAccessLogEnvoy("/dev/stdout"), 0),
},
envoy_api_v2_auth.TlsParameters_TLSv1_3,
"h2", "http/1.1",
),
},
}
l2.FilterChains[0].TlsContext.CommonTlsContext.TlsParams.TlsMinimumProtocolVersion = envoy_api_v2_auth.TlsParameters_TLSv1_3

// verify that i2's TLS 1.3 minimum has NOT been downgraded to 1.2
assert.Equal(t, &v2.DiscoveryResponse{
Expand Down
4 changes: 3 additions & 1 deletion internal/envoy/listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,9 @@ func FilterChainTLS(domain string, secret *dag.Secret, filters []*envoy_api_v2_l
}
// attach certificate data to this listener if provided.
if secret != nil {
fc.TlsContext = DownstreamTLSContext(Secretname(secret), tlsMinProtoVersion, alpnProtos...)
fc.TransportSocket = DownstreamTLSTransportSocket(
DownstreamTLSContext(Secretname(secret), tlsMinProtoVersion, alpnProtos...),
)
}
return fc
}
Expand Down
10 changes: 10 additions & 0 deletions internal/envoy/socket.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,13 @@ func UpstreamTLSTransportSocket(tls *envoy_api_v2_auth.UpstreamTlsContext) *envo
},
}
}

// DownstreamTLSTransportSocket returns a custom transport socket using the DownstreamTlsContext provided.
func DownstreamTLSTransportSocket(tls *envoy_api_v2_auth.DownstreamTlsContext) *envoy_api_v2_core.TransportSocket {
return &envoy_api_v2_core.TransportSocket{
Name: "tls",
ConfigType: &envoy_api_v2_core.TransportSocket_TypedConfig{
TypedConfig: toAny(tls),
},
}
}
24 changes: 24 additions & 0 deletions internal/envoy/socket_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,27 @@ func TestUpstreamTLSTransportSocket(t *testing.T) {
})
}
}

func TestDownstreamTLSTransportSocket(t *testing.T) {
tests := map[string]struct {
ctxt *envoy_api_v2_auth.DownstreamTlsContext
want *envoy_api_v2_core.TransportSocket
}{
"default/tls": {
ctxt: DownstreamTLSContext("default/tls", envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"),
want: &envoy_api_v2_core.TransportSocket{
Name: "tls",
ConfigType: &envoy_api_v2_core.TransportSocket_TypedConfig{
TypedConfig: toAny(DownstreamTLSContext("default/tls", envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1")),
},
},
},
}

for name, tc := range tests {
t.Run(name, func(t *testing.T) {
got := DownstreamTLSTransportSocket(tc.ctxt)
assert.Equal(t, tc.want, got)
})
}
}
16 changes: 13 additions & 3 deletions internal/featuretests/tlsprotocolversion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ import (

v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2"
envoy_api_v2_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth"
envoy_api_v2_listener "github.com/envoyproxy/go-control-plane/envoy/api/v2/listener"
ingressroutev1 "github.com/projectcontour/contour/apis/contour/v1beta1"
projcontour "github.com/projectcontour/contour/apis/projectcontour/v1"
"github.com/projectcontour/contour/internal/dag"
"github.com/projectcontour/contour/internal/envoy"
v1 "k8s.io/api/core/v1"
"k8s.io/api/networking/v1beta1"
Expand Down Expand Up @@ -126,10 +128,18 @@ func TestTLSMinimumProtocolVersion(t *testing.T) {
ListenerFilters: envoy.ListenerFilters(
envoy.TLSInspector(),
),
FilterChains: filterchaintls("kuard.example.com", sec1, envoy.HTTPConnectionManager("ingress_https", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), "h2", "http/1.1"),
FilterChains: []*envoy_api_v2_listener.FilterChain{
envoy.FilterChainTLS(
"kuard.example.com",
&dag.Secret{Object: sec1},
[]*envoy_api_v2_listener.Filter{
envoy.HTTPConnectionManager("ingress_https", envoy.FileAccessLogEnvoy("/dev/stdout"), 0),
},
envoy_api_v2_auth.TlsParameters_TLSv1_3,
"h2", "http/1.1",
),
},
}
// easier to patch this up than add more params to filterchaintls
l1.FilterChains[0].TlsContext.CommonTlsContext.TlsParams.TlsMinimumProtocolVersion = envoy_api_v2_auth.TlsParameters_TLSv1_3

c.Request(listenerType, "ingress_https").Equals(&v2.DiscoveryResponse{
Resources: resources(t,
Expand Down

0 comments on commit 7d8c73b

Please sign in to comment.