Merge pull request #12676 from hashicorp/implement-lambda-patching
Implement Lambda Patching in the Serverless Plugin
This commit is contained in:
commit
9b291d362a
|
@ -642,13 +642,19 @@ func TestConfigSnapshotTerminatingGatewayIgnoreExtraResolvers(t testing.T) *Conf
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfigSnapshotTerminatingGatewayWithServiceDefaultsMeta(t testing.T) *ConfigSnapshot {
|
func TestConfigSnapshotTerminatingGatewayWithLambdaService(t testing.T) *ConfigSnapshot {
|
||||||
web := structs.NewServiceName("web", nil)
|
web := structs.NewServiceName("web", nil)
|
||||||
return TestConfigSnapshotTerminatingGateway(t, true, nil, []agentcache.UpdateEvent{
|
return TestConfigSnapshotTerminatingGateway(t, true, nil, []agentcache.UpdateEvent{
|
||||||
{
|
{
|
||||||
CorrelationID: serviceConfigIDPrefix + web.String(),
|
CorrelationID: serviceConfigIDPrefix + web.String(),
|
||||||
Result: &structs.ServiceConfigResponse{
|
Result: &structs.ServiceConfigResponse{
|
||||||
Meta: map[string]string{"a": "b"},
|
ProxyConfig: map[string]interface{}{"protocol": "http"},
|
||||||
|
Meta: map[string]string{
|
||||||
|
"serverless.consul.hashicorp.com/v1alpha1/lambda/enabled": "true",
|
||||||
|
"serverless.consul.hashicorp.com/v1alpha1/lambda/arn": "lambda-arn",
|
||||||
|
"serverless.consul.hashicorp.com/v1alpha1/lambda/payload-passthrough": "true",
|
||||||
|
"serverless.consul.hashicorp.com/v1alpha1/lambda/region": "us-east-1",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
107
agent/xds/serverless_plugin_oss_test.go
Normal file
107
agent/xds/serverless_plugin_oss_test.go
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
//go:build !consulent
|
||||||
|
// +build !consulent
|
||||||
|
|
||||||
|
package xds
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
envoy_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
|
||||||
|
envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
testinf "github.com/mitchellh/go-testing-interface"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/agent/proxycfg"
|
||||||
|
"github.com/hashicorp/consul/agent/xds/proxysupport"
|
||||||
|
"github.com/hashicorp/consul/agent/xds/serverlessplugin"
|
||||||
|
"github.com/hashicorp/consul/agent/xds/xdscommon"
|
||||||
|
"github.com/hashicorp/consul/sdk/testutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestServerlessPluginFromSnapshot(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
create func(t testinf.T) *proxycfg.ConfigSnapshot
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "lambda-terminating-gateway",
|
||||||
|
create: proxycfg.TestConfigSnapshotTerminatingGatewayWithLambdaService,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
latestEnvoyVersion := proxysupport.EnvoyVersions[0]
|
||||||
|
for _, envoyVersion := range proxysupport.EnvoyVersions {
|
||||||
|
sf, err := determineSupportedProxyFeaturesFromString(envoyVersion)
|
||||||
|
require.NoError(t, err)
|
||||||
|
t.Run("envoy-"+envoyVersion, func(t *testing.T) {
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
// Sanity check default with no overrides first
|
||||||
|
snap := tt.create(t)
|
||||||
|
|
||||||
|
// We need to replace the TLS certs with deterministic ones to make golden
|
||||||
|
// files workable. Note we don't update these otherwise they'd change
|
||||||
|
// golden files for every test case and so not be any use!
|
||||||
|
setupTLSRootsAndLeaf(t, snap)
|
||||||
|
|
||||||
|
g := newResourceGenerator(testutil.Logger(t), nil, nil, false)
|
||||||
|
g.ProxyFeatures = sf
|
||||||
|
|
||||||
|
res, err := g.allResourcesFromSnapshot(snap)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
indexedResources := indexResources(g.Logger, res)
|
||||||
|
newResourceMap, err := serverlessplugin.MutateIndexedResources(indexedResources, xdscommon.MakePluginConfiguration(snap))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
entities := []struct {
|
||||||
|
name string
|
||||||
|
key string
|
||||||
|
sorter func([]proto.Message) func(int, int) bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "clusters",
|
||||||
|
key: xdscommon.ClusterType,
|
||||||
|
sorter: func(msgs []proto.Message) func(int, int) bool {
|
||||||
|
return func(i, j int) bool {
|
||||||
|
return msgs[i].(*envoy_cluster_v3.Cluster).Name < msgs[j].(*envoy_cluster_v3.Cluster).Name
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "listeners",
|
||||||
|
key: xdscommon.ListenerType,
|
||||||
|
sorter: func(msgs []proto.Message) func(int, int) bool {
|
||||||
|
return func(i, j int) bool {
|
||||||
|
return msgs[i].(*envoy_listener_v3.Listener).Name < msgs[j].(*envoy_listener_v3.Listener).Name
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, entity := range entities {
|
||||||
|
var msgs []proto.Message
|
||||||
|
for _, e := range newResourceMap.Index[entity.key] {
|
||||||
|
msgs = append(msgs, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(msgs, entity.sorter(msgs))
|
||||||
|
r, err := createResponse(entity.key, "00000001", "00000001", msgs)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
t.Run(entity.name, func(t *testing.T) {
|
||||||
|
gotJSON := protoToJSON(t, r)
|
||||||
|
|
||||||
|
require.JSONEq(t, goldenEnvoy(t,
|
||||||
|
filepath.Join("serverless_plugin", entity.name, tt.name),
|
||||||
|
envoyVersion, latestEnvoyVersion, gotJSON), gotJSON)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
59
agent/xds/serverlessplugin/copied.go
Normal file
59
agent/xds/serverlessplugin/copied.go
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
package serverlessplugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
|
||||||
|
envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
|
||||||
|
envoy_http_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
|
||||||
|
envoy_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/ptypes"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This is copied from xds and not put into the shared package because I'm not
|
||||||
|
// convinced it should be shared.
|
||||||
|
|
||||||
|
func makeUpstreamTLSTransportSocket(tlsContext *envoy_tls_v3.UpstreamTlsContext) (*envoy_core_v3.TransportSocket, error) {
|
||||||
|
if tlsContext == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return makeTransportSocket("tls", tlsContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeTransportSocket(name string, config proto.Message) (*envoy_core_v3.TransportSocket, error) {
|
||||||
|
any, err := ptypes.MarshalAny(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &envoy_core_v3.TransportSocket{
|
||||||
|
Name: name,
|
||||||
|
ConfigType: &envoy_core_v3.TransportSocket_TypedConfig{
|
||||||
|
TypedConfig: any,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeEnvoyHTTPFilter(name string, cfg proto.Message) (*envoy_http_v3.HttpFilter, error) {
|
||||||
|
any, err := ptypes.MarshalAny(cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &envoy_http_v3.HttpFilter{
|
||||||
|
Name: name,
|
||||||
|
ConfigType: &envoy_http_v3.HttpFilter_TypedConfig{TypedConfig: any},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeFilter(name string, cfg proto.Message) (*envoy_listener_v3.Filter, error) {
|
||||||
|
any, err := ptypes.MarshalAny(cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &envoy_listener_v3.Filter{
|
||||||
|
Name: name,
|
||||||
|
ConfigType: &envoy_listener_v3.Filter_TypedConfig{TypedConfig: any},
|
||||||
|
}, nil
|
||||||
|
}
|
170
agent/xds/serverlessplugin/lambda_patcher.go
Normal file
170
agent/xds/serverlessplugin/lambda_patcher.go
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
package serverlessplugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
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_endpoint_v3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3"
|
||||||
|
envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
|
||||||
|
envoy_lambda_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/aws_lambda/v3"
|
||||||
|
envoy_http_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
|
||||||
|
envoy_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
|
||||||
|
envoy_resource_v3 "github.com/envoyproxy/go-control-plane/pkg/resource/v3"
|
||||||
|
pstruct "github.com/golang/protobuf/ptypes/struct"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/agent/xds/xdscommon"
|
||||||
|
"github.com/hashicorp/consul/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
lambdaPrefix string = "serverless.consul.hashicorp.com/v1alpha1"
|
||||||
|
lambdaEnabledTag string = lambdaPrefix + "/lambda/enabled"
|
||||||
|
lambdaArnTag string = lambdaPrefix + "/lambda/arn"
|
||||||
|
lambdaPayloadPassthroughTag string = lambdaPrefix + "/lambda/payload-passhthrough"
|
||||||
|
lambdaRegionTag string = lambdaPrefix + "/lambda/region"
|
||||||
|
lambdaInvocationMode string = lambdaPrefix + "/lambda/invocation-mode"
|
||||||
|
)
|
||||||
|
|
||||||
|
type lambdaPatcher struct {
|
||||||
|
arn string
|
||||||
|
payloadPassthrough bool
|
||||||
|
region string
|
||||||
|
kind api.ServiceKind
|
||||||
|
invocationMode envoy_lambda_v3.Config_InvocationMode
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ patcher = (*lambdaPatcher)(nil)
|
||||||
|
|
||||||
|
func makeLambdaPatcher(serviceConfig xdscommon.ServiceConfig) (patcher, bool) {
|
||||||
|
var patcher lambdaPatcher
|
||||||
|
if !isStringTrue(serviceConfig.Meta[lambdaEnabledTag]) {
|
||||||
|
return patcher, true
|
||||||
|
}
|
||||||
|
|
||||||
|
arn := serviceConfig.Meta[lambdaArnTag]
|
||||||
|
if arn == "" {
|
||||||
|
return patcher, false
|
||||||
|
}
|
||||||
|
|
||||||
|
region := serviceConfig.Meta[lambdaRegionTag]
|
||||||
|
if region == "" {
|
||||||
|
return patcher, false
|
||||||
|
}
|
||||||
|
|
||||||
|
payloadPassthrough := isStringTrue(serviceConfig.Meta[lambdaPayloadPassthroughTag])
|
||||||
|
|
||||||
|
invocationModeStr := serviceConfig.Meta[lambdaInvocationMode]
|
||||||
|
invocationMode := envoy_lambda_v3.Config_SYNCHRONOUS
|
||||||
|
if invocationModeStr == "asynchronous" {
|
||||||
|
invocationMode = envoy_lambda_v3.Config_ASYNCHRONOUS
|
||||||
|
}
|
||||||
|
|
||||||
|
return lambdaPatcher{
|
||||||
|
arn: arn,
|
||||||
|
payloadPassthrough: payloadPassthrough,
|
||||||
|
region: region,
|
||||||
|
kind: serviceConfig.Kind,
|
||||||
|
invocationMode: invocationMode,
|
||||||
|
}, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isStringTrue(v string) bool {
|
||||||
|
return v == "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p lambdaPatcher) CanPatch(kind api.ServiceKind) bool {
|
||||||
|
return kind == p.kind
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p lambdaPatcher) PatchCluster(c *envoy_cluster_v3.Cluster) (*envoy_cluster_v3.Cluster, bool, error) {
|
||||||
|
transportSocket, err := makeUpstreamTLSTransportSocket(&envoy_tls_v3.UpstreamTlsContext{
|
||||||
|
Sni: "*.amazonaws.com",
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return c, false, fmt.Errorf("failed to make transport socket: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cluster := &envoy_cluster_v3.Cluster{
|
||||||
|
Name: c.Name,
|
||||||
|
ConnectTimeout: c.ConnectTimeout,
|
||||||
|
ClusterDiscoveryType: &envoy_cluster_v3.Cluster_Type{Type: envoy_cluster_v3.Cluster_LOGICAL_DNS},
|
||||||
|
DnsLookupFamily: envoy_cluster_v3.Cluster_V4_ONLY,
|
||||||
|
LbPolicy: envoy_cluster_v3.Cluster_ROUND_ROBIN,
|
||||||
|
Metadata: &envoy_core_v3.Metadata{
|
||||||
|
FilterMetadata: map[string]*pstruct.Struct{
|
||||||
|
"com.amazonaws.lambda": {
|
||||||
|
Fields: map[string]*pstruct.Value{
|
||||||
|
"egress_gateway": {Kind: &pstruct.Value_BoolValue{BoolValue: true}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
LoadAssignment: &envoy_endpoint_v3.ClusterLoadAssignment{
|
||||||
|
ClusterName: c.Name,
|
||||||
|
Endpoints: []*envoy_endpoint_v3.LocalityLbEndpoints{
|
||||||
|
{
|
||||||
|
LbEndpoints: []*envoy_endpoint_v3.LbEndpoint{
|
||||||
|
{
|
||||||
|
HostIdentifier: &envoy_endpoint_v3.LbEndpoint_Endpoint{
|
||||||
|
Endpoint: &envoy_endpoint_v3.Endpoint{
|
||||||
|
Address: &envoy_core_v3.Address{
|
||||||
|
Address: &envoy_core_v3.Address_SocketAddress{
|
||||||
|
SocketAddress: &envoy_core_v3.SocketAddress{
|
||||||
|
Address: fmt.Sprintf("lambda.%s.amazonaws.com", p.region),
|
||||||
|
PortSpecifier: &envoy_core_v3.SocketAddress_PortValue{
|
||||||
|
PortValue: 443,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TransportSocket: transportSocket,
|
||||||
|
}
|
||||||
|
return cluster, true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p lambdaPatcher) PatchFilter(filter *envoy_listener_v3.Filter) (*envoy_listener_v3.Filter, bool, error) {
|
||||||
|
if filter.Name != "envoy.filters.network.http_connection_manager" {
|
||||||
|
return filter, false, nil
|
||||||
|
}
|
||||||
|
if typedConfig := filter.GetTypedConfig(); typedConfig == nil {
|
||||||
|
return filter, false, errors.New("error getting typed config for http filter")
|
||||||
|
}
|
||||||
|
|
||||||
|
config := envoy_resource_v3.GetHTTPConnectionManager(filter)
|
||||||
|
if config == nil {
|
||||||
|
return filter, false, errors.New("error unmarshalling filter")
|
||||||
|
}
|
||||||
|
httpFilter, err := makeEnvoyHTTPFilter(
|
||||||
|
"envoy.filters.http.aws_lambda",
|
||||||
|
&envoy_lambda_v3.Config{
|
||||||
|
Arn: p.arn,
|
||||||
|
PayloadPassthrough: p.payloadPassthrough,
|
||||||
|
InvocationMode: p.invocationMode,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return filter, false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
config.HttpFilters = []*envoy_http_v3.HttpFilter{
|
||||||
|
httpFilter,
|
||||||
|
{Name: "envoy.filters.http.router"},
|
||||||
|
}
|
||||||
|
config.StripMatchingHostPort = true
|
||||||
|
newFilter, err := makeFilter("envoy.filters.network.http_connection_manager", config)
|
||||||
|
if err != nil {
|
||||||
|
return filter, false, errors.New("error making new filter")
|
||||||
|
}
|
||||||
|
|
||||||
|
return newFilter, true, nil
|
||||||
|
}
|
83
agent/xds/serverlessplugin/lambda_patcher_test.go
Normal file
83
agent/xds/serverlessplugin/lambda_patcher_test.go
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
package serverlessplugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/agent/xds/xdscommon"
|
||||||
|
"github.com/hashicorp/consul/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMakeLambdaPatcher(t *testing.T) {
|
||||||
|
kind := api.ServiceKindTerminatingGateway
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
enabled bool
|
||||||
|
arn string
|
||||||
|
payloadPassthrough bool
|
||||||
|
region string
|
||||||
|
expected lambdaPatcher
|
||||||
|
ok bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "no meta",
|
||||||
|
ok: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "lambda disabled",
|
||||||
|
enabled: false,
|
||||||
|
ok: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "missing arn",
|
||||||
|
enabled: true,
|
||||||
|
region: "blah",
|
||||||
|
ok: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "missing region",
|
||||||
|
enabled: true,
|
||||||
|
region: "arn",
|
||||||
|
ok: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "including payload passthrough",
|
||||||
|
enabled: true,
|
||||||
|
arn: "arn",
|
||||||
|
region: "blah",
|
||||||
|
payloadPassthrough: true,
|
||||||
|
expected: lambdaPatcher{
|
||||||
|
arn: "arn",
|
||||||
|
payloadPassthrough: true,
|
||||||
|
region: "blah",
|
||||||
|
kind: kind,
|
||||||
|
},
|
||||||
|
ok: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
config := xdscommon.ServiceConfig{
|
||||||
|
Kind: kind,
|
||||||
|
Meta: map[string]string{
|
||||||
|
lambdaEnabledTag: strconv.FormatBool(tc.enabled),
|
||||||
|
lambdaArnTag: tc.arn,
|
||||||
|
lambdaRegionTag: tc.region,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if tc.payloadPassthrough {
|
||||||
|
config.Meta[lambdaPayloadPassthroughTag] = strconv.FormatBool(tc.payloadPassthrough)
|
||||||
|
}
|
||||||
|
|
||||||
|
patcher, ok := makeLambdaPatcher(config)
|
||||||
|
|
||||||
|
require.Equal(t, tc.ok, ok)
|
||||||
|
|
||||||
|
require.Equal(t, tc.expected, patcher)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
81
agent/xds/serverlessplugin/patcher.go
Normal file
81
agent/xds/serverlessplugin/patcher.go
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
package serverlessplugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
envoy_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
|
||||||
|
envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/agent/xds/xdscommon"
|
||||||
|
"github.com/hashicorp/consul/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
// patcher is the interface that each serverless integration must implement. It
|
||||||
|
// is responsible for modifying the xDS structures based on only the state of
|
||||||
|
// the patcher.
|
||||||
|
type patcher interface {
|
||||||
|
// CanPatch determines if the patcher can mutate resources for the given api.ServiceKind
|
||||||
|
CanPatch(api.ServiceKind) bool
|
||||||
|
|
||||||
|
// PatchCluster patches a cluster to include the custom Envoy configuration
|
||||||
|
// required to integrate with the serverless integration.
|
||||||
|
PatchCluster(*envoy_cluster_v3.Cluster) (*envoy_cluster_v3.Cluster, bool, error)
|
||||||
|
|
||||||
|
// PatchFilter patches an Envoy filter to include the custom Envoy
|
||||||
|
// configuration required to integrate with the serverless integration.
|
||||||
|
PatchFilter(*envoy_listener_v3.Filter) (*envoy_listener_v3.Filter, bool, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type patchers map[api.CompoundServiceName]patcher
|
||||||
|
|
||||||
|
func getPatcher(patchers patchers, kind api.ServiceKind, name api.CompoundServiceName) patcher {
|
||||||
|
patcher, ok := patchers[name]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !patcher.CanPatch(kind) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return patcher
|
||||||
|
}
|
||||||
|
|
||||||
|
// getPatcherBySNI gets the patcher for the associated SNI.
|
||||||
|
func getPatcherBySNI(config xdscommon.PluginConfiguration, kind api.ServiceKind, sni string) patcher {
|
||||||
|
serviceName, ok := config.SNIToServiceName[sni]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceConfig, ok := config.ServiceConfigs[serviceName]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
p := makePatcher(serviceConfig)
|
||||||
|
if p == nil || !p.CanPatch(kind) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func makePatcher(serviceConfig xdscommon.ServiceConfig) patcher {
|
||||||
|
for _, constructor := range patchConstructors {
|
||||||
|
patcher, ok := constructor(serviceConfig)
|
||||||
|
if ok {
|
||||||
|
return patcher
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// patchConstructor is used to construct patchers based on
|
||||||
|
// xdscommon.ServiceConfig. This function contains all of the logic around
|
||||||
|
// turning Meta data into the patcher.
|
||||||
|
type patchConstructor func(xdscommon.ServiceConfig) (patcher, bool)
|
||||||
|
|
||||||
|
// patchConstructors contains all patchers that getPatchers tries to create.
|
||||||
|
var patchConstructors = []patchConstructor{makeLambdaPatcher}
|
100
agent/xds/serverlessplugin/patcher_test.go
Normal file
100
agent/xds/serverlessplugin/patcher_test.go
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
package serverlessplugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/agent/xds/xdscommon"
|
||||||
|
"github.com/hashicorp/consul/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetPatcherBySNI(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
sni string
|
||||||
|
kind api.ServiceKind
|
||||||
|
expected patcher
|
||||||
|
config *xdscommon.PluginConfiguration
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "no sni match",
|
||||||
|
sni: "not-matching",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no patcher",
|
||||||
|
config: &xdscommon.PluginConfiguration{},
|
||||||
|
sni: "lambda-sni",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no kind match",
|
||||||
|
kind: api.ServiceKindIngressGateway,
|
||||||
|
sni: "lambda-sni",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "full match",
|
||||||
|
sni: "lambda-sni",
|
||||||
|
kind: api.ServiceKindTerminatingGateway,
|
||||||
|
expected: lambdaPatcher{
|
||||||
|
arn: "arn",
|
||||||
|
region: "region",
|
||||||
|
payloadPassthrough: false,
|
||||||
|
kind: api.ServiceKindTerminatingGateway,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
config := sampleConfig()
|
||||||
|
if tc.config != nil {
|
||||||
|
config = *tc.config
|
||||||
|
}
|
||||||
|
patcher := getPatcherBySNI(config, tc.kind, tc.sni)
|
||||||
|
|
||||||
|
if tc.expected == nil {
|
||||||
|
require.Empty(t, patcher)
|
||||||
|
} else {
|
||||||
|
require.Equal(t, tc.expected, patcher)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
lambdaService = api.CompoundServiceName{Name: "lambda"}
|
||||||
|
disabledLambdaService = api.CompoundServiceName{Name: "disabled-lambda"}
|
||||||
|
invalidLambdaService = api.CompoundServiceName{Name: "invalid-lambda"}
|
||||||
|
)
|
||||||
|
|
||||||
|
func sampleConfig() xdscommon.PluginConfiguration {
|
||||||
|
return xdscommon.PluginConfiguration{
|
||||||
|
ServiceConfigs: map[api.CompoundServiceName]xdscommon.ServiceConfig{
|
||||||
|
lambdaService: {
|
||||||
|
Kind: api.ServiceKindTerminatingGateway,
|
||||||
|
Meta: map[string]string{
|
||||||
|
lambdaEnabledTag: "true",
|
||||||
|
lambdaArnTag: "arn",
|
||||||
|
lambdaRegionTag: "region",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
disabledLambdaService: {
|
||||||
|
Kind: api.ServiceKindTerminatingGateway,
|
||||||
|
Meta: map[string]string{
|
||||||
|
lambdaEnabledTag: "false",
|
||||||
|
lambdaArnTag: "arn",
|
||||||
|
lambdaRegionTag: "region",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
invalidLambdaService: {
|
||||||
|
Kind: api.ServiceKindTerminatingGateway,
|
||||||
|
Meta: map[string]string{
|
||||||
|
lambdaEnabledTag: "true",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
SNIToServiceName: map[string]api.CompoundServiceName{
|
||||||
|
"lambda-sni": lambdaService,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,122 @@
|
||||||
package serverlessplugin
|
package serverlessplugin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
envoy_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
|
||||||
|
envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"github.com/hashicorp/go-multierror"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/agent/xds/xdscommon"
|
"github.com/hashicorp/consul/agent/xds/xdscommon"
|
||||||
|
"github.com/hashicorp/consul/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// MutateIndexedResources updates indexed xDS structures to include patches for
|
||||||
|
// serverless integrations. It is responsible for constructing all of the
|
||||||
|
// patchers and forwarding xDS structs onto the appropriate patcher. If any
|
||||||
|
// portion of this function fails, it will record the error and continue. The
|
||||||
|
// behavior is appropriate since the unpatched xDS structures this receives are
|
||||||
|
// typically invalid.
|
||||||
func MutateIndexedResources(resources *xdscommon.IndexedResources, config xdscommon.PluginConfiguration) (*xdscommon.IndexedResources, error) {
|
func MutateIndexedResources(resources *xdscommon.IndexedResources, config xdscommon.PluginConfiguration) (*xdscommon.IndexedResources, error) {
|
||||||
return resources, nil
|
var resultErr error
|
||||||
|
|
||||||
|
// The serverless plugin only supports terminating gateays for now, but will
|
||||||
|
// likely add connect proxies soon.
|
||||||
|
if config.Kind != api.ServiceKindTerminatingGateway {
|
||||||
|
return resources, resultErr
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, indexType := range []string{
|
||||||
|
xdscommon.ClusterType,
|
||||||
|
xdscommon.ListenerType,
|
||||||
|
} {
|
||||||
|
for nameOrSNI, msg := range resources.Index[indexType] {
|
||||||
|
switch resource := msg.(type) {
|
||||||
|
case *envoy_cluster_v3.Cluster:
|
||||||
|
patcher := getPatcherBySNI(config, config.Kind, nameOrSNI)
|
||||||
|
if patcher == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
newCluster, patched, err := patcher.PatchCluster(resource)
|
||||||
|
if err != nil {
|
||||||
|
resultErr = multierror.Append(resultErr, fmt.Errorf("error patching cluster: %w", err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if patched {
|
||||||
|
resources.Index[xdscommon.ClusterType][nameOrSNI] = newCluster
|
||||||
|
}
|
||||||
|
|
||||||
|
case *envoy_listener_v3.Listener:
|
||||||
|
newListener, patched, err := patchTerminatingGatewayListener(resource, config)
|
||||||
|
if err != nil {
|
||||||
|
resultErr = multierror.Append(resultErr, fmt.Errorf("error patching listener: %w", err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if patched {
|
||||||
|
resources.Index[xdscommon.ListenerType][nameOrSNI] = newListener
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
resultErr = multierror.Append(resultErr, fmt.Errorf("unsupported type was skipped: %T", resource))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resources, resultErr
|
||||||
|
}
|
||||||
|
|
||||||
|
func patchTerminatingGatewayListener(l *envoy_listener_v3.Listener, config xdscommon.PluginConfiguration) (proto.Message, bool, error) {
|
||||||
|
var resultErr error
|
||||||
|
patched := false
|
||||||
|
for _, filterChain := range l.FilterChains {
|
||||||
|
sni := getSNI(filterChain)
|
||||||
|
|
||||||
|
if sni == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
patcher := getPatcherBySNI(config, config.Kind, sni)
|
||||||
|
|
||||||
|
if patcher == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var filters []*envoy_listener_v3.Filter
|
||||||
|
|
||||||
|
for _, filter := range filterChain.Filters {
|
||||||
|
newFilter, ok, err := patcher.PatchFilter(filter)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
resultErr = multierror.Append(resultErr, fmt.Errorf("error patching listener filter: %w", err))
|
||||||
|
filters = append(filters, filter)
|
||||||
|
}
|
||||||
|
if ok {
|
||||||
|
filters = append(filters, newFilter)
|
||||||
|
patched = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filterChain.Filters = filters
|
||||||
|
}
|
||||||
|
|
||||||
|
return l, patched, resultErr
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSNI(chain *envoy_listener_v3.FilterChain) string {
|
||||||
|
var sni string
|
||||||
|
|
||||||
|
if chain == nil {
|
||||||
|
return sni
|
||||||
|
}
|
||||||
|
|
||||||
|
if chain.FilterChainMatch == nil {
|
||||||
|
return sni
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(chain.FilterChainMatch.ServerNames) == 0 {
|
||||||
|
return sni
|
||||||
|
}
|
||||||
|
|
||||||
|
return chain.FilterChainMatch.ServerNames[0]
|
||||||
}
|
}
|
||||||
|
|
169
agent/xds/testdata/serverless_plugin/clusters/lambda-terminating-gateway.envoy-1-20-x.golden
vendored
Normal file
169
agent/xds/testdata/serverless_plugin/clusters/lambda-terminating-gateway.envoy-1-20-x.golden
vendored
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
{
|
||||||
|
"versionInfo": "00000001",
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||||
|
"name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"type": "LOGICAL_DNS",
|
||||||
|
"connectTimeout": "5s",
|
||||||
|
"loadAssignment": {
|
||||||
|
"clusterName": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"endpoints": [
|
||||||
|
{
|
||||||
|
"lbEndpoints": [
|
||||||
|
{
|
||||||
|
"endpoint": {
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "api.altdomain",
|
||||||
|
"portValue": 8081
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"healthStatus": "HEALTHY",
|
||||||
|
"loadBalancingWeight": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dnsRefreshRate": "10s",
|
||||||
|
"dnsLookupFamily": "V4_ONLY",
|
||||||
|
"outlierDetection": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"transportSocket": {
|
||||||
|
"name": "tls",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
|
||||||
|
"commonTlsContext": {
|
||||||
|
"tlsParams": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"tlsCertificates": [
|
||||||
|
{
|
||||||
|
"certificateChain": {
|
||||||
|
"filename": "api.cert.pem"
|
||||||
|
},
|
||||||
|
"privateKey": {
|
||||||
|
"filename": "api.key.pem"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validationContext": {
|
||||||
|
"trustedCa": {
|
||||||
|
"filename": "ca.cert.pem"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||||
|
"name": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"type": "LOGICAL_DNS",
|
||||||
|
"connectTimeout": "5s",
|
||||||
|
"loadAssignment": {
|
||||||
|
"clusterName": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"endpoints": [
|
||||||
|
{
|
||||||
|
"lbEndpoints": [
|
||||||
|
{
|
||||||
|
"endpoint": {
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "cache.mydomain",
|
||||||
|
"portValue": 8081
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"healthStatus": "HEALTHY",
|
||||||
|
"loadBalancingWeight": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dnsRefreshRate": "10s",
|
||||||
|
"dnsLookupFamily": "V4_ONLY",
|
||||||
|
"outlierDetection": {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||||
|
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"type": "LOGICAL_DNS",
|
||||||
|
"connectTimeout": "5s",
|
||||||
|
"loadAssignment": {
|
||||||
|
"clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"endpoints": [
|
||||||
|
{
|
||||||
|
"lbEndpoints": [
|
||||||
|
{
|
||||||
|
"endpoint": {
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "db.mydomain",
|
||||||
|
"portValue": 8081
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"healthStatus": "UNHEALTHY",
|
||||||
|
"loadBalancingWeight": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dnsRefreshRate": "10s",
|
||||||
|
"dnsLookupFamily": "V4_ONLY",
|
||||||
|
"outlierDetection": {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||||
|
"name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"type": "LOGICAL_DNS",
|
||||||
|
"connectTimeout": "5s",
|
||||||
|
"loadAssignment": {
|
||||||
|
"clusterName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"endpoints": [
|
||||||
|
{
|
||||||
|
"lbEndpoints": [
|
||||||
|
{
|
||||||
|
"endpoint": {
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "lambda.us-east-1.amazonaws.com",
|
||||||
|
"portValue": 443
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dnsLookupFamily": "V4_ONLY",
|
||||||
|
"transportSocket": {
|
||||||
|
"name": "tls",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
|
||||||
|
"sni": "*.amazonaws.com"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"filterMetadata": {
|
||||||
|
"com.amazonaws.lambda": {
|
||||||
|
"egress_gateway": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||||
|
"nonce": "00000001"
|
||||||
|
}
|
272
agent/xds/testdata/serverless_plugin/listeners/lambda-terminating-gateway.envoy-1-20-x.golden
vendored
Normal file
272
agent/xds/testdata/serverless_plugin/listeners/lambda-terminating-gateway.envoy-1-20-x.golden
vendored
Normal file
|
@ -0,0 +1,272 @@
|
||||||
|
{
|
||||||
|
"versionInfo": "00000001",
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||||
|
"name": "default:1.2.3.4:8443",
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "1.2.3.4",
|
||||||
|
"portValue": 8443
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"filterChains": [
|
||||||
|
{
|
||||||
|
"filterChainMatch": {
|
||||||
|
"serverNames": [
|
||||||
|
"api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.network.rbac",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC",
|
||||||
|
"rules": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"statPrefix": "connect_authz"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.network.tcp_proxy",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy",
|
||||||
|
"statPrefix": "upstream.api.default.default.dc1",
|
||||||
|
"cluster": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transportSocket": {
|
||||||
|
"name": "tls",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext",
|
||||||
|
"commonTlsContext": {
|
||||||
|
"tlsParams": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"tlsCertificates": [
|
||||||
|
{
|
||||||
|
"certificateChain": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICnTCCAkKgAwIBAgIRAJrvEdaRAkSltrotd/l/j2cwCgYIKoZIzj0EAwIwgbgx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw\nFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjE/MD0GA1UEAxM2Q29uc3VsIEFnZW50IENB\nIDk2NjM4NzM1MDkzNTU5NTIwNDk3MTQwOTU3MDY1MTc0OTg3NDMxMB4XDTIwMDQx\nNDIyMzE1MloXDTIxMDQxNDIyMzE1MlowHDEaMBgGA1UEAxMRc2VydmVyLmRjMS5j\nb25zdWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ4v0FoIYI0OWmxE2MR6w5l\n0pWGhc02RpsOPj/6RS1fmXMMu7JzPzwCmkGcR16RlwwhNFKCZsWpvAjVRHf/pTp+\no4HHMIHEMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB\nBQUHAwIwDAYDVR0TAQH/BAIwADApBgNVHQ4EIgQgk7kABFitAy3PluyNtmzYiC7H\njSN8W/K/OXNJQAQAscMwKwYDVR0jBCQwIoAgNKbPPepvRHXSAPTc+a/BXBzFX1qJ\ny+Zi7qtjlFX7qtUwLQYDVR0RBCYwJIIRc2VydmVyLmRjMS5jb25zdWyCCWxvY2Fs\naG9zdIcEfwAAATAKBggqhkjOPQQDAgNJADBGAiEAhP4HmN5BWysWTbQWClXaWUah\nLpBGFrvc/2cCQuyEZKsCIQD6JyYCYMArtWwZ4G499zktxrFlqfX14bqyONrxtA5I\nDw==\n-----END CERTIFICATE-----\n"
|
||||||
|
},
|
||||||
|
"privateKey": {
|
||||||
|
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIE3KbKXHdsa0vvC1fysQaGdoJRgjRALIolI4XJanie+coAoGCCqGSM49\nAwEHoUQDQgAEOL9BaCGCNDlpsRNjEesOZdKVhoXNNkabDj4/+kUtX5lzDLuycz88\nAppBnEdekZcMITRSgmbFqbwI1UR3/6U6fg==\n-----END EC PRIVATE KEY-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validationContext": {
|
||||||
|
"trustedCa": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requireClientCertificate": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filterChainMatch": {
|
||||||
|
"serverNames": [
|
||||||
|
"cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.network.rbac",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC",
|
||||||
|
"rules": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"statPrefix": "connect_authz"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.network.tcp_proxy",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy",
|
||||||
|
"statPrefix": "upstream.cache.default.default.dc1",
|
||||||
|
"cluster": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transportSocket": {
|
||||||
|
"name": "tls",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext",
|
||||||
|
"commonTlsContext": {
|
||||||
|
"tlsParams": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"tlsCertificates": [
|
||||||
|
{
|
||||||
|
"certificateChain": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICmjCCAkGgAwIBAgIQe1ZmC0rzRwer6jaH1YIUIjAKBggqhkjOPQQDAjCBuDEL\nMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2Nv\nMRowGAYDVQQJExExMDEgU2Vjb25kIFN0cmVldDEOMAwGA1UEERMFOTQxMDUxFzAV\nBgNVBAoTDkhhc2hpQ29ycCBJbmMuMT8wPQYDVQQDEzZDb25zdWwgQWdlbnQgQ0Eg\nODE5ODAwNjg0MDM0MTM3ODkyNDYxNTA1MDk0NDU3OTU1MTQxNjEwHhcNMjAwNjE5\nMTU1MjAzWhcNMjEwNjE5MTU1MjAzWjAcMRowGAYDVQQDExFzZXJ2ZXIuZGMxLmNv\nbnN1bDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH2aWaaa3fpQLBayheHiKlrH\n+z53m0frfGknKjOhOPVYDVHV8x0OE01negswVQbKHAtxPf1M8Zy+WbI9rK7Ua1mj\ngccwgcQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF\nBQcDAjAMBgNVHRMBAf8EAjAAMCkGA1UdDgQiBCDf9CPBSUwwZvpeW73oJLTmgQE2\ntW1NKpL5t1uq9WFcqDArBgNVHSMEJDAigCCPPd/NxgZB0tq2M8pdVpPj3Cr79iTv\ni4/T1ysodfMb7zAtBgNVHREEJjAkghFzZXJ2ZXIuZGMxLmNvbnN1bIIJbG9jYWxo\nb3N0hwR/AAABMAoGCCqGSM49BAMCA0cAMEQCIFCjFZAoXq0s2ied2eIBv0i1KoW5\nIhCylnKFt6iHkyDeAiBBCByTcjHRgEQmqyPojQKoO584EFiczTub9aWdnf9tEw==\n-----END CERTIFICATE-----\n"
|
||||||
|
},
|
||||||
|
"privateKey": {
|
||||||
|
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEINsen3S8xzxMrKcRZIvxXzhKDn43Tw9ttqWEFU9TqS5hoAoGCCqGSM49\nAwEHoUQDQgAEfZpZpprd+lAsFrKF4eIqWsf7PnebR+t8aScqM6E49VgNUdXzHQ4T\nTWd6CzBVBsocC3E9/UzxnL5Zsj2srtRrWQ==\n-----END EC PRIVATE KEY-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validationContext": {
|
||||||
|
"trustedCa": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requireClientCertificate": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filterChainMatch": {
|
||||||
|
"serverNames": [
|
||||||
|
"db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.network.rbac",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC",
|
||||||
|
"rules": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"statPrefix": "connect_authz"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.network.tcp_proxy",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy",
|
||||||
|
"statPrefix": "upstream.db.default.default.dc1",
|
||||||
|
"cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transportSocket": {
|
||||||
|
"name": "tls",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext",
|
||||||
|
"commonTlsContext": {
|
||||||
|
"tlsParams": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"tlsCertificates": [
|
||||||
|
{
|
||||||
|
"certificateChain": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICnTCCAkOgAwIBAgIRAKF+qDJbaOULNL1TIatrsBowCgYIKoZIzj0EAwIwgbkx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw\nFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjFAMD4GA1UEAxM3Q29uc3VsIEFnZW50IENB\nIDE4Nzg3MDAwNjUzMDcxOTYzNTk1ODkwNTE1ODY1NjEzMDA2MTU0NDAeFw0yMDA2\nMTkxNTMxMzRaFw0yMTA2MTkxNTMxMzRaMBwxGjAYBgNVBAMTEXNlcnZlci5kYzEu\nY29uc3VsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdQ8Igci5f7ZvvCVsxXt9\ntLfvczD+60XHg0OC0+Aka7ZjQfbEjQwZbz/82EwPoS7Dqo3LTK4IuelOimoNNxuk\nkaOBxzCBxDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG\nAQUFBwMCMAwGA1UdEwEB/wQCMAAwKQYDVR0OBCIEILzTLkfJcdWQnTMKUcai/YJq\n0RqH1pjCqtY7SOU4gGOTMCsGA1UdIwQkMCKAIMa2vNcTEC5AGfHIYARJ/4sodX0o\nLzCj3lpw7BcEzPTcMC0GA1UdEQQmMCSCEXNlcnZlci5kYzEuY29uc3Vsgglsb2Nh\nbGhvc3SHBH8AAAEwCgYIKoZIzj0EAwIDSAAwRQIgBZ/Z4GSLEc98WvT/qjTVCNTG\n1WNaAaesVbkRx+J0yl8CIQDAVoqY9ByA5vKHjnQrxWlc/JUtJz8wudg7e/OCRriP\nSg==\n-----END CERTIFICATE-----\n"
|
||||||
|
},
|
||||||
|
"privateKey": {
|
||||||
|
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIN1v14FaNxgY4MgjDOOWthen8dgwB0lNMs9/j2TfrnxzoAoGCCqGSM49\nAwEHoUQDQgAEdQ8Igci5f7ZvvCVsxXt9tLfvczD+60XHg0OC0+Aka7ZjQfbEjQwZ\nbz/82EwPoS7Dqo3LTK4IuelOimoNNxukkQ==\n-----END EC PRIVATE KEY-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validationContext": {
|
||||||
|
"trustedCa": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requireClientCertificate": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filterChainMatch": {
|
||||||
|
"serverNames": [
|
||||||
|
"web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.network.http_connection_manager",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager",
|
||||||
|
"statPrefix": "upstream.web.default.default.dc1",
|
||||||
|
"rds": {
|
||||||
|
"configSource": {
|
||||||
|
"ads": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"resourceApiVersion": "V3"
|
||||||
|
},
|
||||||
|
"routeConfigName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
},
|
||||||
|
"httpFilters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.http.aws_lambda",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.aws_lambda.v3.Config",
|
||||||
|
"arn": "lambda-arn"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.http.router"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tracing": {
|
||||||
|
"randomSampling": {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"stripMatchingHostPort": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transportSocket": {
|
||||||
|
"name": "tls",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext",
|
||||||
|
"commonTlsContext": {
|
||||||
|
"tlsParams": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"tlsCertificates": [
|
||||||
|
{
|
||||||
|
"certificateChain": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||||
|
},
|
||||||
|
"privateKey": {
|
||||||
|
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validationContext": {
|
||||||
|
"trustedCa": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requireClientCertificate": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.network.sni_cluster"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.network.tcp_proxy",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy",
|
||||||
|
"statPrefix": "terminating_gateway.default",
|
||||||
|
"cluster": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"listenerFilters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.listener.tls_inspector"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"trafficDirection": "INBOUND"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||||
|
"nonce": "00000001"
|
||||||
|
}
|
|
@ -78,7 +78,8 @@ type PluginConfiguration struct {
|
||||||
// associated service's CompoundServiceName
|
// associated service's CompoundServiceName
|
||||||
EnvoyIDToServiceName map[string]api.CompoundServiceName
|
EnvoyIDToServiceName map[string]api.CompoundServiceName
|
||||||
|
|
||||||
// Kind is mode the local Envoy proxy is running in
|
// Kind is mode the local Envoy proxy is running in. For now, only
|
||||||
|
// terminating gateways are supported.
|
||||||
Kind api.ServiceKind
|
Kind api.ServiceKind
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMakePluginConfiguration_TerminatingGateway(t *testing.T) {
|
func TestMakePluginConfiguration_TerminatingGateway(t *testing.T) {
|
||||||
snap := proxycfg.TestConfigSnapshotTerminatingGatewayWithServiceDefaultsMeta(t)
|
snap := proxycfg.TestConfigSnapshotTerminatingGatewayWithLambdaService(t)
|
||||||
|
|
||||||
webService := api.CompoundServiceName{
|
webService := api.CompoundServiceName{
|
||||||
Name: "web",
|
Name: "web",
|
||||||
|
@ -41,7 +41,12 @@ func TestMakePluginConfiguration_TerminatingGateway(t *testing.T) {
|
||||||
ServiceConfigs: map[api.CompoundServiceName]ServiceConfig{
|
ServiceConfigs: map[api.CompoundServiceName]ServiceConfig{
|
||||||
webService: {
|
webService: {
|
||||||
Kind: api.ServiceKindTerminatingGateway,
|
Kind: api.ServiceKindTerminatingGateway,
|
||||||
Meta: map[string]string{"a": "b"},
|
Meta: map[string]string{
|
||||||
|
"serverless.consul.hashicorp.com/v1alpha1/lambda/enabled": "true",
|
||||||
|
"serverless.consul.hashicorp.com/v1alpha1/lambda/arn": "lambda-arn",
|
||||||
|
"serverless.consul.hashicorp.com/v1alpha1/lambda/payload-passthrough": "true",
|
||||||
|
"serverless.consul.hashicorp.com/v1alpha1/lambda/region": "us-east-1",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
apiService: {
|
apiService: {
|
||||||
Kind: api.ServiceKindTerminatingGateway,
|
Kind: api.ServiceKindTerminatingGateway,
|
||||||
|
|
Loading…
Reference in a new issue