forked from hashicorp/consul
/
config_entry_mesh.go
215 lines (175 loc) · 5.87 KB
/
config_entry_mesh.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package structs
import (
"encoding/json"
"fmt"
"github.com/hernad/consul/acl"
"github.com/hernad/consul/types"
)
type MeshConfigEntry struct {
// TransparentProxy contains cluster-wide options pertaining to TPROXY mode
// when enabled.
TransparentProxy TransparentProxyMeshConfig `alias:"transparent_proxy"`
// 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"`
TLS *MeshTLSConfig `json:",omitempty"`
HTTP *MeshHTTPConfig `json:",omitempty"`
Peering *PeeringMeshConfig `json:",omitempty"`
Meta map[string]string `json:",omitempty"`
acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"`
RaftIndex
}
// TransparentProxyMeshConfig contains cluster-wide options pertaining to
// TPROXY mode when enabled.
type TransparentProxyMeshConfig struct {
// MeshDestinationsOnly can be used to disable the pass-through that
// allows traffic to destinations outside of the mesh.
MeshDestinationsOnly bool `alias:"mesh_destinations_only"`
}
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"`
}
type MeshHTTPConfig struct {
SanitizeXForwardedClientCert bool `alias:"sanitize_x_forwarded_client_cert"`
}
// 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"`
}
func (e *MeshConfigEntry) GetKind() string {
return MeshConfig
}
func (e *MeshConfigEntry) GetName() string {
if e == nil {
return ""
}
return MeshConfigMesh
}
func (e *MeshConfigEntry) GetMeta() map[string]string {
if e == nil {
return nil
}
return e.Meta
}
func (e *MeshConfigEntry) Normalize() error {
if e == nil {
return fmt.Errorf("config entry is nil")
}
e.EnterpriseMeta.Normalize()
return nil
}
func (e *MeshConfigEntry) Validate() error {
if e == nil {
return fmt.Errorf("config entry is nil")
}
if err := validateConfigEntryMeta(e.Meta); err != nil {
return err
}
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)
}
}
}
return e.validateEnterpriseMeta()
}
func (e *MeshConfigEntry) CanRead(authz acl.Authorizer) error {
return nil
}
func (e *MeshConfigEntry) CanWrite(authz acl.Authorizer) error {
var authzContext acl.AuthorizerContext
e.FillAuthzContext(&authzContext)
return authz.ToAllowAuthorizer().MeshWriteAllowed(&authzContext)
}
func (e *MeshConfigEntry) GetRaftIndex() *RaftIndex {
if e == nil {
return &RaftIndex{}
}
return &e.RaftIndex
}
func (e *MeshConfigEntry) GetEnterpriseMeta() *acl.EnterpriseMeta {
if e == nil {
return nil
}
return &e.EnterpriseMeta
}
// 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)
}
func (e *MeshConfigEntry) PeerThroughMeshGateways() bool {
if e == nil || e.Peering == nil {
return false
}
return e.Peering.PeerThroughMeshGateways
}
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
}