Skip to content

Commit

Permalink
internal/contour: auth.SdsSecretConfig for auth.CommonTlsContext
Browse files Browse the repository at this point in the history
Addresses the non-goals of the high0level design for secret discovery,
converting auth.CommonTlsContext from TlsCertificates with inline bytes
for secret data to TlsCertificateSdsSecretConfigs for secret references
from the xDS gRPC server.

Updates: projectcontour#898
Signed-off-by: Matt Alberts <[email protected]>
  • Loading branch information
Matt Alberts committed Apr 30, 2019
1 parent 48c93c1 commit cda64ab
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 56 deletions.
2 changes: 2 additions & 0 deletions cmd/contour/contour.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ func main() {
bootstrap.Flag("stats-address", "Envoy /stats interface address").StringVar(&config.StatsAddress)
bootstrap.Flag("stats-port", "Envoy /stats interface port").IntVar(&config.StatsPort)
bootstrap.Flag("xds-address", "xDS gRPC API address").StringVar(&config.XDSAddress)
bootstrap.Flag("xds-cluster", "xDS gRPC API cluster name").StringVar(&config.XDSClusterName)
bootstrap.Flag("xds-port", "xDS gRPC API port").IntVar(&config.XDSGRPCPort)
bootstrap.Flag("statsd-enabled", "enable statsd output").BoolVar(&config.StatsdEnabled)
bootstrap.Flag("statsd-address", "statsd address").StringVar(&config.StatsdAddress)
Expand Down Expand Up @@ -141,6 +142,7 @@ func main() {
serve.Flag("use-proxy-protocol", "Use PROXY protocol for all listeners").BoolVar(&ch.UseProxyProto)
serve.Flag("ingress-class-name", "Contour IngressClass name").StringVar(&reh.IngressClass)
serve.Flag("ingressroute-root-namespaces", "Restrict contour to searching these namespaces for root ingress routes").StringVar(&ingressrouteRootNamespaceFlag)
serve.Flag("xds-cluster", "xDS gRPC API cluster name").Default(contour.DEFAULT_XDS_CLUSTER_NAME).StringVar(&ch.XDSClusterName)

args := os.Args[1:]
switch kingpin.MustParse(app.Parse(args)) {
Expand Down
9 changes: 6 additions & 3 deletions internal/contour/listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"github.com/gogo/protobuf/proto"
"github.com/heptio/contour/internal/dag"
"github.com/heptio/contour/internal/envoy"
"k8s.io/api/core/v1"
)

const (
Expand All @@ -33,6 +32,7 @@ const (
DEFAULT_HTTPS_ACCESS_LOG = "/dev/stdout"
DEFAULT_HTTPS_LISTENER_ADDRESS = DEFAULT_HTTP_LISTENER_ADDRESS
DEFAULT_HTTPS_LISTENER_PORT = 8443
DEFAULT_XDS_CLUSTER_NAME = "contour"
)

// ListenerVisitorConfig holds configuration parameters for visitListeners.
Expand Down Expand Up @@ -61,6 +61,10 @@ type ListenerVisitorConfig struct {
// If not set, defaults to DEFAULT_HTTPS_ACCESS_LOG.
HTTPSAccessLog string

// Envoy's XDX gRPC API cluster name references.
// If not set, defaults to DEFAULT_XDS_CLUSTER_NAME.
XDSClusterName string

// UseProxyProto configurs all listeners to expect a PROXY
// V1 or V2 preamble.
// If not set, defaults to false.
Expand Down Expand Up @@ -261,8 +265,7 @@ func (v *listenerVisitor) visit(vertex dag.Vertex) {

// attach certificate data to this listener if provided.
if vh.Secret != nil {
data := vh.Secret.Data()
fc.TlsContext = envoy.DownstreamTLSContext(data[v1.TLSCertKey], data[v1.TLSPrivateKeyKey], vh.MinProtoVersion, alpnProtos...)
fc.TlsContext = envoy.DownstreamTLSContext(envoy.Secretname(vh.Secret), v.XDSClusterName, vh.MinProtoVersion, alpnProtos...)
}

v.listeners[ENVOY_HTTPS_LISTENER].FilterChains = append(v.listeners[ENVOY_HTTPS_LISTENER].FilterChains, fc)
Expand Down
25 changes: 18 additions & 7 deletions internal/contour/listener_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ func TestListenerVisit(t *testing.T) {
}),
},
"simple ingress with secret": {
ListenerVisitorConfig: ListenerVisitorConfig{
XDSClusterName: "cluster",
},
objs: []interface{}{
&v1beta1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Expand Down Expand Up @@ -169,6 +172,9 @@ func TestListenerVisit(t *testing.T) {
}),
},
"simple ingressroute with secret": {
ListenerVisitorConfig: ListenerVisitorConfig{
XDSClusterName: "cluster",
},
objs: []interface{}{
&ingressroutev1.IngressRoute{
ObjectMeta: metav1.ObjectMeta{
Expand Down Expand Up @@ -242,6 +248,9 @@ func TestListenerVisit(t *testing.T) {
want: map[string]*v2.Listener{},
},
"simple tls ingress with allow-http:false": {
ListenerVisitorConfig: ListenerVisitorConfig{
XDSClusterName: "cluster",
},
objs: []interface{}{
&v1beta1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Expand Down Expand Up @@ -287,10 +296,11 @@ func TestListenerVisit(t *testing.T) {
},
"http listener on non default port": { // issue 72
ListenerVisitorConfig: ListenerVisitorConfig{
HTTPAddress: "127.0.0.100",
HTTPPort: 9100,
HTTPSAddress: "127.0.0.200",
HTTPSPort: 9200,
HTTPAddress: "127.0.0.100",
HTTPPort: 9100,
HTTPSAddress: "127.0.0.200",
HTTPSPort: 9200,
XDSClusterName: "cluster",
},
objs: []interface{}{
&v1beta1.Ingress{
Expand Down Expand Up @@ -338,7 +348,8 @@ func TestListenerVisit(t *testing.T) {
},
"use proxy proto": {
ListenerVisitorConfig: ListenerVisitorConfig{
UseProxyProto: true,
XDSClusterName: "cluster",
UseProxyProto: true,
},
objs: []interface{}{
&v1beta1.Ingress{
Expand Down Expand Up @@ -392,6 +403,7 @@ func TestListenerVisit(t *testing.T) {
ListenerVisitorConfig: ListenerVisitorConfig{
HTTPAccessLog: "/tmp/http_access.log",
HTTPSAccessLog: "/tmp/https_access.log",
XDSClusterName: "cluster",
},
objs: []interface{}{
&v1beta1.Ingress{
Expand Down Expand Up @@ -470,8 +482,7 @@ func filterchain(filters ...listener.Filter) []listener.FilterChain {
}

func tlscontext(tlsMinProtoVersion auth.TlsParameters_TlsProtocol, alpnprotos ...string) *auth.DownstreamTlsContext {
data := secretdata("certificate", "key")
return envoy.DownstreamTLSContext(data[v1.TLSCertKey], data[v1.TLSPrivateKeyKey], tlsMinProtoVersion, alpnprotos...)
return envoy.DownstreamTLSContext("default/secret/735ad571c1", "cluster", tlsMinProtoVersion, alpnprotos...)
}

func secretdata(cert, key string) map[string][]byte {
Expand Down
6 changes: 5 additions & 1 deletion internal/contour/visitor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,14 @@ func TestVisitListeners(t *testing.T) {
}

tests := map[string]struct {
ListenerVisitorConfig
root dag.Visitable
want map[string]*v2.Listener
}{
"TCPService forward": {
ListenerVisitorConfig: ListenerVisitorConfig{
XDSClusterName: "cluster",
},
root: &dag.Listener{
Port: 443,
VirtualHosts: virtualhosts(
Expand Down Expand Up @@ -148,7 +152,7 @@ func TestVisitListeners(t *testing.T) {

for name, tc := range tests {
t.Run(name, func(t *testing.T) {
got := visitListeners(tc.root, new(ListenerVisitorConfig))
got := visitListeners(tc.root, &tc.ListenerVisitorConfig)
if diff := cmp.Diff(tc.want, got); diff != "" {
t.Fatal(diff)
}
Expand Down
39 changes: 21 additions & 18 deletions internal/e2e/lds_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/gogo/protobuf/types"
"github.com/heptio/contour/apis/generated/clientset/versioned/fake"
"github.com/heptio/contour/internal/contour"
"github.com/heptio/contour/internal/dag"
"github.com/heptio/contour/internal/envoy"
"github.com/heptio/contour/internal/k8s"
"google.golang.org/grpc"
Expand Down Expand Up @@ -191,7 +192,7 @@ func TestTLSListener(t *testing.T) {
ListenerFilters: []listener.ListenerFilter{
envoy.TLSInspector(),
},
FilterChains: filterchaintls("kuard.example.com", envoy.HTTPConnectionManager("ingress_https", "/dev/stdout"), "h2", "http/1.1"),
FilterChains: filterchaintls("kuard.example.com", s1, envoy.HTTPConnectionManager("ingress_https", "/dev/stdout"), "h2", "http/1.1"),
}),
},
TypeUrl: listenerType,
Expand Down Expand Up @@ -227,7 +228,7 @@ func TestTLSListener(t *testing.T) {
ListenerFilters: []listener.ListenerFilter{
envoy.TLSInspector(),
},
FilterChains: filterchaintls("kuard.example.com", envoy.HTTPConnectionManager("ingress_https", "/dev/stdout"), "h2", "http/1.1"),
FilterChains: filterchaintls("kuard.example.com", s1, envoy.HTTPConnectionManager("ingress_https", "/dev/stdout"), "h2", "http/1.1"),
}),
},
TypeUrl: listenerType,
Expand Down Expand Up @@ -325,7 +326,7 @@ func TestIngressRouteTLSListener(t *testing.T) {
ListenerFilters: []listener.ListenerFilter{
envoy.TLSInspector(),
},
FilterChains: filterchaintls("kuard.example.com", envoy.HTTPConnectionManager("ingress_https", "/dev/stdout"), "h2", "http/1.1"),
FilterChains: filterchaintls("kuard.example.com", s1, envoy.HTTPConnectionManager("ingress_https", "/dev/stdout"), "h2", "http/1.1"),
}

l1.FilterChains[0].TlsContext.CommonTlsContext.TlsParams.TlsMinimumProtocolVersion = auth.TlsParameters_TLSv1_1
Expand Down Expand Up @@ -370,7 +371,7 @@ func TestIngressRouteTLSListener(t *testing.T) {
ListenerFilters: []listener.ListenerFilter{
envoy.TLSInspector(),
},
FilterChains: filterchaintls("kuard.example.com", envoy.HTTPConnectionManager("ingress_https", "/dev/stdout"), "h2", "http/1.1"),
FilterChains: filterchaintls("kuard.example.com", s1, envoy.HTTPConnectionManager("ingress_https", "/dev/stdout"), "h2", "http/1.1"),
}

l2.FilterChains[0].TlsContext.CommonTlsContext.TlsParams.TlsMinimumProtocolVersion = auth.TlsParameters_TLSv1_3
Expand Down Expand Up @@ -437,7 +438,7 @@ func TestLDSFilter(t *testing.T) {
ListenerFilters: []listener.ListenerFilter{
envoy.TLSInspector(),
},
FilterChains: filterchaintls("kuard.example.com", envoy.HTTPConnectionManager("ingress_https", "/dev/stdout"), "h2", "http/1.1"),
FilterChains: filterchaintls("kuard.example.com", s1, envoy.HTTPConnectionManager("ingress_https", "/dev/stdout"), "h2", "http/1.1"),
}),
},
TypeUrl: listenerType,
Expand Down Expand Up @@ -523,7 +524,7 @@ func TestLDSTLSMinimumProtocolVersion(t *testing.T) {
ListenerFilters: []listener.ListenerFilter{
envoy.TLSInspector(),
},
FilterChains: filterchaintls("kuard.example.com", envoy.HTTPConnectionManager("ingress_https", "/dev/stdout"), "h2", "http/1.1"),
FilterChains: filterchaintls("kuard.example.com", s1, envoy.HTTPConnectionManager("ingress_https", "/dev/stdout"), "h2", "http/1.1"),
}),
},
TypeUrl: listenerType,
Expand Down Expand Up @@ -556,7 +557,7 @@ func TestLDSTLSMinimumProtocolVersion(t *testing.T) {
ListenerFilters: []listener.ListenerFilter{
envoy.TLSInspector(),
},
FilterChains: filterchaintls("kuard.example.com", envoy.HTTPConnectionManager("ingress_https", "/dev/stdout"), "h2", "http/1.1"),
FilterChains: filterchaintls("kuard.example.com", s1, envoy.HTTPConnectionManager("ingress_https", "/dev/stdout"), "h2", "http/1.1"),
}
// easier to patch this up than add more params to filterchaintls
l1.FilterChains[0].TlsContext.CommonTlsContext.TlsParams.TlsMinimumProtocolVersion = auth.TlsParameters_TLSv1_3
Expand Down Expand Up @@ -672,7 +673,7 @@ func TestLDSIngressHTTPSUseProxyProtocol(t *testing.T) {
envoy.ProxyProtocol(),
envoy.TLSInspector(),
},
FilterChains: filterchaintls("kuard.example.com", envoy.HTTPConnectionManager("ingress_https", "/dev/stdout"), "h2", "http/1.1"),
FilterChains: filterchaintls("kuard.example.com", s1, envoy.HTTPConnectionManager("ingress_https", "/dev/stdout"), "h2", "http/1.1"),
}
assertEqual(t, &v2.DiscoveryResponse{
VersionInfo: "2",
Expand Down Expand Up @@ -754,7 +755,7 @@ func TestLDSCustomAddressAndPort(t *testing.T) {
ListenerFilters: []listener.ListenerFilter{
envoy.TLSInspector(),
},
FilterChains: filterchaintls("kuard.example.com", envoy.HTTPConnectionManager("ingress_https", "/dev/stdout"), "h2", "http/1.1"),
FilterChains: filterchaintls("kuard.example.com", s1, envoy.HTTPConnectionManager("ingress_https", "/dev/stdout"), "h2", "http/1.1"),
}
assertEqual(t, &v2.DiscoveryResponse{
VersionInfo: "2",
Expand Down Expand Up @@ -825,7 +826,7 @@ func TestLDSCustomAccessLogPaths(t *testing.T) {
ListenerFilters: []listener.ListenerFilter{
envoy.TLSInspector(),
},
FilterChains: filterchaintls("kuard.example.com", envoy.HTTPConnectionManager("ingress_https", "/tmp/https_access.log"), "h2", "http/1.1"),
FilterChains: filterchaintls("kuard.example.com", s1, envoy.HTTPConnectionManager("ingress_https", "/tmp/https_access.log"), "h2", "http/1.1"),
}
assertEqual(t, &v2.DiscoveryResponse{
VersionInfo: "2",
Expand Down Expand Up @@ -1008,7 +1009,7 @@ func TestIngressRouteHTTPS(t *testing.T) {
ListenerFilters: []listener.ListenerFilter{
envoy.TLSInspector(),
},
FilterChains: filterchaintls("example.com", envoy.HTTPConnectionManager("ingress_https", "/dev/stdout"), "h2", "http/1.1"),
FilterChains: filterchaintls("example.com", s1, envoy.HTTPConnectionManager("ingress_https", "/dev/stdout"), "h2", "http/1.1"),
}
assertEqual(t, &v2.DiscoveryResponse{
VersionInfo: "2",
Expand Down Expand Up @@ -1144,7 +1145,7 @@ func TestLDSIngressRouteTCPForward(t *testing.T) {
ingressHTTPS := &v2.Listener{
Name: "ingress_https",
Address: *envoy.SocketAddress("0.0.0.0", 8443),
FilterChains: filterchaintls("kuard-tcp.example.com", tcpproxy("ingress_https", "default/correct-backend/80/da39a3ee5e")),
FilterChains: filterchaintls("kuard-tcp.example.com", s1, tcpproxy("ingress_https", "default/correct-backend/80/da39a3ee5e")),
ListenerFilters: []listener.ListenerFilter{
envoy.TLSInspector(),
},
Expand Down Expand Up @@ -1173,8 +1174,7 @@ func TestIngressRouteTLSCertificateDelegation(t *testing.T) {
Nonce: "0",
}, streamLDS(t, cc))

// add a secret object secret/wildcard.
rh.OnAdd(&v1.Secret{
s1 := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "wildcard",
Namespace: "secret",
Expand All @@ -1183,7 +1183,10 @@ func TestIngressRouteTLSCertificateDelegation(t *testing.T) {
v1.TLSCertKey: []byte("certificate"),
v1.TLSPrivateKeyKey: []byte("key"),
},
})
}

// add a secret object secret/wildcard.
rh.OnAdd(s1)

// add an ingressroute in a different namespace mentioning secret/wildcard.
rh.OnAdd(&ingressroutev1.IngressRoute{
Expand Down Expand Up @@ -1247,7 +1250,7 @@ func TestIngressRouteTLSCertificateDelegation(t *testing.T) {
ListenerFilters: []listener.ListenerFilter{
envoy.TLSInspector(),
},
FilterChains: filterchaintls("example.com", envoy.HTTPConnectionManager("ingress_https", "/dev/stdout"), "h2", "http/1.1"),
FilterChains: filterchaintls("example.com", s1, envoy.HTTPConnectionManager("ingress_https", "/dev/stdout"), "h2", "http/1.1"),
}

assertEqual(t, &v2.DiscoveryResponse{
Expand Down Expand Up @@ -1366,7 +1369,7 @@ func filterchain(filters ...listener.Filter) []listener.FilterChain {
return []listener.FilterChain{fc}
}

func filterchaintls(domain string, filter listener.Filter, alpn ...string) []listener.FilterChain {
func filterchaintls(domain string, secret *v1.Secret, filter listener.Filter, alpn ...string) []listener.FilterChain {
fc := listener.FilterChain{
Filters: []listener.Filter{
filter,
Expand All @@ -1375,7 +1378,7 @@ func filterchaintls(domain string, filter listener.Filter, alpn ...string) []lis
fc.FilterChainMatch = &listener.FilterChainMatch{
ServerNames: []string{domain},
}
fc.TlsContext = envoy.DownstreamTLSContext([]byte("certificate"), []byte("key"), auth.TlsParameters_TLSv1_1, alpn...)
fc.TlsContext = envoy.DownstreamTLSContext(envoy.Secretname(&dag.Secret{Object: secret}), "", auth.TlsParameters_TLSv1_1, alpn...)
return []listener.FilterChain{fc}
}

Expand Down
17 changes: 4 additions & 13 deletions internal/envoy/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ package envoy

import (
"github.com/envoyproxy/go-control-plane/envoy/api/v2/auth"
"github.com/envoyproxy/go-control-plane/envoy/api/v2/core"
)

var (
Expand Down Expand Up @@ -56,25 +55,17 @@ func UpstreamTLSContext(alpnProtocols ...string) *auth.UpstreamTlsContext {
}

// DownstreamTLSContext creates a new DownstreamTlsContext.
func DownstreamTLSContext(cert, key []byte, tlsMinProtoVersion auth.TlsParameters_TlsProtocol, alpnProtos ...string) *auth.DownstreamTlsContext {
func DownstreamTLSContext(secretName, clusterName string, tlsMinProtoVersion auth.TlsParameters_TlsProtocol, alpnProtos ...string) *auth.DownstreamTlsContext {
return &auth.DownstreamTlsContext{
CommonTlsContext: &auth.CommonTlsContext{
TlsParams: &auth.TlsParameters{
TlsMinimumProtocolVersion: tlsMinProtoVersion,
TlsMaximumProtocolVersion: auth.TlsParameters_TLSv1_3,
CipherSuites: ciphers,
},
TlsCertificates: []*auth.TlsCertificate{{
CertificateChain: &core.DataSource{
Specifier: &core.DataSource_InlineBytes{
InlineBytes: cert,
},
},
PrivateKey: &core.DataSource{
Specifier: &core.DataSource_InlineBytes{
InlineBytes: key,
},
},
TlsCertificateSdsSecretConfigs: []*auth.SdsSecretConfig{{
Name: secretName,
SdsConfig: ConfigSource(clusterName),
}},
AlpnProtocols: alpnProtos,
},
Expand Down
8 changes: 6 additions & 2 deletions internal/envoy/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ import (
func Bootstrap(c *BootstrapConfig) *bootstrap.Bootstrap {
b := &bootstrap.Bootstrap{
DynamicResources: &bootstrap.Bootstrap_DynamicResources{
LdsConfig: ConfigSource("contour"),
CdsConfig: ConfigSource("contour"),
LdsConfig: ConfigSource(stringOrDefault(c.XDSClusterName, "contour")),
CdsConfig: ConfigSource(stringOrDefault(c.XDSClusterName, "contour")),
},
StaticResources: &bootstrap.Bootstrap_StaticResources{
Listeners: []api.Listener{{
Expand Down Expand Up @@ -204,6 +204,10 @@ type BootstrapConfig struct {
// Defaults to 127.0.0.1.
XDSAddress string

// XDSClusterName is the name reference for the gROC XDS management server.
// Defaults to contour.
XDSClusterName string

// XDSGRPCPort is the management server port that provides the v2 gRPC API.
// Defaults to 8001.
XDSGRPCPort int
Expand Down
Loading

0 comments on commit cda64ab

Please sign in to comment.