mirror of https://github.com/hashicorp/consul
Merge branch 'main' of https://github.com/hashicorp/consul into ui/enhancement/updateNodeList
commit
23ce82b4ce
73
CHANGELOG.md
73
CHANGELOG.md
|
@ -1,3 +1,76 @@
|
|||
## 1.16.0 (June 26, 2023)
|
||||
|
||||
BREAKING CHANGES:
|
||||
|
||||
* api: The `/v1/health/connect/` and `/v1/health/ingress/` endpoints now immediately return 403 "Permission Denied" errors whenever a token with insufficient `service:read` permissions is provided. Prior to this change, the endpoints returned a success code with an empty result list when a token with insufficient permissions was provided. [[GH-17424](https://github.com/hashicorp/consul/issues/17424)]
|
||||
* peering: Removed deprecated backward-compatibility behavior.
|
||||
Upstream overrides in service-defaults will now only apply to peer upstreams when the `peer` field is provided.
|
||||
Visit the 1.16.x [upgrade instructions](https://developer.hashicorp.com/consul/docs/upgrading/upgrade-specific) for more information. [[GH-16957](https://github.com/hashicorp/consul/issues/16957)]
|
||||
|
||||
SECURITY:
|
||||
|
||||
* Bump Dockerfile base image to `alpine:3.18`. [[GH-17719](https://github.com/hashicorp/consul/issues/17719)]
|
||||
* audit-logging: **(Enterprise only)** limit `v1/operator/audit-hash` endpoint to ACL token with `operator:read` privileges.
|
||||
|
||||
FEATURES:
|
||||
|
||||
* api: (Enterprise only) Add `POST /v1/operator/audit-hash` endpoint to calculate the hash of the data used by the audit log hash function and salt.
|
||||
* cli: (Enterprise only) Add a new `consul operator audit hash` command to retrieve and compare the hash of the data used by the audit log hash function and salt.
|
||||
* cli: Adds new command - `consul services export` - for exporting a service to a peer or partition [[GH-15654](https://github.com/hashicorp/consul/issues/15654)]
|
||||
* connect: **(Consul Enterprise only)** Implement order-by-locality failover.
|
||||
* mesh: Add new permissive mTLS mode that allows sidecar proxies to forward incoming traffic unmodified to the application. This adds `AllowEnablingPermissiveMutualTLS` setting to the mesh config entry and the `MutualTLSMode` setting to proxy-defaults and service-defaults. [[GH-17035](https://github.com/hashicorp/consul/issues/17035)]
|
||||
* mesh: Support configuring JWT authentication in Envoy. [[GH-17452](https://github.com/hashicorp/consul/issues/17452)]
|
||||
* server: **(Enterprise Only)** added server side RPC requests IP based read/write rate-limiter. [[GH-4633](https://github.com/hashicorp/consul/issues/4633)]
|
||||
* server: **(Enterprise Only)** allow automatic license utilization reporting. [[GH-5102](https://github.com/hashicorp/consul/issues/5102)]
|
||||
* server: added server side RPC requests global read/write rate-limiter. [[GH-16292](https://github.com/hashicorp/consul/issues/16292)]
|
||||
* xds: Add `property-override` built-in Envoy extension that directly patches Envoy resources. [[GH-17487](https://github.com/hashicorp/consul/issues/17487)]
|
||||
* xds: Add a built-in Envoy extension that inserts External Authorization (ext_authz) network and HTTP filters. [[GH-17495](https://github.com/hashicorp/consul/issues/17495)]
|
||||
* xds: Add a built-in Envoy extension that inserts Wasm HTTP filters. [[GH-16877](https://github.com/hashicorp/consul/issues/16877)]
|
||||
* xds: Add a built-in Envoy extension that inserts Wasm network filters. [[GH-17505](https://github.com/hashicorp/consul/issues/17505)]
|
||||
|
||||
IMPROVEMENTS:
|
||||
|
||||
* * api: Support filtering for config entries. [[GH-17183](https://github.com/hashicorp/consul/issues/17183)]
|
||||
* * cli: Add `-filter` option to `consul config list` for filtering config entries. [[GH-17183](https://github.com/hashicorp/consul/issues/17183)]
|
||||
* agent: remove agent cache dependency from service mesh leaf certificate management [[GH-17075](https://github.com/hashicorp/consul/issues/17075)]
|
||||
* api: Enable setting query options on agent force-leave endpoint. [[GH-15987](https://github.com/hashicorp/consul/issues/15987)]
|
||||
* audit-logging: **(Enterprise only)** enable error response and request body logging
|
||||
* ca: automatically set up Vault's auto-tidy setting for tidy_expired_issuers when using Vault as a CA provider. [[GH-17138](https://github.com/hashicorp/consul/issues/17138)]
|
||||
* ca: support Vault agent auto-auth config for Vault CA provider using AliCloud authentication. [[GH-16224](https://github.com/hashicorp/consul/issues/16224)]
|
||||
* ca: support Vault agent auto-auth config for Vault CA provider using AppRole authentication. [[GH-16259](https://github.com/hashicorp/consul/issues/16259)]
|
||||
* ca: support Vault agent auto-auth config for Vault CA provider using Azure MSI authentication. [[GH-16298](https://github.com/hashicorp/consul/issues/16298)]
|
||||
* ca: support Vault agent auto-auth config for Vault CA provider using JWT authentication. [[GH-16266](https://github.com/hashicorp/consul/issues/16266)]
|
||||
* ca: support Vault agent auto-auth config for Vault CA provider using Kubernetes authentication. [[GH-16262](https://github.com/hashicorp/consul/issues/16262)]
|
||||
* command: Adds ACL enabled to status output on agent startup. [[GH-17086](https://github.com/hashicorp/consul/issues/17086)]
|
||||
* command: Allow creating ACL Token TTL with greater than 24 hours with the -expires-ttl flag. [[GH-17066](https://github.com/hashicorp/consul/issues/17066)]
|
||||
* connect: **(Enterprise Only)** Add support for specifying "Partition" and "Namespace" in Prepared Queries failover rules.
|
||||
* connect: update supported envoy versions to 1.23.10, 1.24.8, 1.25.7, 1.26.2 [[GH-17546](https://github.com/hashicorp/consul/issues/17546)]
|
||||
* connect: update supported envoy versions to 1.23.8, 1.24.6, 1.25.4, 1.26.0 [[GH-5200](https://github.com/hashicorp/consul/issues/5200)]
|
||||
* fix metric names in /docs/agent/telemetry [[GH-17577](https://github.com/hashicorp/consul/issues/17577)]
|
||||
* gateway: Change status condition reason for invalid certificate on a listener from "Accepted" to "ResolvedRefs". [[GH-17115](https://github.com/hashicorp/consul/issues/17115)]
|
||||
* http: accept query parameters `datacenter`, `ap` (enterprise-only), and `namespace` (enterprise-only). Both short-hand and long-hand forms of these query params are now supported via the HTTP API (dc/datacenter, ap/partition, ns/namespace). [[GH-17525](https://github.com/hashicorp/consul/issues/17525)]
|
||||
* systemd: set service type to notify. [[GH-16845](https://github.com/hashicorp/consul/issues/16845)]
|
||||
* ui: Update alerts to Hds::Alert component [[GH-16412](https://github.com/hashicorp/consul/issues/16412)]
|
||||
* ui: Update to use Hds::Toast component to show notifications [[GH-16519](https://github.com/hashicorp/consul/issues/16519)]
|
||||
* ui: update from <button> and <a> to design-system-components button <Hds::Button> [[GH-16251](https://github.com/hashicorp/consul/issues/16251)]
|
||||
* ui: update typography to styles from hds [[GH-16577](https://github.com/hashicorp/consul/issues/16577)]
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* Fix a race condition where an event is published before the data associated is commited to memdb. [[GH-16871](https://github.com/hashicorp/consul/issues/16871)]
|
||||
* connect: Fix issue where changes to service exports were not reflected in proxies. [[GH-17775](https://github.com/hashicorp/consul/issues/17775)]
|
||||
* gateways: **(Enterprise only)** Fixed a bug in API gateways where gateway configuration objects in non-default partitions did not reconcile properly. [[GH-17581](https://github.com/hashicorp/consul/issues/17581)]
|
||||
* gateways: Fixed a bug in API gateways where binding a route that only targets a service imported from a peer results
|
||||
in the programmed gateway having no routes. [[GH-17609](https://github.com/hashicorp/consul/issues/17609)]
|
||||
* gateways: Fixed a bug where API gateways were not being taken into account in determining xDS rate limits. [[GH-17631](https://github.com/hashicorp/consul/issues/17631)]
|
||||
* namespaces: **(Enterprise only)** fixes a bug where agent health checks stop syncing for all services on a node if the namespace of any service has been removed from the server.
|
||||
* namespaces: **(Enterprise only)** fixes a bug where namespaces are stuck in a deferred deletion state indefinitely under some conditions.
|
||||
Also fixes the Consul query metadata present in the HTTP headers of the namespace read and list endpoints.
|
||||
* peering: Fix a bug that caused server agents to continue cleaning up peering resources even after loss of leadership. [[GH-17483](https://github.com/hashicorp/consul/issues/17483)]
|
||||
* peering: Fixes a bug where the importing partition was not added to peered failover targets, which causes issues when the importing partition is a non-default partition. [[GH-16673](https://github.com/hashicorp/consul/issues/16673)]
|
||||
* ui: fixes ui tests run on CI [[GH-16428](https://github.com/hashicorp/consul/issues/16428)]
|
||||
* xds: Fixed a bug where modifying ACLs on a token being actively used for an xDS connection caused all xDS updates to fail. [[GH-17566](https://github.com/hashicorp/consul/issues/17566)]
|
||||
|
||||
## 1.15.4 (June 26, 2023)
|
||||
FEATURES:
|
||||
|
||||
|
|
|
@ -1,199 +0,0 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package localratelimit
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
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_ratelimit "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/local_ratelimit/v3"
|
||||
envoy_http_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
|
||||
envoy_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3"
|
||||
envoy_resource_v3 "github.com/envoyproxy/go-control-plane/pkg/resource/v3"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/hashicorp/consul/envoyextensions/extensioncommon"
|
||||
)
|
||||
|
||||
type ratelimit struct {
|
||||
extensioncommon.BasicExtensionAdapter
|
||||
|
||||
ProxyType string
|
||||
|
||||
// Token bucket of the rate limit
|
||||
MaxTokens *int
|
||||
TokensPerFill *int
|
||||
FillInterval *int
|
||||
|
||||
// Percent of requests to be rate limited
|
||||
FilterEnabled *uint32
|
||||
FilterEnforced *uint32
|
||||
}
|
||||
|
||||
var _ extensioncommon.BasicExtension = (*ratelimit)(nil)
|
||||
|
||||
// Constructor follows a specific function signature required for the extension registration.
|
||||
func Constructor(ext api.EnvoyExtension) (extensioncommon.EnvoyExtender, error) {
|
||||
var r ratelimit
|
||||
if name := ext.Name; name != api.BuiltinLocalRatelimitExtension {
|
||||
return nil, fmt.Errorf("expected extension name 'ratelimit' but got %q", name)
|
||||
}
|
||||
|
||||
if err := r.fromArguments(ext.Arguments); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &extensioncommon.BasicEnvoyExtender{
|
||||
Extension: &r,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *ratelimit) fromArguments(args map[string]interface{}) error {
|
||||
if err := mapstructure.Decode(args, r); err != nil {
|
||||
return fmt.Errorf("error decoding extension arguments: %v", err)
|
||||
}
|
||||
if r.ProxyType == "" {
|
||||
r.ProxyType = string(api.ServiceKindConnectProxy)
|
||||
}
|
||||
return r.validate()
|
||||
}
|
||||
|
||||
func (r *ratelimit) validate() error {
|
||||
var resultErr error
|
||||
|
||||
// NOTE: Envoy requires FillInterval value must be greater than 0.
|
||||
// If unset, it is considered as 0.
|
||||
if r.FillInterval == nil {
|
||||
resultErr = multierror.Append(resultErr, fmt.Errorf("FillInterval(in second) is missing"))
|
||||
} else if *r.FillInterval <= 0 {
|
||||
resultErr = multierror.Append(resultErr, fmt.Errorf("FillInterval(in second) must be greater than 0, got %d", *r.FillInterval))
|
||||
}
|
||||
|
||||
// NOTE: Envoy requires MaxToken value must be greater than 0.
|
||||
// If unset, it is considered as 0.
|
||||
if r.MaxTokens == nil {
|
||||
resultErr = multierror.Append(resultErr, fmt.Errorf("MaxTokens is missing"))
|
||||
} else if *r.MaxTokens <= 0 {
|
||||
resultErr = multierror.Append(resultErr, fmt.Errorf("MaxTokens must be greater than 0, got %d", r.MaxTokens))
|
||||
}
|
||||
|
||||
// TokensPerFill is allowed to unset. In this case, envoy
|
||||
// uses its default value, which is 1.
|
||||
if r.TokensPerFill != nil && *r.TokensPerFill <= 0 {
|
||||
resultErr = multierror.Append(resultErr, fmt.Errorf("TokensPerFill must be greater than 0, got %d", *r.TokensPerFill))
|
||||
}
|
||||
|
||||
if err := validateProxyType(r.ProxyType); err != nil {
|
||||
resultErr = multierror.Append(resultErr, err)
|
||||
}
|
||||
|
||||
return resultErr
|
||||
}
|
||||
|
||||
// CanApply determines if the extension can apply to the given extension configuration.
|
||||
func (p *ratelimit) CanApply(config *extensioncommon.RuntimeConfig) bool {
|
||||
return string(config.Kind) == p.ProxyType
|
||||
}
|
||||
|
||||
// PatchFilter inserts a http local rate_limit filter at the head of
|
||||
// envoy.filters.network.http_connection_manager filters
|
||||
func (r ratelimit) PatchFilter(p extensioncommon.FilterPayload) (*envoy_listener_v3.Filter, bool, error) {
|
||||
filter := p.Message
|
||||
// rate limit is only applied to the inbound listener of the service itself
|
||||
// since the limit is aggregated from all downstream connections.
|
||||
if !p.IsInbound() {
|
||||
return filter, false, nil
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
tokenBucket := envoy_type_v3.TokenBucket{}
|
||||
|
||||
if r.TokensPerFill != nil {
|
||||
tokenBucket.TokensPerFill = &wrapperspb.UInt32Value{
|
||||
Value: uint32(*r.TokensPerFill),
|
||||
}
|
||||
}
|
||||
if r.MaxTokens != nil {
|
||||
tokenBucket.MaxTokens = uint32(*r.MaxTokens)
|
||||
}
|
||||
|
||||
if r.FillInterval != nil {
|
||||
tokenBucket.FillInterval = durationpb.New(time.Duration(*r.FillInterval) * time.Second)
|
||||
}
|
||||
|
||||
var FilterEnabledDefault *envoy_core_v3.RuntimeFractionalPercent
|
||||
if r.FilterEnabled != nil {
|
||||
FilterEnabledDefault = &envoy_core_v3.RuntimeFractionalPercent{
|
||||
DefaultValue: &envoy_type_v3.FractionalPercent{
|
||||
Numerator: *r.FilterEnabled,
|
||||
Denominator: envoy_type_v3.FractionalPercent_HUNDRED,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var FilterEnforcedDefault *envoy_core_v3.RuntimeFractionalPercent
|
||||
if r.FilterEnforced != nil {
|
||||
FilterEnforcedDefault = &envoy_core_v3.RuntimeFractionalPercent{
|
||||
DefaultValue: &envoy_type_v3.FractionalPercent{
|
||||
Numerator: *r.FilterEnforced,
|
||||
Denominator: envoy_type_v3.FractionalPercent_HUNDRED,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
ratelimitHttpFilter, err := extensioncommon.MakeEnvoyHTTPFilter(
|
||||
"envoy.filters.http.local_ratelimit",
|
||||
&envoy_ratelimit.LocalRateLimit{
|
||||
TokenBucket: &tokenBucket,
|
||||
StatPrefix: "local_ratelimit",
|
||||
FilterEnabled: FilterEnabledDefault,
|
||||
FilterEnforced: FilterEnforcedDefault,
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return filter, false, err
|
||||
}
|
||||
|
||||
changedFilters := make([]*envoy_http_v3.HttpFilter, 0, len(config.HttpFilters)+1)
|
||||
|
||||
// The ratelimitHttpFilter is inserted as the first element of the http
|
||||
// filter chain.
|
||||
changedFilters = append(changedFilters, ratelimitHttpFilter)
|
||||
changedFilters = append(changedFilters, config.HttpFilters...)
|
||||
config.HttpFilters = changedFilters
|
||||
|
||||
newFilter, err := extensioncommon.MakeFilter("envoy.filters.network.http_connection_manager", config)
|
||||
if err != nil {
|
||||
return filter, false, errors.New("error making new filter")
|
||||
}
|
||||
|
||||
return newFilter, true, nil
|
||||
}
|
||||
|
||||
func validateProxyType(t string) error {
|
||||
if t != string(api.ServiceKindConnectProxy) {
|
||||
return fmt.Errorf("unexpected ProxyType %q", t)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,187 +0,0 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package localratelimit
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/hashicorp/consul/envoyextensions/extensioncommon"
|
||||
)
|
||||
|
||||
func TestConstructor(t *testing.T) {
|
||||
makeArguments := func(overrides map[string]interface{}) map[string]interface{} {
|
||||
m := map[string]interface{}{
|
||||
"ProxyType": "connect-proxy",
|
||||
}
|
||||
|
||||
for k, v := range overrides {
|
||||
m[k] = v
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
cases := map[string]struct {
|
||||
extensionName string
|
||||
arguments map[string]interface{}
|
||||
expected ratelimit
|
||||
ok bool
|
||||
expectedErrMsg string
|
||||
}{
|
||||
"with no arguments": {
|
||||
arguments: nil,
|
||||
ok: false,
|
||||
},
|
||||
"with an invalid name": {
|
||||
arguments: makeArguments(map[string]interface{}{}),
|
||||
extensionName: "bad",
|
||||
ok: false,
|
||||
},
|
||||
"MaxToken is missing": {
|
||||
arguments: makeArguments(map[string]interface{}{
|
||||
"ProxyType": "connect-proxy",
|
||||
"FillInterval": 30,
|
||||
"TokensPerFill": 5,
|
||||
}),
|
||||
expectedErrMsg: "MaxTokens is missing",
|
||||
ok: false,
|
||||
},
|
||||
"MaxTokens <= 0": {
|
||||
arguments: makeArguments(map[string]interface{}{
|
||||
"ProxyType": "connect-proxy",
|
||||
"FillInterval": 30,
|
||||
"TokensPerFill": 5,
|
||||
"MaxTokens": 0,
|
||||
}),
|
||||
expectedErrMsg: "MaxTokens must be greater than 0",
|
||||
ok: false,
|
||||
},
|
||||
"FillInterval is missing": {
|
||||
arguments: makeArguments(map[string]interface{}{
|
||||
"ProxyType": "connect-proxy",
|
||||
"TokensPerFill": 5,
|
||||
"MaxTokens": 10,
|
||||
}),
|
||||
expectedErrMsg: "FillInterval(in second) is missing",
|
||||
ok: false,
|
||||
},
|
||||
"FillInterval <= 0": {
|
||||
arguments: makeArguments(map[string]interface{}{
|
||||
"ProxyType": "connect-proxy",
|
||||
"FillInterval": 0,
|
||||
"TokensPerFill": 5,
|
||||
"MaxTokens": 10,
|
||||
}),
|
||||
expectedErrMsg: "FillInterval(in second) must be greater than 0",
|
||||
ok: false,
|
||||
},
|
||||
"TokensPerFill <= 0": {
|
||||
arguments: makeArguments(map[string]interface{}{
|
||||
"ProxyType": "connect-proxy",
|
||||
"FillInterval": 30,
|
||||
"TokensPerFill": 0,
|
||||
"MaxTokens": 10,
|
||||
}),
|
||||
expectedErrMsg: "TokensPerFill must be greater than 0",
|
||||
ok: false,
|
||||
},
|
||||
"FilterEnabled < 0": {
|
||||
arguments: makeArguments(map[string]interface{}{
|
||||
"ProxyType": "connect-proxy",
|
||||
"FillInterval": 30,
|
||||
"TokensPerFill": 5,
|
||||
"MaxTokens": 10,
|
||||
"FilterEnabled": -1,
|
||||
}),
|
||||
expectedErrMsg: "cannot parse 'FilterEnabled', -1 overflows uint",
|
||||
ok: false,
|
||||
},
|
||||
"FilterEnforced < 0": {
|
||||
arguments: makeArguments(map[string]interface{}{
|
||||
"ProxyType": "connect-proxy",
|
||||
"FillInterval": 30,
|
||||
"TokensPerFill": 5,
|
||||
"MaxTokens": 10,
|
||||
"FilterEnforced": -1,
|
||||
}),
|
||||
expectedErrMsg: "cannot parse 'FilterEnforced', -1 overflows uint",
|
||||
ok: false,
|
||||
},
|
||||
"invalid proxy type": {
|
||||
arguments: makeArguments(map[string]interface{}{
|
||||
"ProxyType": "invalid",
|
||||
"FillInterval": 30,
|
||||
"MaxTokens": 20,
|
||||
"TokensPerFill": 5,
|
||||
}),
|
||||
expectedErrMsg: `unexpected ProxyType "invalid"`,
|
||||
ok: false,
|
||||
},
|
||||
"default proxy type": {
|
||||
arguments: makeArguments(map[string]interface{}{
|
||||
"FillInterval": 30,
|
||||
"MaxTokens": 20,
|
||||
"TokensPerFill": 5,
|
||||
}),
|
||||
expected: ratelimit{
|
||||
ProxyType: "connect-proxy",
|
||||
MaxTokens: intPointer(20),
|
||||
FillInterval: intPointer(30),
|
||||
TokensPerFill: intPointer(5),
|
||||
},
|
||||
ok: true,
|
||||
},
|
||||
"valid everything": {
|
||||
arguments: makeArguments(map[string]interface{}{
|
||||
"ProxyType": "connect-proxy",
|
||||
"FillInterval": 30,
|
||||
"MaxTokens": 20,
|
||||
"TokensPerFill": 5,
|
||||
}),
|
||||
expected: ratelimit{
|
||||
ProxyType: "connect-proxy",
|
||||
MaxTokens: intPointer(20),
|
||||
FillInterval: intPointer(30),
|
||||
TokensPerFill: intPointer(5),
|
||||
},
|
||||
ok: true,
|
||||
},
|
||||
}
|
||||
|
||||
for n, tc := range cases {
|
||||
t.Run(n, func(t *testing.T) {
|
||||
|
||||
extensionName := api.BuiltinLocalRatelimitExtension
|
||||
if tc.extensionName != "" {
|
||||
extensionName = tc.extensionName
|
||||
}
|
||||
|
||||
svc := api.CompoundServiceName{Name: "svc"}
|
||||
ext := extensioncommon.RuntimeConfig{
|
||||
ServiceName: svc,
|
||||
EnvoyExtension: api.EnvoyExtension{
|
||||
Name: extensionName,
|
||||
Arguments: tc.arguments,
|
||||
},
|
||||
}
|
||||
|
||||
e, err := Constructor(ext.EnvoyExtension)
|
||||
|
||||
if tc.ok {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, &extensioncommon.BasicEnvoyExtender{Extension: &tc.expected}, e)
|
||||
} else {
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tc.expectedErrMsg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func intPointer(i int) *int {
|
||||
return &i
|
||||
}
|
|
@ -11,7 +11,6 @@ import (
|
|||
|
||||
awslambda "github.com/hashicorp/consul/agent/envoyextensions/builtin/aws-lambda"
|
||||
extauthz "github.com/hashicorp/consul/agent/envoyextensions/builtin/ext-authz"
|
||||
"github.com/hashicorp/consul/agent/envoyextensions/builtin/http/localratelimit"
|
||||
"github.com/hashicorp/consul/agent/envoyextensions/builtin/lua"
|
||||
propertyoverride "github.com/hashicorp/consul/agent/envoyextensions/builtin/property-override"
|
||||
"github.com/hashicorp/consul/agent/envoyextensions/builtin/wasm"
|
||||
|
@ -24,7 +23,6 @@ type extensionConstructor func(api.EnvoyExtension) (extensioncommon.EnvoyExtende
|
|||
var extensionConstructors = map[string]extensionConstructor{
|
||||
api.BuiltinLuaExtension: lua.Constructor,
|
||||
api.BuiltinAWSLambdaExtension: awslambda.Constructor,
|
||||
api.BuiltinLocalRatelimitExtension: localratelimit.Constructor,
|
||||
api.BuiltinPropertyOverrideExtension: propertyoverride.Constructor,
|
||||
api.BuiltinWasmExtension: wasm.Constructor,
|
||||
api.BuiltinExtAuthzExtension: extauthz.Constructor,
|
||||
|
|
|
@ -574,7 +574,7 @@ func (e *ProxyConfigEntry) UnmarshalBinary(data []byte) error {
|
|||
// into a concrete type.
|
||||
//
|
||||
// There is an 'api' variation of this in
|
||||
// command/config/write/config_write.go:newDecodeConfigEntry
|
||||
// command/helpers/helpers.go:newDecodeConfigEntry
|
||||
func DecodeConfigEntry(raw map[string]interface{}) (ConfigEntry, error) {
|
||||
var entry ConfigEntry
|
||||
|
||||
|
|
|
@ -15,13 +15,14 @@ import (
|
|||
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_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
|
||||
"github.com/hashicorp/consul/agent/xds/testcommon"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
goversion "github.com/hashicorp/go-version"
|
||||
testinf "github.com/mitchellh/go-testing-interface"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/hashicorp/consul/agent/xds/testcommon"
|
||||
|
||||
propertyoverride "github.com/hashicorp/consul/agent/envoyextensions/builtin/property-override"
|
||||
"github.com/hashicorp/consul/agent/proxycfg"
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
|
@ -579,27 +580,6 @@ end`,
|
|||
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, nsFunc, nil, makeLambdaServiceDefaults(true))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "http-local-ratelimit-applyto-filter",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) {
|
||||
ns.Proxy.Config["protocol"] = "http"
|
||||
ns.Proxy.EnvoyExtensions = []structs.EnvoyExtension{
|
||||
{
|
||||
Name: api.BuiltinLocalRatelimitExtension,
|
||||
Arguments: map[string]interface{}{
|
||||
"ProxyType": "connect-proxy",
|
||||
"MaxTokens": 3,
|
||||
"TokensPerFill": 2,
|
||||
"FillInterval": 10,
|
||||
"FilterEnabled": 100,
|
||||
"FilterEnforced": 100,
|
||||
},
|
||||
},
|
||||
}
|
||||
}, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "wasm-http-local-file",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
|
|
|
@ -1,127 +0,0 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {},
|
||||
"resourceApiVersion": "V3"
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"circuitBreakers": {},
|
||||
"outlierDetection": {},
|
||||
"commonLbConfig": {
|
||||
"healthyPanicThreshold": {}
|
||||
},
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
|
||||
"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"
|
||||
},
|
||||
"matchSubjectAltNames": [
|
||||
{
|
||||
"exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {},
|
||||
"resourceApiVersion": "V3"
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"circuitBreakers": {},
|
||||
"outlierDetection": {},
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
|
||||
"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"
|
||||
},
|
||||
"matchSubjectAltNames": [
|
||||
{
|
||||
"exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target"
|
||||
},
|
||||
{
|
||||
"exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"name": "local_app",
|
||||
"type": "STATIC",
|
||||
"connectTimeout": "5s",
|
||||
"loadAssignment": {
|
||||
"clusterName": "local_app",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "127.0.0.1",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment",
|
||||
"clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "10.10.1.1",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
},
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "10.10.1.2",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment",
|
||||
"clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "10.10.1.1",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
},
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "10.20.1.2",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -1,256 +0,0 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"name": "db:127.0.0.1:9191",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "127.0.0.1",
|
||||
"portValue": 9191
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"filters": [
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"name": "prepared_query:geo-cache:127.10.10.10:8181",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "127.10.10.10",
|
||||
"portValue": 8181
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.filters.network.tcp_proxy",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy",
|
||||
"statPrefix": "upstream.prepared_query_geo-cache",
|
||||
"cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"name": "public_listener:0.0.0.0:9999",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "0.0.0.0",
|
||||
"portValue": 9999
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.filters.network.http_connection_manager",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager",
|
||||
"statPrefix": "public_listener",
|
||||
"routeConfig": {
|
||||
"name": "public_listener",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "public_listener",
|
||||
"domains": [
|
||||
"*"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": {
|
||||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "local_app"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"httpFilters": [
|
||||
{
|
||||
"name": "envoy.filters.http.local_ratelimit",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit",
|
||||
"statPrefix": "local_ratelimit",
|
||||
"tokenBucket": {
|
||||
"maxTokens": 3,
|
||||
"tokensPerFill": 2,
|
||||
"fillInterval": "10s"
|
||||
},
|
||||
"filterEnabled": {
|
||||
"defaultValue": {
|
||||
"numerator": 100
|
||||
}
|
||||
},
|
||||
"filterEnforced": {
|
||||
"defaultValue": {
|
||||
"numerator": 100
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "envoy.filters.http.rbac",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC",
|
||||
"rules": {}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "envoy.filters.http.header_to_metadata",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.filters.http.header_to_metadata.v3.Config",
|
||||
"requestRules": [
|
||||
{
|
||||
"header": "x-forwarded-client-cert",
|
||||
"onHeaderPresent": {
|
||||
"metadataNamespace": "consul",
|
||||
"key": "trust-domain",
|
||||
"regexValueRewrite": {
|
||||
"pattern": {
|
||||
"googleRe2": {},
|
||||
"regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*"
|
||||
},
|
||||
"substitution": "\\1"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"header": "x-forwarded-client-cert",
|
||||
"onHeaderPresent": {
|
||||
"metadataNamespace": "consul",
|
||||
"key": "partition",
|
||||
"regexValueRewrite": {
|
||||
"pattern": {
|
||||
"googleRe2": {},
|
||||
"regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*"
|
||||
},
|
||||
"substitution": "\\2"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"header": "x-forwarded-client-cert",
|
||||
"onHeaderPresent": {
|
||||
"metadataNamespace": "consul",
|
||||
"key": "namespace",
|
||||
"regexValueRewrite": {
|
||||
"pattern": {
|
||||
"googleRe2": {},
|
||||
"regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*"
|
||||
},
|
||||
"substitution": "\\3"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"header": "x-forwarded-client-cert",
|
||||
"onHeaderPresent": {
|
||||
"metadataNamespace": "consul",
|
||||
"key": "datacenter",
|
||||
"regexValueRewrite": {
|
||||
"pattern": {
|
||||
"googleRe2": {},
|
||||
"regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*"
|
||||
},
|
||||
"substitution": "\\4"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"header": "x-forwarded-client-cert",
|
||||
"onHeaderPresent": {
|
||||
"metadataNamespace": "consul",
|
||||
"key": "service",
|
||||
"regexValueRewrite": {
|
||||
"pattern": {
|
||||
"googleRe2": {},
|
||||
"regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*"
|
||||
},
|
||||
"substitution": "\\5"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "envoy.filters.http.router",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tracing": {
|
||||
"randomSampling": {}
|
||||
},
|
||||
"forwardClientCertDetails": "APPEND_FORWARD",
|
||||
"setCurrentClientCertDetails": {
|
||||
"subject": true,
|
||||
"cert": true,
|
||||
"chain": true,
|
||||
"dns": true,
|
||||
"uri": 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"
|
||||
}
|
||||
},
|
||||
"alpnProtocols": [
|
||||
"http/1.1"
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": true
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"trafficDirection": "INBOUND"
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -42,7 +42,6 @@ const (
|
|||
BuiltinAWSLambdaExtension string = "builtin/aws/lambda"
|
||||
BuiltinExtAuthzExtension string = "builtin/ext-authz"
|
||||
BuiltinLuaExtension string = "builtin/lua"
|
||||
BuiltinLocalRatelimitExtension string = "builtin/http/localratelimit"
|
||||
BuiltinPropertyOverrideExtension string = "builtin/property-override"
|
||||
BuiltinWasmExtension string = "builtin/wasm"
|
||||
// BuiltinValidateExtension should not be exposed directly or accepted as a valid configured
|
||||
|
|
|
@ -7,17 +7,12 @@ import (
|
|||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/hashicorp/consul/command/config"
|
||||
"github.com/hashicorp/consul/command/flags"
|
||||
"github.com/hashicorp/consul/command/helpers"
|
||||
"github.com/hashicorp/consul/lib/decode"
|
||||
)
|
||||
|
||||
func New(ui cli.Ui) *cmd {
|
||||
|
@ -109,67 +104,6 @@ func (c *cmd) Run(args []string) int {
|
|||
return 0
|
||||
}
|
||||
|
||||
// There is a 'structs' variation of this in
|
||||
// agent/structs/config_entry.go:DecodeConfigEntry
|
||||
func newDecodeConfigEntry(raw map[string]interface{}) (api.ConfigEntry, error) {
|
||||
var entry api.ConfigEntry
|
||||
|
||||
kindVal, ok := raw["Kind"]
|
||||
if !ok {
|
||||
kindVal, ok = raw["kind"]
|
||||
}
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Payload does not contain a kind/Kind key at the top level")
|
||||
}
|
||||
|
||||
if kindStr, ok := kindVal.(string); ok {
|
||||
newEntry, err := api.MakeConfigEntry(kindStr, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
entry = newEntry
|
||||
} else {
|
||||
return nil, fmt.Errorf("Kind value in payload is not a string")
|
||||
}
|
||||
|
||||
var md mapstructure.Metadata
|
||||
decodeConf := &mapstructure.DecoderConfig{
|
||||
DecodeHook: mapstructure.ComposeDecodeHookFunc(
|
||||
decode.HookWeakDecodeFromSlice,
|
||||
decode.HookTranslateKeys,
|
||||
mapstructure.StringToTimeDurationHookFunc(),
|
||||
mapstructure.StringToTimeHookFunc(time.RFC3339),
|
||||
),
|
||||
Metadata: &md,
|
||||
Result: &entry,
|
||||
WeaklyTypedInput: true,
|
||||
}
|
||||
|
||||
decoder, err := mapstructure.NewDecoder(decodeConf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := decoder.Decode(raw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, k := range md.Unused {
|
||||
switch k {
|
||||
case "kind", "Kind":
|
||||
// The kind field is used to determine the target, but doesn't need
|
||||
// to exist on the target.
|
||||
continue
|
||||
}
|
||||
err = multierror.Append(err, fmt.Errorf("invalid config key %q", k))
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return entry, nil
|
||||
}
|
||||
|
||||
func (c *cmd) Synopsis() string {
|
||||
return synopsis
|
||||
}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
|
||||
snapshot_envoy_admin localhost:19000 s1 primary || true
|
||||
snapshot_envoy_admin localhost:19001 s2 primary || true
|
|
@ -1,19 +0,0 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
services {
|
||||
name = "s1"
|
||||
port = 8080
|
||||
connect {
|
||||
sidecar_service {
|
||||
proxy {
|
||||
upstreams = [
|
||||
{
|
||||
destination_name = "s2"
|
||||
local_bind_port = 5000
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
services {
|
||||
name = "s2"
|
||||
port = 8181
|
||||
connect { sidecar_service {} }
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
|
||||
set -eEuo pipefail
|
||||
|
||||
upsert_config_entry primary '
|
||||
Kind = "service-defaults"
|
||||
Name = "s2"
|
||||
Protocol = "http"
|
||||
EnvoyExtensions = [
|
||||
{
|
||||
Name = "builtin/http/localratelimit",
|
||||
Arguments = {
|
||||
ProxyType = "connect-proxy"
|
||||
MaxTokens = 1,
|
||||
TokensPerFill = 1,
|
||||
FillInterval = 120,
|
||||
FilterEnabled = 100,
|
||||
FilterEnforced = 100,
|
||||
}
|
||||
}
|
||||
]
|
||||
'
|
||||
|
||||
upsert_config_entry primary '
|
||||
Kind = "service-defaults"
|
||||
Name = "s1"
|
||||
Protocol = "tcp"
|
||||
EnvoyExtensions = [
|
||||
{
|
||||
Name = "builtin/http/localratelimit",
|
||||
Arguments = {
|
||||
ProxyType = "connect-proxy"
|
||||
MaxTokens = 1,
|
||||
TokensPerFill = 1,
|
||||
FillInterval = 120,
|
||||
FilterEnabled = 100,
|
||||
FilterEnforced = 100,
|
||||
}
|
||||
}
|
||||
]
|
||||
'
|
||||
|
||||
register_services primary
|
||||
|
||||
gen_envoy_bootstrap s1 19000 primary
|
||||
gen_envoy_bootstrap s2 19001 primary
|
|
@ -1,6 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
|
||||
export REQUIRED_SERVICES="s1 s1-sidecar-proxy s2 s2-sidecar-proxy"
|
|
@ -1,57 +0,0 @@
|
|||
#!/usr/bin/env bats
|
||||
|
||||
load helpers
|
||||
|
||||
@test "s1 proxy admin is up on :19000" {
|
||||
retry_default curl -f -s localhost:19000/stats -o /dev/null
|
||||
}
|
||||
|
||||
@test "s2 proxy admin is up on :19001" {
|
||||
retry_default curl -f -s localhost:19001/stats -o /dev/null
|
||||
}
|
||||
|
||||
@test "s1 proxy listener should be up and have right cert" {
|
||||
assert_proxy_presents_cert_uri localhost:21000 s1
|
||||
}
|
||||
|
||||
@test "s2 proxy listener should be up and have right cert" {
|
||||
assert_proxy_presents_cert_uri localhost:21001 s2
|
||||
}
|
||||
|
||||
@test "s2 proxy should be healthy" {
|
||||
assert_service_has_healthy_instances s2 1
|
||||
}
|
||||
|
||||
@test "s1 upstream should have healthy endpoints for s2" {
|
||||
assert_upstream_has_endpoints_in_status 127.0.0.1:19000 s2.default.primary HEALTHY 1
|
||||
}
|
||||
|
||||
@test "s2 proxy should have been configured with http local ratelimit filters" {
|
||||
HTTP_FILTERS=$(get_envoy_http_filters localhost:19001)
|
||||
PUB=$(echo "$HTTP_FILTERS" | grep -E "^public_listener:" | cut -f 2 -d ' ')
|
||||
|
||||
echo "HTTP_FILTERS = $HTTP_FILTERS"
|
||||
echo "PUB = $PUB"
|
||||
|
||||
[ "$PUB" = "envoy.filters.http.local_ratelimit,envoy.filters.http.rbac,envoy.filters.http.header_to_metadata,envoy.filters.http.router" ]
|
||||
}
|
||||
|
||||
@test "s1(tcp) proxy should not be changed by http/localratelimit extension" {
|
||||
TCP_FILTERS=$(get_envoy_listener_filters localhost:19000)
|
||||
PUB=$(echo "$TCP_FILTERS" | grep -E "^public_listener:" | cut -f 2 -d ' ')
|
||||
|
||||
echo "TCP_FILTERS = $TCP_FILTERS"
|
||||
echo "PUB = $PUB"
|
||||
|
||||
[ "$PUB" = "envoy.filters.network.rbac,envoy.filters.network.tcp_proxy" ]
|
||||
}
|
||||
|
||||
@test "first connection to s2 - success" {
|
||||
run retry_default curl -s -f -d hello localhost:5000
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"hello"* ]]
|
||||
}
|
||||
|
||||
@test "ratelimit to s2 is in effect - return code 429" {
|
||||
retry_default must_fail_http_connection localhost:5000 429
|
||||
}
|
|
@ -22,8 +22,13 @@ For nodes in server mode, the node is removed from the Raft peer set
|
|||
in a graceful manner. This is critical, as in certain situations a
|
||||
non-graceful leave can affect cluster availability.
|
||||
|
||||
Running `consul leave` on a server explicitly will reduce the quorum size. Even if the cluster used `bootstrap_expect` to set a quorum size initially, issuing `consul leave` on a server will reconfigure the cluster to have fewer servers.
|
||||
This means you could end up with just one server that is still able to commit writes because quorum is only 1, but those writes might be lost if that server fails before more are added.
|
||||
Depending on how many Consul servers are running, running `consul leave` on a server explicitly can reduce the quorum
|
||||
size (which is derived from the number of Consul servers, see
|
||||
[deployment_table](/consul/docs/architecture/consensus#deployment_table)).
|
||||
Even if the cluster used `bootstrap_expect` to set a number of servers and thus quorum size initially,
|
||||
issuing `consul leave` on a server will reconfigure the cluster to have fewer servers.
|
||||
This means you could end up with just one server that is still able to commit writes because the quorum size for
|
||||
1-server setup is only 1, but those writes might be lost if that server fails before more are added.
|
||||
|
||||
The table below shows this command's [required ACLs](/consul/api-docs/api-structure#authentication). Configuration of
|
||||
[blocking queries](/consul/api-docs/features/blocking) and [agent caching](/consul/api-docs/features/caching)
|
||||
|
|
|
@ -22,11 +22,11 @@ Configure your [`Gateway`](/consul/docs/api-gateway/configuration/gateway) and [
|
|||
|
||||
<CodeBlockConfig hideClipboard filename="values.yaml">
|
||||
|
||||
```yaml
|
||||
apiGateway:
|
||||
enabled: true
|
||||
managedGatewayClass:
|
||||
```
|
||||
```yaml
|
||||
apiGateway:
|
||||
enabled: true
|
||||
managedGatewayClass:
|
||||
```
|
||||
|
||||
</CodeBlockConfig>
|
||||
|
||||
|
@ -34,9 +34,9 @@ Configure your [`Gateway`](/consul/docs/api-gateway/configuration/gateway) and [
|
|||
|
||||
Issue the `kubectl apply` command to implement the configurations:
|
||||
|
||||
```shell-session
|
||||
$ kubectl apply -f gateway.yaml routes.yaml
|
||||
```
|
||||
```shell-session
|
||||
$ kubectl apply -f gateway.yaml routes.yaml
|
||||
```
|
||||
|
||||
|
||||
<!--- Commented out per https://github.com/hashicorp/consul/pull/11951/files#r791204596
|
||||
|
|
|
@ -182,6 +182,60 @@ spec:
|
|||
]
|
||||
```
|
||||
|
||||
</CodeTabs>
|
||||
</Tab>
|
||||
|
||||
|
||||
<Tab heading="Consul Enterprise (Sameness Group)">
|
||||
<CodeTabs heading="Exported services configuration syntax" tabs={[ "HCL", "Kubernetes YAML", "JSON" ]}>
|
||||
|
||||
```hcl
|
||||
Kind = "exported-services"
|
||||
Partition = "<partition containing services to export>"
|
||||
Name = "<partition containing services to export>"
|
||||
Services = [
|
||||
{
|
||||
Name = "<name of service to export>"
|
||||
Namespace = "<namespace in the partition containing the service to export>"
|
||||
Consumers = [
|
||||
{
|
||||
SamenessGroup = "<name of the sameness group that dials the exported service>"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
```yaml
|
||||
apiVersion: consul.hashicorp.com/v1alpha1
|
||||
kind: ExportedServices
|
||||
metadata:
|
||||
name: <partition containing services to export>
|
||||
spec:
|
||||
services:
|
||||
- name: <name of service to export>
|
||||
namespace: <namespace in the partition containing the service to export>
|
||||
consumers:
|
||||
- samenessGroup: <name of the sameness group that dials the exported service>
|
||||
```
|
||||
|
||||
```json
|
||||
"Kind": "exported-services",
|
||||
"Partition": "<partition containing services to export>",
|
||||
"Name": "<partition containing services to export>",
|
||||
"Services": [
|
||||
{
|
||||
"Name": "<name of service to export>",
|
||||
"Namespace": "<namespace in the partition containing the service to export>"
|
||||
"Consumers": [
|
||||
{
|
||||
"SamenessGroup": "<name of the sameness group that dials the exported service>"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
</CodeTabs>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
@ -456,6 +510,57 @@ spec:
|
|||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Exporting a service to a sameness group
|
||||
|
||||
The following example configures Consul to export a service named `api` to a defined group of partitions that belong to a separately defined [sameness group](/consul/docs/connect/config-entries/sameness-group) named `monitoring`.
|
||||
|
||||
<CodeTabs tabs={[ "HCL", "Kubernetes YAML", "JSON" ]}>
|
||||
|
||||
```hcl
|
||||
Kind = "exported-services"
|
||||
Name = "default"
|
||||
|
||||
Services = [
|
||||
{
|
||||
Name = "api"
|
||||
Consumers = [
|
||||
{
|
||||
SamenessGroup = "monitoring"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
```yaml
|
||||
apiVersion: consul.hashicorp.com/v1alpha1
|
||||
Kind: ExportedServices
|
||||
metadata:
|
||||
name: default
|
||||
spec:
|
||||
services:
|
||||
- name: api
|
||||
consumers:
|
||||
- samenessGroup: monitoring
|
||||
```
|
||||
|
||||
```json
|
||||
"Kind": "exported-services",
|
||||
"Name": "default",
|
||||
"Services": [
|
||||
{
|
||||
"Name": "api",
|
||||
"Consumers": [
|
||||
{
|
||||
"SamenessGroup": "monitoring"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
</CodeTabs>
|
||||
|
||||
### Exporting all services
|
||||
|
||||
<Tabs>
|
||||
|
|
|
@ -404,7 +404,7 @@ String value that specifies the namespace in which to register the service. Refe
|
|||
|
||||
## Multiple service definitions
|
||||
|
||||
You can define multiple services in a single definition file in the `servcies` block. This enables you register multiple services in a single command. Note that the HTTP API does not support the `services` block.
|
||||
You can define multiple services in a single definition file in the `services` block. This enables you register multiple services in a single command. Note that the HTTP API does not support the `services` block.
|
||||
|
||||
<CodeTabs tabs={[ "HCL", "JSON" ]}>
|
||||
|
||||
|
|
Loading…
Reference in New Issue