2023-03-28 18:39:22 +00:00
// Copyright (c) HashiCorp, Inc.
2023-08-11 13:12:13 +00:00
// SPDX-License-Identifier: BUSL-1.1
2023-03-28 18:39:22 +00:00
2021-04-06 18:19:59 +00:00
package structs
import (
2021-04-29 21:44:32 +00:00
"encoding/json"
2021-04-06 18:19:59 +00:00
"fmt"
"github.com/hashicorp/consul/acl"
2022-03-30 18:43:59 +00:00
"github.com/hashicorp/consul/types"
2021-04-06 18:19:59 +00:00
)
2021-04-28 22:13:29 +00:00
type MeshConfigEntry struct {
2021-04-06 18:19:59 +00:00
// TransparentProxy contains cluster-wide options pertaining to TPROXY mode
// when enabled.
2021-04-28 22:13:29 +00:00
TransparentProxy TransparentProxyMeshConfig ` alias:"transparent_proxy" `
2021-04-06 18:19:59 +00:00
2023-04-19 19:45:00 +00:00
// AllowEnablingPermissiveMutualTLS must be true in order to allow setting
// MutualTLSMode=permissive in either service-defaults or proxy-defaults.
AllowEnablingPermissiveMutualTLS bool ` json:",omitempty" alias:"allow_enabling_permissive_mutual_tls" `
2024-08-20 05:39:28 +00:00
// ValidateClusters controls whether the clusters the route table refers to are validated. The default value is
// false. When set to false and a route refers to a cluster that does not exist, the route table loads and routing
// to a non-existent cluster results in a 404. When set to true and the route is set to a cluster that do not exist,
// the route table will not load. For more information, refer to
// [HTTP route configuration in the Envoy docs](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route.proto#envoy-v3-api-field-config-route-v3-routeconfiguration-validate-clusters)
// for more details.
ValidateClusters bool ` json:",omitempty" alias:"validate_clusters" `
2022-03-30 18:43:59 +00:00
TLS * MeshTLSConfig ` json:",omitempty" `
2022-04-26 20:46:29 +00:00
HTTP * MeshHTTPConfig ` json:",omitempty" `
2022-09-02 20:52:11 +00:00
Peering * PeeringMeshConfig ` json:",omitempty" `
2022-03-13 03:55:53 +00:00
Meta map [ string ] string ` json:",omitempty" `
2023-12-12 13:29:13 +00:00
Hash uint64 ` json:",omitempty" hash:"ignore" `
2022-03-13 03:55:53 +00:00
acl . EnterpriseMeta ` hcl:",squash" mapstructure:",squash" `
2023-12-12 13:29:13 +00:00
RaftIndex ` hash:"ignore" `
}
func ( e * MeshConfigEntry ) SetHash ( h uint64 ) {
e . Hash = h
}
func ( e * MeshConfigEntry ) GetHash ( ) uint64 {
return e . Hash
2021-04-06 18:19:59 +00:00
}
2021-04-28 22:13:29 +00:00
// TransparentProxyMeshConfig contains cluster-wide options pertaining to
2021-04-06 18:19:59 +00:00
// TPROXY mode when enabled.
2021-04-28 22:13:29 +00:00
type TransparentProxyMeshConfig struct {
2021-06-14 20:15:09 +00:00
// MeshDestinationsOnly can be used to disable the pass-through that
2021-04-06 18:19:59 +00:00
// allows traffic to destinations outside of the mesh.
2021-06-14 20:15:09 +00:00
MeshDestinationsOnly bool ` alias:"mesh_destinations_only" `
2021-04-06 18:19:59 +00:00
}
2022-03-30 18:43:59 +00:00
type MeshTLSConfig struct {
Incoming * MeshDirectionalTLSConfig ` json:",omitempty" `
Outgoing * MeshDirectionalTLSConfig ` json:",omitempty" `
}
type MeshDirectionalTLSConfig struct {
TLSMinVersion types . TLSVersion ` json:",omitempty" alias:"tls_min_version" `
TLSMaxVersion types . TLSVersion ` json:",omitempty" alias:"tls_max_version" `
// Define a subset of cipher suites to restrict
// Only applicable to connections negotiated via TLS 1.2 or earlier
CipherSuites [ ] types . TLSCipherSuite ` json:",omitempty" alias:"cipher_suites" `
}
2022-05-02 16:35:34 +00:00
type MeshHTTPConfig struct {
SanitizeXForwardedClientCert bool ` alias:"sanitize_x_forwarded_client_cert" `
}
2022-09-02 20:52:11 +00:00
// PeeringMeshConfig contains cluster-wide options pertaining to peering.
type PeeringMeshConfig struct {
// PeerThroughMeshGateways determines whether peering traffic between
// control planes should flow through mesh gateways. If enabled,
// Consul servers will advertise mesh gateway addresses as their own.
// Additionally, mesh gateways will configure themselves to expose
// the local servers using a peering-specific SNI.
PeerThroughMeshGateways bool ` alias:"peer_through_mesh_gateways" `
}
2021-04-28 22:13:29 +00:00
func ( e * MeshConfigEntry ) GetKind ( ) string {
return MeshConfig
2021-04-06 18:19:59 +00:00
}
2021-04-28 22:13:29 +00:00
func ( e * MeshConfigEntry ) GetName ( ) string {
2021-04-06 18:19:59 +00:00
if e == nil {
return ""
}
2021-04-29 19:54:27 +00:00
return MeshConfigMesh
2021-04-06 18:19:59 +00:00
}
2021-04-28 22:13:29 +00:00
func ( e * MeshConfigEntry ) GetMeta ( ) map [ string ] string {
2021-04-06 18:19:59 +00:00
if e == nil {
return nil
}
return e . Meta
}
2021-04-28 22:13:29 +00:00
func ( e * MeshConfigEntry ) Normalize ( ) error {
2021-04-06 18:19:59 +00:00
if e == nil {
return fmt . Errorf ( "config entry is nil" )
}
e . EnterpriseMeta . Normalize ( )
2023-12-12 13:29:13 +00:00
h , err := HashConfigEntry ( e )
if err != nil {
return err
}
e . Hash = h
2021-04-06 18:19:59 +00:00
return nil
}
2021-04-28 22:13:29 +00:00
func ( e * MeshConfigEntry ) Validate ( ) error {
2021-04-06 18:19:59 +00:00
if e == nil {
return fmt . Errorf ( "config entry is nil" )
}
2022-03-30 18:43:59 +00:00
2021-04-06 18:19:59 +00:00
if err := validateConfigEntryMeta ( e . Meta ) ; err != nil {
return err
}
2022-03-30 18:43:59 +00:00
if e . TLS != nil {
if e . TLS . Incoming != nil {
if err := validateMeshDirectionalTLSConfig ( e . TLS . Incoming ) ; err != nil {
return fmt . Errorf ( "error in incoming TLS configuration: %v" , err )
}
}
if e . TLS . Outgoing != nil {
if err := validateMeshDirectionalTLSConfig ( e . TLS . Outgoing ) ; err != nil {
return fmt . Errorf ( "error in outgoing TLS configuration: %v" , err )
}
}
}
2021-04-06 18:19:59 +00:00
return e . validateEnterpriseMeta ( )
}
2022-03-11 21:45:51 +00:00
func ( e * MeshConfigEntry ) CanRead ( authz acl . Authorizer ) error {
return nil
2021-04-06 18:19:59 +00:00
}
2022-03-11 21:45:51 +00:00
func ( e * MeshConfigEntry ) CanWrite ( authz acl . Authorizer ) error {
2021-04-06 18:19:59 +00:00
var authzContext acl . AuthorizerContext
e . FillAuthzContext ( & authzContext )
2022-03-11 21:45:51 +00:00
return authz . ToAllowAuthorizer ( ) . MeshWriteAllowed ( & authzContext )
2021-04-06 18:19:59 +00:00
}
2021-04-28 22:13:29 +00:00
func ( e * MeshConfigEntry ) GetRaftIndex ( ) * RaftIndex {
2021-04-06 18:19:59 +00:00
if e == nil {
return & RaftIndex { }
}
return & e . RaftIndex
}
2022-03-13 03:55:53 +00:00
func ( e * MeshConfigEntry ) GetEnterpriseMeta ( ) * acl . EnterpriseMeta {
2021-04-06 18:19:59 +00:00
if e == nil {
return nil
}
return & e . EnterpriseMeta
}
2021-04-29 21:44:32 +00:00
// MarshalJSON adds the Kind field so that the JSON can be decoded back into the
// correct type.
// This method is implemented on the structs type (as apposed to the api type)
// because that is what the API currently uses to return a response.
func ( e * MeshConfigEntry ) MarshalJSON ( ) ( [ ] byte , error ) {
type Alias MeshConfigEntry
source := & struct {
Kind string
* Alias
} {
Kind : MeshConfig ,
Alias : ( * Alias ) ( e ) ,
}
return json . Marshal ( source )
}
2022-03-30 18:43:59 +00:00
2022-09-23 03:14:25 +00:00
func ( e * MeshConfigEntry ) PeerThroughMeshGateways ( ) bool {
if e == nil || e . Peering == nil {
return false
}
return e . Peering . PeerThroughMeshGateways
}
2022-03-30 18:43:59 +00:00
func validateMeshDirectionalTLSConfig ( cfg * MeshDirectionalTLSConfig ) error {
if cfg == nil {
return nil
}
return validateTLSConfig ( cfg . TLSMinVersion , cfg . TLSMaxVersion , cfg . CipherSuites )
}
func validateTLSConfig (
tlsMinVersion types . TLSVersion ,
tlsMaxVersion types . TLSVersion ,
cipherSuites [ ] types . TLSCipherSuite ,
) error {
if tlsMinVersion != types . TLSVersionUnspecified {
if err := types . ValidateTLSVersion ( tlsMinVersion ) ; err != nil {
return err
}
}
if tlsMaxVersion != types . TLSVersionUnspecified {
if err := types . ValidateTLSVersion ( tlsMaxVersion ) ; err != nil {
return err
}
if tlsMinVersion != types . TLSVersionUnspecified {
if err , maxLessThanMin := tlsMaxVersion . LessThan ( tlsMinVersion ) ; err == nil && maxLessThanMin {
return fmt . Errorf ( "configuring max version %s less than the configured min version %s is invalid" , tlsMaxVersion , tlsMinVersion )
}
}
}
if len ( cipherSuites ) != 0 {
if _ , ok := types . TLSVersionsWithConfigurableCipherSuites [ tlsMinVersion ] ; ! ok {
return fmt . Errorf ( "configuring CipherSuites is only applicable to connections negotiated with TLS 1.2 or earlier, TLSMinVersion is set to %s" , tlsMinVersion )
}
// NOTE: it would be nice to emit a warning but not return an error from
// here if TLSMaxVersion is unspecified, TLS_AUTO or TLSv1_3
if err := types . ValidateEnvoyCipherSuites ( cipherSuites ) ; err != nil {
return err
}
}
return nil
}