Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V3 feature tests authorization #3080

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion cmd/contour/contour.go
Expand Up @@ -16,10 +16,11 @@ package main
import (
"os"

envoy_v3 "github.com/projectcontour/contour/internal/envoy/v3"

resource "github.com/envoyproxy/go-control-plane/pkg/resource/v2"
"github.com/projectcontour/contour/internal/build"
envoy_v2 "github.com/projectcontour/contour/internal/envoy/v2"
envoy_v3 "github.com/projectcontour/contour/internal/envoy/v3"
"github.com/projectcontour/contour/internal/k8s"
"github.com/projectcontour/contour/pkg/config"
"github.com/sirupsen/logrus"
Expand Down
3 changes: 3 additions & 0 deletions cmd/contour/serve.go
Expand Up @@ -656,6 +656,9 @@ func doServe(log logrus.FieldLogger, ctx *serveContext) error {
case config.ContourServerType:
contour_xds_v2.RegisterServer(contour_xds_v2.NewContourServer(log, xdscache.ResourcesOf(resources)...), grpcServer)
contour_xds_v3.RegisterServer(contour_xds_v3.NewContourServer(log, xdscache.ResourcesOf(resources)...), grpcServer)
default:
// This can't happen due to config validation.
log.Fatalf("invalid xdsServerType %q configured", ctx.Config.Server.XDSServerType)
}

addr := net.JoinHostPort(ctx.xdsAddr, strconv.Itoa(ctx.xdsPort))
Expand Down
1 change: 1 addition & 0 deletions examples/contour/03-envoy.yaml
Expand Up @@ -99,6 +99,7 @@ spec:
- /config/envoy.json
- --xds-address=contour
- --xds-port=8001
- --xds-resource-version=v3
- --resources-dir=/config/resources
- --envoy-cafile=/certs/ca.crt
- --envoy-cert-file=/certs/tls.crt
Expand Down
1 change: 1 addition & 0 deletions examples/render/contour.yaml
Expand Up @@ -1849,6 +1849,7 @@ spec:
- /config/envoy.json
- --xds-address=contour
- --xds-port=8001
- --xds-resource-version=v3
- --resources-dir=/config/resources
- --envoy-cafile=/certs/ca.crt
- --envoy-cert-file=/certs/tls.crt
Expand Down
12 changes: 12 additions & 0 deletions internal/envoy/cluster.go
Expand Up @@ -20,6 +20,9 @@ import (
"strconv"
"strings"

envoy_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
envoy_type "github.com/envoyproxy/go-control-plane/envoy/type/v3"

"github.com/projectcontour/contour/internal/dag"
)

Expand Down Expand Up @@ -122,3 +125,12 @@ func AnyPositive(first uint32, rest ...uint32) bool {
}
return false
}

// ClusterCommonLBConfig creates a *v2.Cluster_CommonLbConfig with HealthyPanicThreshold disabled.
func ClusterCommonLBConfig() *envoy_cluster_v3.Cluster_CommonLbConfig {
return &envoy_cluster_v3.Cluster_CommonLbConfig{
HealthyPanicThreshold: &envoy_type.Percent{ // Disable HealthyPanicThreshold
Value: 0,
},
}
}
4 changes: 2 additions & 2 deletions internal/envoy/v2/listener.go
Expand Up @@ -435,7 +435,7 @@ func Filters(filters ...*envoy_api_v2_listener.Filter) []*envoy_api_v2_listener.
return filters
}

// FilterChain retruns a *envoy_api_v2_listener.FilterChain for the supplied filters.
// FilterChain returns a *envoy_api_v2_listener.FilterChain for the supplied filters.
func FilterChain(filters ...*envoy_api_v2_listener.Filter) *envoy_api_v2_listener.FilterChain {
return &envoy_api_v2_listener.FilterChain{
Filters: filters,
Expand Down Expand Up @@ -548,7 +548,7 @@ func FilterChainTLS(domain string, downstream *envoy_api_v2_auth.DownstreamTlsCo
return fc
}

// FilterChainTLSFallback returns a TLS enabled envoy_api_v2_listener.FilterChain conifgured for FallbackCertificate.
// FilterChainTLSFallback returns a TLS enabled envoy_api_v2_listener.FilterChain configured for FallbackCertificate.
func FilterChainTLSFallback(downstream *envoy_api_v2_auth.DownstreamTlsContext, filters []*envoy_api_v2_listener.Filter) *envoy_api_v2_listener.FilterChain {
fc := &envoy_api_v2_listener.FilterChain{
Name: "fallback-certificate",
Expand Down
2 changes: 1 addition & 1 deletion internal/envoy/v2/regex.go
Expand Up @@ -29,7 +29,7 @@ import (
// and https://github.com/projectcontour/contour/issues/2240
const maxRegexProgramSize = 1 << 20

// SafeRegexMatch retruns a matcher.RegexMatcher for the supplied regex.
// SafeRegexMatch returns a matcher.RegexMatcher for the supplied regex.
// SafeRegexMatch does not escape regex meta characters.
func SafeRegexMatch(regex string) *matcher.RegexMatcher {
return &matcher.RegexMatcher{
Expand Down
70 changes: 70 additions & 0 deletions internal/envoy/v3/accesslog.go
@@ -0,0 +1,70 @@
// Copyright Project Contour Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package v3

import (
accesslog "github.com/envoyproxy/go-control-plane/envoy/config/accesslog/v3"
accesslogv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/file/v3"
"github.com/envoyproxy/go-control-plane/pkg/wellknown"
_struct "github.com/golang/protobuf/ptypes/struct"
"github.com/projectcontour/contour/internal/protobuf"
"github.com/projectcontour/contour/pkg/config"
)

// FileAccessLogEnvoy returns a new file based access log filter
// that will output Envoy's default access logs.
func FileAccessLogEnvoy(path string) []*accesslog.AccessLog {
return []*accesslog.AccessLog{{
Name: wellknown.FileAccessLog,
ConfigType: &accesslog.AccessLog_TypedConfig{
TypedConfig: protobuf.MustMarshalAny(&accesslogv3.FileAccessLog{
Path: path,
// AccessLogFormat left blank to defer to Envoy's default log format.
}),
},
}}
}

// FileAccessLogJSON returns a new file based access log filter
// that will log in JSON format
func FileAccessLogJSON(path string, fields config.AccessLogFields) []*accesslog.AccessLog {

jsonformat := &_struct.Struct{
Fields: make(map[string]*_struct.Value),
}

for k, v := range fields.AsFieldMap() {
jsonformat.Fields[k] = sv(v)
}

return []*accesslog.AccessLog{{
Name: wellknown.FileAccessLog,
ConfigType: &accesslog.AccessLog_TypedConfig{
TypedConfig: protobuf.MustMarshalAny(&accesslogv3.FileAccessLog{
Path: path,
AccessLogFormat: &accesslogv3.FileAccessLog_JsonFormat{
JsonFormat: jsonformat,
},
}),
},
}}
}

func sv(s string) *_struct.Value {
return &_struct.Value{
Kind: &_struct.Value_StringValue{
StringValue: s,
},
}
}
110 changes: 110 additions & 0 deletions internal/envoy/v3/auth.go
@@ -0,0 +1,110 @@
// Copyright Project Contour Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package v3

import (
envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
envoy_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
envoy_matcher_v3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3"
"github.com/projectcontour/contour/internal/dag"
"github.com/projectcontour/contour/internal/envoy"
"github.com/projectcontour/contour/internal/protobuf"
)

// UpstreamTLSContext creates an envoy_tls_v3.UpstreamTlsContext. By default
// UpstreamTLSContext returns a HTTP/1.1 TLS enabled context. A list of
// additional ALPN protocols can be provided.
func UpstreamTLSContext(peerValidationContext *dag.PeerValidationContext, sni string, clientSecret *dag.Secret, alpnProtocols ...string) *envoy_tls_v3.UpstreamTlsContext {
var clientSecretConfigs []*envoy_tls_v3.SdsSecretConfig
if clientSecret != nil {
clientSecretConfigs = []*envoy_tls_v3.SdsSecretConfig{{
Name: envoy.Secretname(clientSecret),
SdsConfig: ConfigSource("contour"),
}}
}

context := &envoy_tls_v3.UpstreamTlsContext{
CommonTlsContext: &envoy_tls_v3.CommonTlsContext{
AlpnProtocols: alpnProtocols,
TlsCertificateSdsSecretConfigs: clientSecretConfigs,
},
Sni: sni,
}

if peerValidationContext.GetCACertificate() != nil && len(peerValidationContext.GetSubjectName()) > 0 {
// We have to explicitly assign the value from validationContext
// to context.CommonTlsContext.ValidationContextType because the
// latter is an interface. Returning nil from validationContext
// directly into this field boxes the nil into the unexported
// type of this grpc OneOf field which causes proto marshaling
// to explode later on.
vc := validationContext(peerValidationContext.GetCACertificate(), peerValidationContext.GetSubjectName())
if vc != nil {
context.CommonTlsContext.ValidationContextType = vc
}
}

return context
}

func validationContext(ca []byte, subjectName string) *envoy_tls_v3.CommonTlsContext_ValidationContext {
vc := &envoy_tls_v3.CommonTlsContext_ValidationContext{
ValidationContext: &envoy_tls_v3.CertificateValidationContext{
TrustedCa: &envoy_core_v3.DataSource{
// TODO(dfc) update this for SDS
Specifier: &envoy_core_v3.DataSource_InlineBytes{
InlineBytes: ca,
},
},
},
}

if len(subjectName) > 0 {
vc.ValidationContext.MatchSubjectAltNames = []*envoy_matcher_v3.StringMatcher{{
MatchPattern: &envoy_matcher_v3.StringMatcher_Exact{
Exact: subjectName,
}},
}
}

return vc
}

// DownstreamTLSContext creates a new DownstreamTlsContext.
func DownstreamTLSContext(serverSecret *dag.Secret, tlsMinProtoVersion envoy_tls_v3.TlsParameters_TlsProtocol, peerValidationContext *dag.PeerValidationContext, alpnProtos ...string) *envoy_tls_v3.DownstreamTlsContext {
context := &envoy_tls_v3.DownstreamTlsContext{
CommonTlsContext: &envoy_tls_v3.CommonTlsContext{
TlsParams: &envoy_tls_v3.TlsParameters{
TlsMinimumProtocolVersion: tlsMinProtoVersion,
TlsMaximumProtocolVersion: envoy_tls_v3.TlsParameters_TLSv1_3,
CipherSuites: envoy.Ciphers,
},
TlsCertificateSdsSecretConfigs: []*envoy_tls_v3.SdsSecretConfig{{
Name: envoy.Secretname(serverSecret),
SdsConfig: ConfigSource("contour"),
}},
AlpnProtocols: alpnProtos,
},
}

if peerValidationContext.GetCACertificate() != nil {
vc := validationContext(peerValidationContext.GetCACertificate(), "")
if vc != nil {
context.CommonTlsContext.ValidationContextType = vc
context.RequireClientCertificate = protobuf.Bool(true)
}
}

return context
}
10 changes: 10 additions & 0 deletions internal/envoy/v3/cluster.go
Expand Up @@ -16,6 +16,7 @@ package v3
import (
envoy_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
envoy_type "github.com/envoyproxy/go-control-plane/envoy/type/v3"
)

// ConfigSource returns a *envoy_core_v3.ConfigSource for cluster.
Expand All @@ -38,6 +39,15 @@ func ConfigSource(cluster string) *envoy_core_v3.ConfigSource {
}
}

// ClusterCommonLBConfig creates a *envoy_cluster_v3.Cluster_CommonLbConfig with HealthyPanicThreshold disabled.
func ClusterCommonLBConfig() *envoy_cluster_v3.Cluster_CommonLbConfig {
return &envoy_cluster_v3.Cluster_CommonLbConfig{
HealthyPanicThreshold: &envoy_type.Percent{ // Disable HealthyPanicThreshold
Value: 0,
},
}
}

// ClusterDiscoveryType returns the type of a ClusterDiscovery as a Cluster_type.
func ClusterDiscoveryType(t envoy_cluster_v3.Cluster_DiscoveryType) *envoy_cluster_v3.Cluster_Type {
return &envoy_cluster_v3.Cluster_Type{Type: t}
Expand Down