blob: cc26cb254a39a61b3d82a936faa92948c885ba9c [file] [log] [blame]
// Copyright Istio 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 model
import (
"testing"
"time"
)
import (
"github.com/davecgh/go-spew/spew"
core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
auth "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
matcher "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3"
"github.com/google/go-cmp/cmp"
"google.golang.org/protobuf/testing/protocmp"
"google.golang.org/protobuf/types/known/durationpb"
)
import (
"github.com/apache/dubbo-go-pixiu/pilot/pkg/model"
"github.com/apache/dubbo-go-pixiu/pkg/spiffe"
)
func TestConstructSdsSecretConfig(t *testing.T) {
testCases := []struct {
name string
secretName string
expected *auth.SdsSecretConfig
}{
{
name: "ConstructSdsSecretConfig",
secretName: "spiffe://cluster.local/ns/bar/sa/foo",
expected: &auth.SdsSecretConfig{
Name: "spiffe://cluster.local/ns/bar/sa/foo",
SdsConfig: &core.ConfigSource{
ResourceApiVersion: core.ApiVersion_V3,
ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
ApiConfigSource: &core.ApiConfigSource{
ApiType: core.ApiConfigSource_GRPC,
SetNodeOnFirstMessageOnly: true,
TransportApiVersion: core.ApiVersion_V3,
GrpcServices: []*core.GrpcService{
{
TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName},
},
},
},
},
},
},
},
},
{
name: "ConstructSdsSecretConfig without secretName",
secretName: "",
expected: nil,
},
}
for _, c := range testCases {
t.Run(c.name, func(t *testing.T) {
if got := ConstructSdsSecretConfig(c.secretName); !cmp.Equal(got, c.expected, protocmp.Transform()) {
t.Errorf("ConstructSdsSecretConfig: got(%#v), want(%#v)\n", got, c.expected)
}
})
}
}
func TestApplyToCommonTLSContext(t *testing.T) {
testCases := []struct {
name string
node *model.Proxy
trustDomainAliases []string
validateClient bool
expected *auth.CommonTlsContext
}{
{
name: "MTLSStrict using SDS",
node: &model.Proxy{
Metadata: &model.NodeMetadata{},
},
validateClient: true,
expected: &auth.CommonTlsContext{
TlsCertificateSdsSecretConfigs: []*auth.SdsSecretConfig{
{
Name: "default",
SdsConfig: &core.ConfigSource{
InitialFetchTimeout: durationpb.New(time.Second * 0),
ResourceApiVersion: core.ApiVersion_V3,
ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
ApiConfigSource: &core.ApiConfigSource{
ApiType: core.ApiConfigSource_GRPC,
SetNodeOnFirstMessageOnly: true,
TransportApiVersion: core.ApiVersion_V3,
GrpcServices: []*core.GrpcService{
{
TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName},
},
},
},
},
},
},
},
},
ValidationContextType: &auth.CommonTlsContext_CombinedValidationContext{
CombinedValidationContext: &auth.CommonTlsContext_CombinedCertificateValidationContext{
DefaultValidationContext: &auth.CertificateValidationContext{},
ValidationContextSdsSecretConfig: &auth.SdsSecretConfig{
Name: "ROOTCA",
SdsConfig: &core.ConfigSource{
InitialFetchTimeout: durationpb.New(time.Second * 0),
ResourceApiVersion: core.ApiVersion_V3,
ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
ApiConfigSource: &core.ApiConfigSource{
ApiType: core.ApiConfigSource_GRPC,
SetNodeOnFirstMessageOnly: true,
TransportApiVersion: core.ApiVersion_V3,
GrpcServices: []*core.GrpcService{
{
TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName},
},
},
},
},
},
},
},
},
},
},
},
{
name: "MTLSStrict using SDS and SAN aliases",
node: &model.Proxy{
Metadata: &model.NodeMetadata{},
},
validateClient: true,
trustDomainAliases: []string{"alias-1.domain", "some-other-alias-1.domain", "alias-2.domain"},
expected: &auth.CommonTlsContext{
TlsCertificateSdsSecretConfigs: []*auth.SdsSecretConfig{
{
Name: "default",
SdsConfig: &core.ConfigSource{
InitialFetchTimeout: durationpb.New(time.Second * 0),
ResourceApiVersion: core.ApiVersion_V3,
ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
ApiConfigSource: &core.ApiConfigSource{
ApiType: core.ApiConfigSource_GRPC,
SetNodeOnFirstMessageOnly: true,
TransportApiVersion: core.ApiVersion_V3,
GrpcServices: []*core.GrpcService{
{
TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName},
},
},
},
},
},
},
},
},
ValidationContextType: &auth.CommonTlsContext_CombinedValidationContext{
CombinedValidationContext: &auth.CommonTlsContext_CombinedCertificateValidationContext{
DefaultValidationContext: &auth.CertificateValidationContext{MatchSubjectAltNames: []*matcher.StringMatcher{
{MatchPattern: &matcher.StringMatcher_Prefix{Prefix: spiffe.URIPrefix + "alias-1.domain" + "/"}},
{MatchPattern: &matcher.StringMatcher_Prefix{Prefix: spiffe.URIPrefix + "some-other-alias-1.domain" + "/"}},
{MatchPattern: &matcher.StringMatcher_Prefix{Prefix: spiffe.URIPrefix + "alias-2.domain" + "/"}},
}},
ValidationContextSdsSecretConfig: &auth.SdsSecretConfig{
Name: "ROOTCA",
SdsConfig: &core.ConfigSource{
InitialFetchTimeout: durationpb.New(time.Second * 0),
ResourceApiVersion: core.ApiVersion_V3,
ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
ApiConfigSource: &core.ApiConfigSource{
ApiType: core.ApiConfigSource_GRPC,
SetNodeOnFirstMessageOnly: true,
TransportApiVersion: core.ApiVersion_V3,
GrpcServices: []*core.GrpcService{
{
TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName},
},
},
},
},
},
},
},
},
},
},
},
{
name: "MTLS using SDS with custom certs in metadata",
node: &model.Proxy{
Metadata: &model.NodeMetadata{
TLSServerCertChain: "serverCertChain",
TLSServerKey: "serverKey",
TLSServerRootCert: "servrRootCert",
},
},
validateClient: true,
expected: &auth.CommonTlsContext{
TlsCertificateSdsSecretConfigs: []*auth.SdsSecretConfig{
{
Name: "file-cert:serverCertChain~serverKey",
SdsConfig: &core.ConfigSource{
ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
ApiConfigSource: &core.ApiConfigSource{
ApiType: core.ApiConfigSource_GRPC,
SetNodeOnFirstMessageOnly: true,
TransportApiVersion: core.ApiVersion_V3,
GrpcServices: []*core.GrpcService{
{
TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName},
},
},
},
},
},
ResourceApiVersion: core.ApiVersion_V3,
},
},
},
ValidationContextType: &auth.CommonTlsContext_CombinedValidationContext{
CombinedValidationContext: &auth.CommonTlsContext_CombinedCertificateValidationContext{
DefaultValidationContext: &auth.CertificateValidationContext{},
ValidationContextSdsSecretConfig: &auth.SdsSecretConfig{
Name: "file-root:servrRootCert",
SdsConfig: &core.ConfigSource{
ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
ApiConfigSource: &core.ApiConfigSource{
ApiType: core.ApiConfigSource_GRPC,
SetNodeOnFirstMessageOnly: true,
TransportApiVersion: core.ApiVersion_V3,
GrpcServices: []*core.GrpcService{
{
TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName},
},
},
},
},
},
ResourceApiVersion: core.ApiVersion_V3,
},
},
},
},
},
},
{
name: "ISTIO_MUTUAL SDS without node meta",
node: &model.Proxy{
Metadata: &model.NodeMetadata{},
},
validateClient: true,
expected: &auth.CommonTlsContext{
TlsCertificateSdsSecretConfigs: []*auth.SdsSecretConfig{
{
Name: "default",
SdsConfig: &core.ConfigSource{
ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
ApiConfigSource: &core.ApiConfigSource{
ApiType: core.ApiConfigSource_GRPC,
SetNodeOnFirstMessageOnly: true,
TransportApiVersion: core.ApiVersion_V3,
GrpcServices: []*core.GrpcService{
{
TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName},
},
},
},
},
},
ResourceApiVersion: core.ApiVersion_V3,
InitialFetchTimeout: durationpb.New(time.Second * 0),
},
},
},
ValidationContextType: &auth.CommonTlsContext_CombinedValidationContext{
CombinedValidationContext: &auth.CommonTlsContext_CombinedCertificateValidationContext{
DefaultValidationContext: &auth.CertificateValidationContext{},
ValidationContextSdsSecretConfig: &auth.SdsSecretConfig{
Name: "ROOTCA",
SdsConfig: &core.ConfigSource{
ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
ApiConfigSource: &core.ApiConfigSource{
ApiType: core.ApiConfigSource_GRPC,
SetNodeOnFirstMessageOnly: true,
TransportApiVersion: core.ApiVersion_V3,
GrpcServices: []*core.GrpcService{
{
TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName},
},
},
},
},
},
ResourceApiVersion: core.ApiVersion_V3,
InitialFetchTimeout: durationpb.New(time.Second * 0),
},
},
},
},
},
},
{
name: "ISTIO_MUTUAL with custom cert paths from proxy node metadata",
node: &model.Proxy{
Metadata: &model.NodeMetadata{
TLSServerCertChain: "/custom/path/to/cert-chain.pem",
TLSServerKey: "/custom-key.pem",
TLSServerRootCert: "/custom/path/to/root.pem",
},
},
validateClient: true,
expected: &auth.CommonTlsContext{
TlsCertificateSdsSecretConfigs: []*auth.SdsSecretConfig{
{
Name: "file-cert:/custom/path/to/cert-chain.pem~/custom-key.pem",
SdsConfig: &core.ConfigSource{
ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
ApiConfigSource: &core.ApiConfigSource{
ApiType: core.ApiConfigSource_GRPC,
SetNodeOnFirstMessageOnly: true,
TransportApiVersion: core.ApiVersion_V3,
GrpcServices: []*core.GrpcService{
{
TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName},
},
},
},
},
},
ResourceApiVersion: core.ApiVersion_V3,
},
},
},
ValidationContextType: &auth.CommonTlsContext_CombinedValidationContext{
CombinedValidationContext: &auth.CommonTlsContext_CombinedCertificateValidationContext{
DefaultValidationContext: &auth.CertificateValidationContext{},
ValidationContextSdsSecretConfig: &auth.SdsSecretConfig{
Name: "file-root:/custom/path/to/root.pem",
SdsConfig: &core.ConfigSource{
ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
ApiConfigSource: &core.ApiConfigSource{
ApiType: core.ApiConfigSource_GRPC,
SetNodeOnFirstMessageOnly: true,
TransportApiVersion: core.ApiVersion_V3,
GrpcServices: []*core.GrpcService{
{
TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName},
},
},
},
},
},
ResourceApiVersion: core.ApiVersion_V3,
},
},
},
},
},
},
{
name: "SIMPLE with custom cert paths from proxy node metadata without cacerts",
node: &model.Proxy{
Metadata: &model.NodeMetadata{
TLSServerCertChain: "/custom/path/to/cert-chain.pem",
TLSServerKey: "/custom-key.pem",
},
},
validateClient: false,
expected: &auth.CommonTlsContext{
TlsCertificateSdsSecretConfigs: []*auth.SdsSecretConfig{
{
Name: "file-cert:/custom/path/to/cert-chain.pem~/custom-key.pem",
SdsConfig: &core.ConfigSource{
ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
ApiConfigSource: &core.ApiConfigSource{
ApiType: core.ApiConfigSource_GRPC,
SetNodeOnFirstMessageOnly: true,
TransportApiVersion: core.ApiVersion_V3,
GrpcServices: []*core.GrpcService{
{
TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName},
},
},
},
},
},
ResourceApiVersion: core.ApiVersion_V3,
},
},
},
},
},
}
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
tlsContext := &auth.CommonTlsContext{}
ApplyToCommonTLSContext(tlsContext, test.node, []string{}, test.trustDomainAliases, test.validateClient)
if !cmp.Equal(tlsContext, test.expected, protocmp.Transform()) {
t.Errorf("got(%#v), want(%#v)\n", spew.Sdump(tlsContext), spew.Sdump(test.expected))
}
})
}
}