mirror of https://github.com/hashicorp/consul
[NET-1151 NET-11228] api: Add fields for HTTP request normalization and L7 intentions header additions (1.15) (#21842)
api: Add fields for HTTP request normalization and L7 intentions header additions This feature is available in Consul CE 1.20.1 and Consul Enterprise 1.19.3, 1.18.4, and 1.15.15.pull/21858/head
parent
619c288023
commit
400c6a8bdc
|
@ -60,11 +60,13 @@ type IntentionHTTPPermission struct {
|
|||
}
|
||||
|
||||
type IntentionHTTPHeaderPermission struct {
|
||||
Name string
|
||||
Present bool `json:",omitempty"`
|
||||
Exact string `json:",omitempty"`
|
||||
Prefix string `json:",omitempty"`
|
||||
Suffix string `json:",omitempty"`
|
||||
Regex string `json:",omitempty"`
|
||||
Invert bool `json:",omitempty"`
|
||||
Name string
|
||||
Present bool `json:",omitempty"`
|
||||
Exact string `json:",omitempty"`
|
||||
Prefix string `json:",omitempty"`
|
||||
Suffix string `json:",omitempty"`
|
||||
Contains string `json:",omitempty"`
|
||||
Regex string `json:",omitempty"`
|
||||
Invert bool `json:",omitempty"`
|
||||
IgnoreCase bool `json:",omitempty" alias:"ignore_case"`
|
||||
}
|
||||
|
|
|
@ -65,12 +65,53 @@ type MeshDirectionalTLSConfig struct {
|
|||
|
||||
type MeshHTTPConfig struct {
|
||||
SanitizeXForwardedClientCert bool `alias:"sanitize_x_forwarded_client_cert"`
|
||||
// Incoming configures settings for incoming HTTP traffic to mesh proxies.
|
||||
Incoming *MeshDirectionalHTTPConfig `json:",omitempty"`
|
||||
}
|
||||
|
||||
// MeshDirectionalHTTPConfig holds mesh configuration specific to HTTP
|
||||
// requests for a given traffic direction.
|
||||
type MeshDirectionalHTTPConfig struct {
|
||||
RequestNormalization *RequestNormalizationMeshConfig `json:",omitempty" alias:"request_normalization"`
|
||||
}
|
||||
|
||||
type PeeringMeshConfig struct {
|
||||
PeerThroughMeshGateways bool `json:",omitempty" alias:"peer_through_mesh_gateways"`
|
||||
}
|
||||
|
||||
// RequestNormalizationMeshConfig contains options pertaining to the
|
||||
// normalization of HTTP requests processed by mesh proxies.
|
||||
type RequestNormalizationMeshConfig struct {
|
||||
// InsecureDisablePathNormalization sets the value of the \`normalize_path\` option in the Envoy listener's
|
||||
// `HttpConnectionManager`. The default value is \`false\`. When set to \`true\` in Consul, \`normalize_path\` is
|
||||
// set to \`false\` for the Envoy proxy. This parameter disables the normalization of request URL paths according to
|
||||
// RFC 3986, conversion of \`\\\` to \`/\`, and decoding non-reserved %-encoded characters. When using L7 intentions
|
||||
// with path match rules, we recommend enabling path normalization in order to avoid match rule circumvention with
|
||||
// non-normalized path values.
|
||||
InsecureDisablePathNormalization bool `json:",omitempty" alias:"insecure_disable_path_normalization"`
|
||||
// MergeSlashes sets the value of the \`merge_slashes\` option in the Envoy listener's \`HttpConnectionManager\`.
|
||||
// The default value is \`false\`. This option controls the normalization of request URL paths by merging
|
||||
// consecutive \`/\` characters. This normalization is not part of RFC 3986. When using L7 intentions with path
|
||||
// match rules, we recommend enabling this setting to avoid match rule circumvention through non-normalized path
|
||||
// values, unless legitimate service traffic depends on allowing for repeat \`/\` characters, or upstream services
|
||||
// are configured to differentiate between single and multiple slashes.
|
||||
MergeSlashes bool `json:",omitempty" alias:"merge_slashes"`
|
||||
// PathWithEscapedSlashesAction sets the value of the \`path_with_escaped_slashes_action\` option in the Envoy
|
||||
// listener's \`HttpConnectionManager\`. The default value of this option is empty, which is equivalent to
|
||||
// \`IMPLEMENTATION_SPECIFIC_DEFAULT\`. This parameter controls the action taken in response to request URL paths
|
||||
// with escaped slashes in the path. When using L7 intentions with path match rules, we recommend enabling this
|
||||
// setting to avoid match rule circumvention through non-normalized path values, unless legitimate service traffic
|
||||
// depends on allowing for escaped \`/\` or \`\\\` characters, or upstream services are configured to differentiate
|
||||
// between escaped and unescaped slashes. Refer to the Envoy documentation for more information on available
|
||||
// options.
|
||||
PathWithEscapedSlashesAction string `json:",omitempty" alias:"path_with_escaped_slashes_action"`
|
||||
// HeadersWithUnderscoresAction sets the value of the \`headers_with_underscores_action\` option in the Envoy
|
||||
// listener's \`HttpConnectionManager\` under \`common_http_protocol_options\`. The default value of this option is
|
||||
// empty, which is equivalent to \`ALLOW\`. Refer to the Envoy documentation for more information on available
|
||||
// options.
|
||||
HeadersWithUnderscoresAction string `json:",omitempty" alias:"headers_with_underscores_action"`
|
||||
}
|
||||
|
||||
func (e *MeshConfigEntry) GetKind() string { return MeshConfig }
|
||||
func (e *MeshConfigEntry) GetName() string { return MeshConfigMesh }
|
||||
func (e *MeshConfigEntry) GetPartition() string { return e.Partition }
|
||||
|
|
|
@ -2305,6 +2305,10 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
name = "hdr-suffix"
|
||||
suffix = "suffix"
|
||||
},
|
||||
{
|
||||
name = "hdr-contains"
|
||||
contains = "contains"
|
||||
},
|
||||
{
|
||||
name = "hdr-regex"
|
||||
regex = "regex"
|
||||
|
@ -2313,7 +2317,12 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
name = "hdr-absent"
|
||||
present = true
|
||||
invert = true
|
||||
}
|
||||
},
|
||||
{
|
||||
name = "hdr-ignore-case"
|
||||
exact = "exact"
|
||||
ignore_case = true
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
|
@ -2382,6 +2391,10 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
Name = "hdr-suffix"
|
||||
Suffix = "suffix"
|
||||
},
|
||||
{
|
||||
Name = "hdr-contains"
|
||||
Contains = "contains"
|
||||
},
|
||||
{
|
||||
Name = "hdr-regex"
|
||||
Regex = "regex"
|
||||
|
@ -2390,6 +2403,11 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
Name = "hdr-absent"
|
||||
Present = true
|
||||
Invert = true
|
||||
},
|
||||
{
|
||||
Name = "hdr-ignore-case"
|
||||
Exact = "exact"
|
||||
IgnoreCase = true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -2460,6 +2478,10 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
"name": "hdr-suffix",
|
||||
"suffix": "suffix"
|
||||
},
|
||||
{
|
||||
"name": "hdr-contains",
|
||||
"contains": "contains"
|
||||
},
|
||||
{
|
||||
"name": "hdr-regex",
|
||||
"regex": "regex"
|
||||
|
@ -2468,6 +2490,11 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
"name": "hdr-absent",
|
||||
"present": true,
|
||||
"invert": true
|
||||
},
|
||||
{
|
||||
"name": "hdr-ignore-case",
|
||||
"exact": "exact",
|
||||
"ignore_case": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -2542,6 +2569,10 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
"Name": "hdr-suffix",
|
||||
"Suffix": "suffix"
|
||||
},
|
||||
{
|
||||
"Name": "hdr-contains",
|
||||
"Contains": "contains"
|
||||
},
|
||||
{
|
||||
"Name": "hdr-regex",
|
||||
"Regex": "regex"
|
||||
|
@ -2550,6 +2581,11 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
"Name": "hdr-absent",
|
||||
"Present": true,
|
||||
"Invert": true
|
||||
},
|
||||
{
|
||||
"Name": "hdr-ignore-case",
|
||||
"Exact": "exact",
|
||||
"IgnoreCase": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -2623,6 +2659,10 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
Name: "hdr-suffix",
|
||||
Suffix: "suffix",
|
||||
},
|
||||
{
|
||||
Name: "hdr-contains",
|
||||
Contains: "contains",
|
||||
},
|
||||
{
|
||||
Name: "hdr-regex",
|
||||
Regex: "regex",
|
||||
|
@ -2632,6 +2672,11 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
Present: true,
|
||||
Invert: true,
|
||||
},
|
||||
{
|
||||
Name: "hdr-ignore-case",
|
||||
Exact: "exact",
|
||||
IgnoreCase: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2719,7 +2764,7 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "mesh",
|
||||
name: "mesh: kitchen sink",
|
||||
snake: `
|
||||
kind = "mesh"
|
||||
meta {
|
||||
|
@ -2729,6 +2774,7 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
transparent_proxy {
|
||||
mesh_destinations_only = true
|
||||
}
|
||||
validate_clusters = true
|
||||
tls {
|
||||
incoming {
|
||||
tls_min_version = "TLSv1_1"
|
||||
|
@ -2747,6 +2793,20 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
]
|
||||
}
|
||||
}
|
||||
http {
|
||||
sanitize_x_forwarded_client_cert = true
|
||||
incoming {
|
||||
request_normalization {
|
||||
insecure_disable_path_normalization = true
|
||||
merge_slashes = true
|
||||
path_with_escaped_slashes_action = "UNESCAPE_AND_FORWARD"
|
||||
headers_with_underscores_action = "DROP_HEADER"
|
||||
}
|
||||
}
|
||||
}
|
||||
peering {
|
||||
peer_through_mesh_gateways = true
|
||||
}
|
||||
`,
|
||||
camel: `
|
||||
Kind = "mesh"
|
||||
|
@ -2757,6 +2817,7 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
TransparentProxy {
|
||||
MeshDestinationsOnly = true
|
||||
}
|
||||
ValidateClusters = true
|
||||
TLS {
|
||||
Incoming {
|
||||
TLSMinVersion = "TLSv1_1"
|
||||
|
@ -2775,6 +2836,20 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
]
|
||||
}
|
||||
}
|
||||
HTTP {
|
||||
SanitizeXForwardedClientCert = true
|
||||
Incoming {
|
||||
RequestNormalization {
|
||||
InsecureDisablePathNormalization = true
|
||||
MergeSlashes = true
|
||||
PathWithEscapedSlashesAction = "UNESCAPE_AND_FORWARD"
|
||||
HeadersWithUnderscoresAction = "DROP_HEADER"
|
||||
}
|
||||
}
|
||||
}
|
||||
Peering {
|
||||
PeerThroughMeshGateways = true
|
||||
}
|
||||
`,
|
||||
snakeJSON: `
|
||||
{
|
||||
|
@ -2786,6 +2861,7 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
"transparent_proxy": {
|
||||
"mesh_destinations_only": true
|
||||
},
|
||||
"validate_clusters": true,
|
||||
"tls": {
|
||||
"incoming": {
|
||||
"tls_min_version": "TLSv1_1",
|
||||
|
@ -2803,6 +2879,20 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
|
||||
]
|
||||
}
|
||||
},
|
||||
"http": {
|
||||
"sanitize_x_forwarded_client_cert": true,
|
||||
"incoming": {
|
||||
"request_normalization": {
|
||||
"insecure_disable_path_normalization": true,
|
||||
"merge_slashes": true,
|
||||
"path_with_escaped_slashes_action": "UNESCAPE_AND_FORWARD",
|
||||
"headers_with_underscores_action": "DROP_HEADER"
|
||||
}
|
||||
}
|
||||
},
|
||||
"peering": {
|
||||
"peer_through_mesh_gateways": true
|
||||
}
|
||||
}
|
||||
`,
|
||||
|
@ -2816,6 +2906,7 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
"TransparentProxy": {
|
||||
"MeshDestinationsOnly": true
|
||||
},
|
||||
"ValidateClusters": true,
|
||||
"TLS": {
|
||||
"Incoming": {
|
||||
"TLSMinVersion": "TLSv1_1",
|
||||
|
@ -2833,6 +2924,20 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
|
||||
]
|
||||
}
|
||||
},
|
||||
"HTTP": {
|
||||
"SanitizeXForwardedClientCert": true,
|
||||
"Incoming": {
|
||||
"RequestNormalization": {
|
||||
"InsecureDisablePathNormalization": true,
|
||||
"MergeSlashes": true,
|
||||
"PathWithEscapedSlashesAction": "UNESCAPE_AND_FORWARD",
|
||||
"HeadersWithUnderscoresAction": "DROP_HEADER"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Peering": {
|
||||
"PeerThroughMeshGateways": true
|
||||
}
|
||||
}
|
||||
`,
|
||||
|
@ -2844,6 +2949,7 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
TransparentProxy: api.TransparentProxyMeshConfig{
|
||||
MeshDestinationsOnly: true,
|
||||
},
|
||||
ValidateClusters: true,
|
||||
TLS: &api.MeshTLSConfig{
|
||||
Incoming: &api.MeshDirectionalTLSConfig{
|
||||
TLSMinVersion: "TLSv1_1",
|
||||
|
@ -2862,6 +2968,20 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
HTTP: &api.MeshHTTPConfig{
|
||||
SanitizeXForwardedClientCert: true,
|
||||
Incoming: &api.MeshDirectionalHTTPConfig{
|
||||
RequestNormalization: &api.RequestNormalizationMeshConfig{
|
||||
InsecureDisablePathNormalization: true,
|
||||
MergeSlashes: true,
|
||||
PathWithEscapedSlashesAction: "UNESCAPE_AND_FORWARD",
|
||||
HeadersWithUnderscoresAction: "DROP_HEADER",
|
||||
},
|
||||
},
|
||||
},
|
||||
Peering: &api.PeeringMeshConfig{
|
||||
PeerThroughMeshGateways: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue