structs: prohibit config entries from referencing more than one partition at a time (#10478)

affected kinds: service-defaults, ingress-gateway, terminating-gateway, service-intentions
This commit is contained in:
R.B. Boyer 2021-06-23 16:44:10 -05:00 committed by GitHub
parent 8344b7fe2e
commit e3835ac6a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 39 additions and 5 deletions

3
.changelog/10478.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
structs: prohibit config entries from referencing more than one partition at a time
```

View File

@ -169,6 +169,10 @@ func (e *ServiceConfigEntry) Validate() error {
if err != nil { if err != nil {
validationErr = multierror.Append(validationErr, fmt.Errorf("error in upstream override for %s: %v", override.ServiceName(), err)) validationErr = multierror.Append(validationErr, fmt.Errorf("error in upstream override for %s: %v", override.ServiceName(), err))
} }
if err := validateInnerEnterpriseMeta(&override.EnterpriseMeta, &e.EnterpriseMeta); err != nil {
validationErr = multierror.Append(validationErr, fmt.Errorf("error in upstream override for %s: %v", override.ServiceName(), err))
}
} }
if e.UpstreamConfig.Defaults != nil { if e.UpstreamConfig.Defaults != nil {
@ -802,6 +806,9 @@ func (cfg UpstreamConfig) validate(named bool) error {
if cfg.EnterpriseMeta.NamespaceOrEmpty() != "" { if cfg.EnterpriseMeta.NamespaceOrEmpty() != "" {
return fmt.Errorf("Namespace must be empty") return fmt.Errorf("Namespace must be empty")
} }
if cfg.EnterpriseMeta.PartitionOrEmpty() != "" {
return fmt.Errorf("Partition must be empty")
}
} }
var validationErr error var validationErr error

View File

@ -379,6 +379,8 @@ type ServiceRouteDestination struct {
// splitting. // splitting.
Namespace string `json:",omitempty"` Namespace string `json:",omitempty"`
// NOTE: Partition is not represented here by design. Do not add it.
// PrefixRewrite allows for the proxied request to have its matching path // PrefixRewrite allows for the proxied request to have its matching path
// prefix modified before being sent to the destination. Described more // prefix modified before being sent to the destination. Described more
// below in the envoy implementation section. // below in the envoy implementation section.
@ -658,6 +660,8 @@ type ServiceSplit struct {
// If this field is specified then this route is ineligible for further // If this field is specified then this route is ineligible for further
// splitting. // splitting.
Namespace string `json:",omitempty"` Namespace string `json:",omitempty"`
// NOTE: Partition is not represented here by design. Do not add it.
} }
// ServiceResolverConfigEntry defines which instances of a service should // ServiceResolverConfigEntry defines which instances of a service should
@ -1048,6 +1052,8 @@ type ServiceResolverRedirect struct {
// Datacenter is the datacenter to resolve the service from instead of the // Datacenter is the datacenter to resolve the service from instead of the
// current one (optional). // current one (optional).
Datacenter string `json:",omitempty"` Datacenter string `json:",omitempty"`
// NOTE: Partition is not represented here by design. Do not add it.
} }
// There are some restrictions on what is allowed in here: // There are some restrictions on what is allowed in here:
@ -1082,6 +1088,8 @@ type ServiceResolverFailover struct {
// //
// This is a DESTINATION during failover. // This is a DESTINATION during failover.
Datacenters []string `json:",omitempty"` Datacenters []string `json:",omitempty"`
// NOTE: Partition is not represented here by design. Do not add it.
} }
// LoadBalancer determines the load balancing policy and configuration for services // LoadBalancer determines the load balancing policy and configuration for services
@ -1336,6 +1344,8 @@ type DiscoveryChainRequest struct {
EvaluateInDatacenter string EvaluateInDatacenter string
EvaluateInNamespace string EvaluateInNamespace string
// NOTE: Partition is not represented here by design. Do not add it.
// OverrideMeshGateway allows for the mesh gateway setting to be overridden // OverrideMeshGateway allows for the mesh gateway setting to be overridden
// for any resolver in the compiled chain. // for any resolver in the compiled chain.
OverrideMeshGateway MeshGatewayConfig OverrideMeshGateway MeshGatewayConfig

View File

@ -164,7 +164,11 @@ func (e *IngressGatewayConfigEntry) Validate() error {
} }
declaredHosts := make(map[string]bool) declaredHosts := make(map[string]bool)
for _, s := range listener.Services { for i, s := range listener.Services {
if err := validateInnerEnterpriseMeta(&s.EnterpriseMeta, &e.EnterpriseMeta); err != nil {
return fmt.Errorf("Services[%d].%v", i, err)
}
if listener.Protocol == "tcp" { if listener.Protocol == "tcp" {
if s.Name == WildcardSpecifier { if s.Name == WildcardSpecifier {
return fmt.Errorf("Wildcard service name is only valid for protocol = 'http' (listener on port %d)", listener.Port) return fmt.Errorf("Wildcard service name is only valid for protocol = 'http' (listener on port %d)", listener.Port)
@ -377,8 +381,13 @@ func (e *TerminatingGatewayConfigEntry) Validate() error {
return fmt.Errorf("Wildcard namespace is not supported for terminating gateway services") return fmt.Errorf("Wildcard namespace is not supported for terminating gateway services")
} }
// Check for duplicates within the entry
cid := NewServiceID(svc.Name, &svc.EnterpriseMeta) cid := NewServiceID(svc.Name, &svc.EnterpriseMeta)
if err := validateInnerEnterpriseMeta(&svc.EnterpriseMeta, &e.EnterpriseMeta); err != nil {
return fmt.Errorf("Service %q: %v", cid.String(), err)
}
// Check for duplicates within the entry
if ok := seen[cid]; ok { if ok := seen[cid]; ok {
return fmt.Errorf("Service %q was specified more than once within a namespace", cid.String()) return fmt.Errorf("Service %q was specified more than once within a namespace", cid.String())
} }

View File

@ -567,7 +567,7 @@ func (e *ServiceIntentionsConfigEntry) validate(legacyWrite bool) error {
return fmt.Errorf("Sources[%d].%v", i, err) return fmt.Errorf("Sources[%d].%v", i, err)
} }
if err := validateSourceIntentionEnterpriseMeta(&src.EnterpriseMeta); err != nil { if err := validateSourceIntentionEnterpriseMeta(&src.EnterpriseMeta, &e.EnterpriseMeta); err != nil {
return fmt.Errorf("Sources[%d].%v", i, err) return fmt.Errorf("Sources[%d].%v", i, err)
} }

View File

@ -2,6 +2,6 @@
package structs package structs
func validateSourceIntentionEnterpriseMeta(_ *EnterpriseMeta) error { func validateSourceIntentionEnterpriseMeta(_, _ *EnterpriseMeta) error {
return nil return nil
} }

View File

@ -6,10 +6,11 @@ import (
"testing" "testing"
"time" "time"
"github.com/hashicorp/consul/sdk/testutil"
"github.com/hashicorp/go-uuid" "github.com/hashicorp/go-uuid"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/hashicorp/consul/sdk/testutil"
) )
func generateUUID() (ret string) { func generateUUID() (ret string) {

View File

@ -30,3 +30,7 @@ func validateUnusedKeys(unused []string) error {
} }
return err return err
} }
func validateInnerEnterpriseMeta(_, _ *EnterpriseMeta) error {
return nil
}