diff --git a/website/content/docs/connect/config-entries/mesh.mdx b/website/content/docs/connect/config-entries/mesh.mdx
index f83c129805..533cca6841 100644
--- a/website/content/docs/connect/config-entries/mesh.mdx
+++ b/website/content/docs/connect/config-entries/mesh.mdx
@@ -264,6 +264,60 @@ spec:
Note that the Kubernetes example does not include a `partition` field. Configuration entries are applied on Kubernetes using [custom resource definitions (CRD)](/consul/docs/k8s/crds), which can only be scoped to their own partition.
+### Request Normalization
+
+Enable options under `HTTP.Incoming.RequestNormalization` to apply normalization to all inbound traffic to mesh proxies.
+
+~> **Compatibility warning**: This feature is available as of Consul CE 1.20.1 and Consul Enterprise 1.20.1, 1.19.2, 1.18.3, and 1.15.15. We recommend upgrading to the latest version of Consul to take advantage of the latest features and improvements.
+
+
+
+```hcl
+Kind = "mesh"
+HTTP {
+ Incoming {
+ RequestNormalization {
+ InsecureDisablePathNormalization = false // default false, shown for completeness
+ MergeSlashes = true
+ PathWithEscapedSlashesAction = "UNESCAPE_AND_FORWARD"
+ HeadersWithUnderscoresAction = "REJECT_REQUEST"
+ }
+ }
+}
+```
+
+```yaml
+apiVersion: consul.hashicorp.com/v1alpha1
+kind: Mesh
+metadata:
+ name: mesh
+spec:
+ http:
+ incoming:
+ requestNormalization:
+ insecureDisablePathNormalization: false # default false, shown for completeness
+ mergeSlashes: true
+ pathWithEscapedSlashesAction: UNESCAPE_AND_FORWARD
+ headersWithUnderscoresAction: REJECT_REQUEST
+```
+
+```json
+{
+ "Kind": "mesh",
+ "HTTP": {
+ "Incoming": {
+ "RequestNormalization": {
+ "InsecureDisablePathNormalization": false,
+ "MergeSlashes": true,
+ "PathWithEscapedSlashesAction": "UNESCAPE_AND_FORWARD",
+ "HeadersWithUnderscoresAction": "REJECT_REQUEST"
+ }
+ }
+ }
+}
+```
+
+
## Available Fields
@@ -435,6 +489,57 @@ Note that the Kubernetes example does not include a `partition` field. Configura
for all Envoy proxies. As a result, Consul will not include the \`x-forwarded-client-cert\` header in the next hop.
If set to \`false\` (default), the XFCC header is propagated to upstream applications.`,
},
+ {
+ name: 'Incoming',
+ type: 'DirectionalHTTPConfig: ',
+ description: `HTTP configuration for inbound traffic to mesh proxies.`,
+ children: [
+ {
+ name: 'RequestNormalization',
+ type: 'RequestNormalizationConfig: ',
+ description: `Request normalization configuration for inbound traffic to mesh proxies.`,
+ children: [
+ {
+ name: 'InsecureDisablePathNormalization',
+ type: 'bool: false',
+ description: `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.`,
+ },
+ {
+ name: 'MergeSlashes',
+ type: 'bool: false',
+ description: `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.`,
+ },
+ {
+ name: 'PathWithEscapedSlashesAction',
+ type: 'string: ""',
+ description: `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.`,
+ },
+ {
+ name: 'HeadersWithUnderscoresAction',
+ type: 'string: ""',
+ description: `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.`,
+ },
+ ],
+ },
+ ],
+ }
],
},
{
diff --git a/website/content/docs/connect/config-entries/service-intentions.mdx b/website/content/docs/connect/config-entries/service-intentions.mdx
index 321b7f1605..5995e1e406 100644
--- a/website/content/docs/connect/config-entries/service-intentions.mdx
+++ b/website/content/docs/connect/config-entries/service-intentions.mdx
@@ -18,10 +18,10 @@ The following outline shows how to format the service intentions configuration e
- [`Kind`](#kind): string | required | must be set to `service-intentions`
-- [`Name`](#name): string | required
+- [`Name`](#name): string | required
- [`Namespace`](#namespace): string | `default` |
- [`Partition`](#partition): string | `default` |
-- [`Meta`](#meta): map | no default
+- [`Meta`](#meta): map | no default
- [`Sources`](#sources): list | no default
- [`Name`](#sources-name): string | no default
- [`Peer`](#sources-peer): string | no default
@@ -31,23 +31,25 @@ The following outline shows how to format the service intentions configuration e
- [`Permissions`](#sources-permissions): list | no default
- [`Action`](#sources-permissions-action): string | no default | required
- [`HTTP`](#sources-permissions-http): map | required
- - [`PathExact`](#sources-permissions-http): string | no default
- - [`PathPrefix`](#sources-permissions-http): string | no default
- - [`PathRegex`](#sources-permissions-http): string | no default
- - [`Methods`](#sources-permissions-http): list | no default
- - [`Header`](#sources-permissions-http-header): list of maps |no default
+ - [`PathExact`](#sources-permissions-http): string | no default
+ - [`PathPrefix`](#sources-permissions-http): string | no default
+ - [`PathRegex`](#sources-permissions-http): string | no default
+ - [`Methods`](#sources-permissions-http): list | no default
+ - [`Header`](#sources-permissions-http-header): list of maps |no default
- [`Name`](#sources-permissions-http-header): string | required
- - [`Present`](#sources-permissions-http-header): boolean | `false`
+ - [`Present`](#sources-permissions-http-header): boolean | `false`
- [`Exact`](#sources-permissions-http-header): string | no default
- [`Prefix`](#sources-permissions-http-header): string | no default
- [`Suffix`](#sources-permissions-http-header): string | no default
- - [`Regex`](#sources-permissions-http-header): string | no default
- - [`Invert`](#sources-permissions-http-header): boolean | `false`
- - [`Precedence`](#sources-precedence): number | no default | _read-only_
- - [`Type`](#sources-type): string | `consul`
- - [`Description`](#sources-description): string
- - [`LegacyID`](#sources-legacyid): string | no default | _read-only_
- - [`LegacyMeta`](#sources-legacymeta): map | no default | _read-only_
+ - [`Contains`](#spec-sources-permissions-http-header): string | no default
+ - [`Regex`](#spec-sources-permissions-http-header): string | no default
+ - [`IgnoreCase`](#spec-sources-permissions-http-header): boolean | `false`
+ - [`Invert`](#sources-permissions-http-header): boolean | `false`
+ - [`Precedence`](#sources-precedence): number | no default | _read-only_
+ - [`Type`](#sources-type): string | `consul`
+ - [`Description`](#sources-description): string
+ - [`LegacyID`](#sources-legacyid): string | no default | _read-only_
+ - [`LegacyMeta`](#sources-legacymeta): map | no default | _read-only_
- [`LegacyCreateTime`](#sources-legacycreatetime): string | no default | _read-only_
- [`LegacyUpdateTime`](#sources-legacyupdatetime): string | no default | _read-only_
@@ -55,11 +57,11 @@ The following outline shows how to format the service intentions configuration e
- [`apiVersion`](#apiversion): string | must be set to `consul.hashicorp.com/v1alpha1`
-- [`kind`](#kind): string | must be set to `ServiceIntentions`
-- [`metadata`](#metadata): map | required
- - [`name`](#metadata-name): string | required
+- [`kind`](#kind): string | must be set to `ServiceIntentions`
+- [`metadata`](#metadata): map | required
+ - [`name`](#metadata-name): string | required
- [`namespace`](#metadata-namespace): string | `default` |
-- [`spec`](#spec): map | no default
+- [`spec`](#spec): map | no default
- [`destination`](#spec-destination): map | no default
- [`name`](#spec-destination-name): string | required
- [`namespace`](#metadata-namespace): string | `default` |
@@ -72,20 +74,22 @@ The following outline shows how to format the service intentions configuration e
- [`permissions`](#spec-sources-permissions): list | no default
- [`action`](#spec-sources-permissions-action): string | no default | required
- [`http`](#spec-sources-permissions-http): map | required
- - [`pathExact`](#spec-sources-permissions-http): string | no default
- - [`pathPrefix`](#spec-sources-permissions-http): string | no default
- - [`pathRegex`](#spec-sources-permissions-http): string | no default
- - [`methods`](#spec-sources-permissions-http): list | no default
- - [`header`](#spec-sources-permissions-http-header): list of maps |no default
+ - [`pathExact`](#spec-sources-permissions-http): string | no default
+ - [`pathPrefix`](#spec-sources-permissions-http): string | no default
+ - [`pathRegex`](#spec-sources-permissions-http): string | no default
+ - [`methods`](#spec-sources-permissions-http): list | no default
+ - [`header`](#spec-sources-permissions-http-header): list of maps |no default
- [`name`](#spec-sources-permissions-http-header): string | required
- - [`present`](#spec-sources-permissions-http-header): boolean | `false`
+ - [`present`](#spec-sources-permissions-http-header): boolean | `false`
- [`exact`](#spec-sources-permissions-http-header): string | no default
- [`prefix`](#spec-sources-permissions-http-header): string | no default
- [`suffix`](#spec-sources-permissions-http-header): string | no default
+ - [`contains`](#spec-sources-permissions-http-header): string | no default
- [`regex`](#spec-sources-permissions-http-header): string | no default
- - [`invert`](#spec-sources-permissions-http-header): boolean | `false`
- - [`type`](#spec-sources-type): string | `consul`
- - [`description`](#spec-sources-description): string
+ - [`ignoreCase`](#spec-sources-permissions-http-header): boolean | `false`
+ - [`invert`](#spec-sources-permissions-http-header): boolean | `false`
+ - [`type`](#spec-sources-type): string | `consul`
+ - [`description`](#spec-sources-description): string
@@ -100,13 +104,13 @@ When every field is defined, a service intentions configuration entry has the fo
```hcl
Kind = "service-intentions"
-Name = ""
+Name = ""
Namespace = "" # string
Partition = "" # string
Meta = {
- "" = ""
- "" = ""
- }
+ "" = ""
+ "" = ""
+ }
Sources = [
{
Name = "" # string
@@ -114,14 +118,14 @@ Sources = [
Namespace = "" # string
Partition = "" # string
Action = "allow" or "deny" # string for L4 intentions
- Permissions = [
- {
- Action = "allow" or "deny" # string for L7 intenions
- HTTP = {
- PathExact = "" # string
- PathPrefix = "" # string
- PathRegex = "" # string
- Methods = [
+ Permissions = [
+ {
+ Action = "allow" or "deny" # string for L7 intentions
+ HTTP = {
+ PathExact = "" # string
+ PathPrefix = "" # string
+ PathRegex = "" # string
+ Methods = [
"", # string
""
]
@@ -129,35 +133,48 @@ Sources = [
{
Name = "" # string
Present = # boolean
+ Invert = # boolean
},
{
Name = "" # string
Exact = "" # boolean
+ IgnoreCase = # boolean
+ Invert = # boolean
},
{
Name = "" # string
Prefix = "" # string
+ IgnoreCase = # boolean
+ Invert = # boolean
},
{
Name = "" # string
Suffix = "" # string
+ IgnoreCase = # boolean
+ Invert = # boolean
+ },
+ {
+ Name = "" # string
+ Contains = "" # string
+ IgnoreCase = # boolean
+ Invert = # boolean
},
{
Name = "" # string
Regex = "" # string
Invert = # boolean
}
- ]
+ ]
}
- }
+ }
]
- Type = "consul" # string
- Description = "" # string
+ Type = "consul" # string
+ Description = "" # string
Precedence = # number
- LegacyID = # string
+ LegacyID = # string
LegacyMeta = # string
LegacyCreateTime = # string
- LegacyUpdateTime = # string
+ LegacyUpdateTime = # string
}
]
```
@@ -173,7 +190,7 @@ metadata:
namespace:
spec:
destination:
- destination:
+ destination:
name:
namespace:
sources:
@@ -194,12 +211,23 @@ spec:
header:
- name:
present: true
+ invert: false
- name:
- exact: false
+ exact:
+ ignoreCase: false
+ invert: false
- name:
prefix:
+ ignoreCase: false
+ invert: false
- name:
suffix:
+ ignoreCase: false
+ invert: false
+ - name:
+ contains:
+ ignoreCase: false
+ invert: false
- name:
regex:
invert: false
@@ -241,19 +269,32 @@ spec:
"Header":[
{
"Name":"",
- "Present":true
+ "Present":true,
+ "Invert":false
},
{
"Name":"",
- "Exact":false
+ "Exact":"",
+ "IgnoreCase":false,,
+ "Invert":false
},
{
"Name":"",
- "Prefix":""
+ "Prefix":"",
+ "IgnoreCase":false,
+ "Invert":false
},
{
"Name":"",
- "Suffix":""
+ "Suffix":"",
+ "IgnoreCase":false,
+ "Invert":false
+ },
+ {
+ "Name":"",
+ "Contains":"",
+ "IgnoreCase":false,
+ "Invert":false
},
{
"Name":"",
@@ -300,7 +341,7 @@ Specifies the type of configuration entry to implement. Must be set to `service-
### `Name`
-Specifies a name of the destination service for all intentions defined in the configuration entry.
+Specifies a name of the destination service for all intentions defined in the configuration entry.
#### Values
@@ -308,22 +349,22 @@ Specifies a name of the destination service for all intentions defined in the co
- This field is required.
- Data type: String
-You can also specify a wildcard character (`*`) to match all services without intentions. Intentions that are applied with a wildcard, however, are not supported when defining L7 [`Permissions`](#sources-permissions).
+You can also specify a wildcard character (`*`) to match all services without intentions. Intentions that are applied with a wildcard, however, are not supported when defining L7 [`Permissions`](#sources-permissions).
-### `Namespace`
+### `Namespace`
-Specifies the [namespace](/consul/docs/enterprise/namespaces) that the configuration entry applies to. Services in the namespace are the traffic destinations that the intentions allow or deny traffic to.
+Specifies the [namespace](/consul/docs/enterprise/namespaces) that the configuration entry applies to. Services in the namespace are the traffic destinations that the intentions allow or deny traffic to.
#### Values
- Default: `default`
- Data type: String
-You can also specify a wildcard character (`*`) to match all namespaces. Intentions that are applied with a wildcard, however, are not supported when defining L7 [`Permissions`](#sources-permissions).
+You can also specify a wildcard character (`*`) to match all namespaces. Intentions that are applied with a wildcard, however, are not supported when defining L7 [`Permissions`](#sources-permissions).
-### `Partition`
+### `Partition`
-Specifies the [admin partition](/consul/docs/enterprise/admin-partitions) to apply the configuration entry. Services in the specified partition are the traffic destinations that the intentions allow or deny traffic to.
+Specifies the [admin partition](/consul/docs/enterprise/admin-partitions) to apply the configuration entry. Services in the specified partition are the traffic destinations that the intentions allow or deny traffic to.
#### Values
@@ -365,7 +406,7 @@ List of configurations that define intention sources and the authorization grant
### `Sources[].Name`
-Specifies the name of the source that the intention allows or denies traffic from. If [`Type`](#sources-type) is set to `consul`, then the value refers to the name of a Consul service. The source is not required to be registered into the Consul catalog.
+Specifies the name of the source that the intention allows or denies traffic from. If [`Type`](#sources-type) is set to `consul`, then the value refers to the name of a Consul service. The source is not required to be registered into the Consul catalog.
#### Values
@@ -375,29 +416,29 @@ Specifies the name of the source that the intention allows or denies traffic fro
### `Sources[].Peer`
-Specifies the name of a peered Consul cluster that the intention allows or denies traffic from. Refer to [Cluster peering overview](/consul/docs/connect/cluster-peering) for additional information about peers.
+Specifies the name of a peered Consul cluster that the intention allows or denies traffic from. Refer to [Cluster peering overview](/consul/docs/connect/cluster-peering) for additional information about peers.
-The `Peer` and `Partition` fields are mutually exclusive.
+The `Peer` and `Partition` fields are mutually exclusive.
#### Values
- Default: None
- Data type: String
-### `Sources[].Namespace`
+### `Sources[].Namespace`
-Specifies the traffic source namespace that the intention allows or denies traffic from.
+Specifies the traffic source namespace that the intention allows or denies traffic from.
#### Values
- Default: If [`Peer`](#sources-peer) is unspecified, defaults to the destination [`Namespace`](#namespace).
- Data type: String
-### `Sources[].Partition`
+### `Sources[].Partition`
-Specifies the name of an admin partition that the intention allows or denies traffic from. Refer to [Admin Partitions](/consul/docs/enterprise/admin-partitions) for additional information about partitions.
+Specifies the name of an admin partition that the intention allows or denies traffic from. Refer to [Admin Partitions](/consul/docs/enterprise/admin-partitions) for additional information about partitions.
-The `Peer` and `Partition` fields are mutually exclusive.
+The `Peer` and `Partition` fields are mutually exclusive.
#### Values
@@ -406,12 +447,12 @@ The `Peer` and `Partition` fields are mutually exclusive.
### `Sources[].Action`
-Specifies the action to take when the source sends traffic to the destination service. The value is either `allow` or `deny`. Do not configure this field to apply L7 intentions to the same source. Configure the [`Permissions`](#sources-permissions) field instead.
+Specifies the action to take when the source sends traffic to the destination service. The value is either `allow` or `deny`. Do not configure this field to apply L7 intentions to the same source. Configure the [`Permissions`](#sources-permissions) field instead.
#### Values
- Default: None
-- This field is required for L4 intentions.
+- This field is required for L4 intentions.
- Data type: String value set to either `allow` or `deny`
Refer to the following examples for additional guidance:
@@ -423,13 +464,13 @@ Refer to the following examples for additional guidance:
### `Sources[].Permissions[]`
-Specifies a list of permissions for L7 traffic sources. The list contains one or more actions and a set of match criteria for each action.
+Specifies a list of permissions for L7 traffic sources. The list contains one or more actions and a set of match criteria for each action.
-Consul applies permissions in the order specified in the configuration. Beginning at the top of the list, Consul applies the first matching request and stops evaluating against the remaining configurations.
+Consul applies permissions in the order specified in the configuration. Beginning at the top of the list, Consul applies the first matching request and stops evaluating against the remaining configurations.
-For requests that do not match any of the defined permissions, Consul applies the intention behavior defined in the [`acl_default_policy`](/consul/docs/agent/config/config-files#acl_default_policy) configuration.
+For requests that do not match any of the defined permissions, Consul applies the intention behavior defined in the [`acl_default_policy`](/consul/docs/agent/config/config-files#acl_default_policy) configuration.
-Do not configure this field for L4 intentions. Use the [`Sources.Action`](#sources-action) parameter instead.
+Do not configure this field for L4 intentions. Use the [`Sources.Action`](#sources-action) parameter instead.
The `Permissions` only applies to services with a compatible protocol. `Permissions` are not supported when the [`Name`](#name) or [`Namespace`](#namespace) field is configured with a wildcard because service instances or services in a namespace may use different protocols.
@@ -449,12 +490,12 @@ Refer to the following examples for additional guidance:
### `Sources[].Permissions[].Action`
-Specifies the action to take when the source sends traffic to the destination service. The value is either `allow` or `deny`.
+Specifies the action to take when the source sends traffic to the destination service. The value is either `allow` or `deny`.
#### Values
- Default: None
-- This field is required.
+- This field is required.
- Data type: String value set to either `allow` or `deny`.
### `Sources[].Permissions[].HTTP`
@@ -465,7 +506,7 @@ Specifies a set of HTTP-specific match criteria. Consul applies the action defin
- Default: None
- This field is required.
-- Data type: Map
+- Data type: Map
The following table describes the parameters that the HTTP map may contain:
@@ -479,14 +520,14 @@ The following table describes the parameters that the HTTP map may contain:
### `Sources[].Permissions[].HTTP[].Header[]`
-Specifies a header name and matching criteria for HTTP request headers. The request header must match all specified criteria for the permission to apply.
+Specifies a header name and matching criteria for HTTP request headers. The request header must match all specified criteria for the permission to apply.
#### Values
- Default: None
-- Data type: list of objects
+- Data type: list of objects
-Each member of the `Header` list is a map that contains a `Name` field and at least one match criterion. The following table describes the parameters that each member of the `Header` list may contain:
+Each member of the `Header` list is a map that contains a `Name` field and at least one match criterion. The following table describes the parameters that each member of the `Header` list may contain:
| Parameter | Description | Data type | Required |
| --- | --- | --- | --- |
@@ -495,17 +536,19 @@ Each member of the `Header` list is a map that contains a `Name` field and at le
| `Exact` | Specifies a value for the header key set in the `Name` field. If the request header value matches the `Exact` value, Consul applies the permission. Do not specify `Exact` if `Present`, `Prefix`, `Suffix`, or `Regex` are configured in the same `Header` configuration. | string | optional |
| `Prefix` | Specifies a prefix value for the header key set in the `Name` field. If the request header value starts with the `Prefix` value, Consul applies the permission. Do not specify `Prefix` if `Present`, `Exact`, `Suffix`, or `Regex` are configured in the same `Header` configuration. | string | optional |
| `Suffix` | Specifies a suffix value for the header key set in the `Name` field. If the request header value ends with the `Suffix` value, Consul applies the permission. Do not specify `Suffix` if `Present`, `Exact`, `Prefix`, or `Regex` are configured in the same `Header` configuration. | string | optional |
-| `Regex` | Specifies a regular expression pattern as the value for the header key set in the `Name` field. If the request header value matches the regex, Consul applies the permission. Do not specify `Regex` if `Present`, `Exact`, `Prefix`, or `Suffix` are configured in the same `Header` configuration. The regex syntax is proxy-specific. If using Envoy, refer to the [re2 documentation](https://github.com/google/re2/wiki/Syntax) for details. | string | optional |
+| `Contains` | Specifies a contains value for the header key set in the `Name` field. If the request header value includes the `Contains` value, Consul applies the permission. Do not specify `Contains` if `Present`, `Exact`, `Prefix`, `Suffix`, or `Regex` are configured in the same `header` configuration. | string | optional |
+| `Regex` | Specifies a regular expression pattern as the value for the header key set in the `Name` field. If the request header value matches the regex, Consul applies the permission. Do not specify `Regex` if `Present`, `Exact`, `Prefix`, `Suffix`, or `Contains` are configured in the same `Header` configuration. The regex syntax is proxy-specific. If using Envoy, refer to the [re2 documentation](https://github.com/google/re2/wiki/Syntax) for details. | string | optional |
+| `IgnoreCase` | Ignores the case of the provided header value when matching with `Exact`, `Prefix`, `Suffix`, or `Contains`. Default is `false`. | boolean | optional |
| `Invert` | Inverts the matching logic configured in the `Header`. Default is `false`. | boolean | optional |
### `Sources[].Precedence`
-The `Precedence` field contains a read-only integer. Consul generates the value based on name configurations for the source and destination services. Refer to [Precedence and matching order](/consul/docs/connect/intentions/create-manage-intentions#precedence-and-matching-order) for additional information.
+The `Precedence` field contains a read-only integer. Consul generates the value based on name configurations for the source and destination services. Refer to [Precedence and matching order](/consul/docs/connect/intentions/create-manage-intentions#precedence-and-matching-order) for additional information.
### `Sources[].Type`
-Specifies the type of destination service that the configuration entry applies to. The only value supported is `consul`.
+Specifies the type of destination service that the configuration entry applies to. The only value supported is `consul`.
#### Values
@@ -514,7 +557,7 @@ Specifies the type of destination service that the configuration entry applies t
### `Sources[].Description`
-Specifies a description of the intention. Consul presents the description in API responses to assist other tools integrated into the network.
+Specifies a description of the intention. Consul presents the description in API responses to assist other tools integrated into the network.
#### Values
@@ -543,7 +586,7 @@ Read-only timestamp marking the most recent intention update. Consul exposes the
### `apiVersion`
-Specifies the version of the Consul API for integrating with Kubernetes. The value must be `consul.hashicorp.com/v1alpha1`.
+Specifies the version of the Consul API for integrating with Kubernetes. The value must be `consul.hashicorp.com/v1alpha1`.
#### Values
@@ -563,7 +606,7 @@ Specifies the type of configuration entry to implement. Must be set to `ServiceI
### `metadata`
-Map that contains an arbitrary name for the configuration entry and the namespace it applies to.
+Map that contains an arbitrary name for the configuration entry and the namespace it applies to.
#### Values
@@ -574,7 +617,7 @@ Map that contains an arbitrary name for the configuration entry and the namespac
Specifies an arbitrary name for the configuration entry. Note that in other configuration entries, the `metadata.name` field specifies the name of the service that the settings apply to. For service intentions, the service that accepts the configurations is the _destination_ and is specified in the [`spec.destination.name`](#spec-destination-name) field. Refer to the following topics for additional information:
-- [ServiceIntentions Special Case (OSS)](/consul/docs/k8s/crds#serviceintentions-special-case)
+- [ServiceIntentions Special Case (OSS)](/consul/docs/k8s/crds#serviceintentions-special-case)
- [ServiceIntentions Special Case (Enterprise)](/consul/docs/k8s/crds#serviceintentions-special-case-enterprise)
#### Values
@@ -582,7 +625,7 @@ Specifies an arbitrary name for the configuration entry. Note that in other conf
- Default: None
- Data type: String
-### `metadata.namespace`
+### `metadata.namespace`
Specifies the [namespace](/consul/docs/enterprise/namespaces) that the configuration entry applies to. Refer to [Consul Enterprise](/consul/docs/k8s/crds#consul-enterprise) for information about how Consul namespaces map to Kubernetes Namespaces. Open source Consul distributions (Consul OSS) ignore the `metadata.namespace` configuration.
@@ -598,43 +641,43 @@ Map that contains the details about the `ServiceIntentions` configuration entry.
- Default: None
- This field is required.
-- Data type: Map
+- Data type: Map
### `spec.destination`
-Map that identifies the destination name and destination namespace that source services are allowed or denied access to.
+Map that identifies the destination name and destination namespace that source services are allowed or denied access to.
#### Values
- Default: None
- This field is required.
-- Data type: Map
+- Data type: Map
### `spec.destination.name`
Specifies the name of the destination service in the mesh that the intentions apply to.
-You can also specify a wildcard character (`*`) to match all services that are missing intention settings. Intentions that are applied with a wildcard, however, are not supported when defining L7 [`permissions`](#spec-sources-permissions).
+You can also specify a wildcard character (`*`) to match all services that are missing intention settings. Intentions that are applied with a wildcard, however, are not supported when defining L7 [`permissions`](#spec-sources-permissions).
#### Values
- Default: None
- This field is required.
-- Data type: String
+- Data type: String
-### `spec.metadata.namespace`
+### `spec.metadata.namespace`
-Specifies the [namespace](/consul/docs/enterprise/namespaces) that the configuration entry applies to. You can also specify a wildcard character (`*`) to match all namespaces. Intentions that are applied with a wildcard, however, are not supported when defining L7 [`permissions`](#spec-sources-permissions).
+Specifies the [namespace](/consul/docs/enterprise/namespaces) that the configuration entry applies to. You can also specify a wildcard character (`*`) to match all namespaces. Intentions that are applied with a wildcard, however, are not supported when defining L7 [`permissions`](#spec-sources-permissions).
Refer to [Consul Enterprise](/consul/docs/k8s/crds#consul-enterprise) for information about how Consul namespaces map to Kubernetes Namespaces. Open source Consul distributions (Consul OSS) ignore the `metadata.namespace` configuration.
#### Values
-- Default: If not set, destination service namespace is inherited from the `connectInject.consulNamespaces` configuration. Refer to [ServiceIntentions Special Case (Enterprise)](/consul/docs/k8s/crds#serviceintentions-special-case-enterprise) for details.
+- Default: If not set, destination service namespace is inherited from the `connectInject.consulNamespaces` configuration. Refer to [ServiceIntentions Special Case (Enterprise)](/consul/docs/k8s/crds#serviceintentions-special-case-enterprise) for details.
- Data type: String
### `spec.sources[]`
-List of configurations that define intention sources and the authorization granted to the sources. You can specify source configurations in any order, but Consul stores and evaluates them in order of reverse precedence at runtime.
+List of configurations that define intention sources and the authorization granted to the sources. You can specify source configurations in any order, but Consul stores and evaluates them in order of reverse precedence at runtime.
#### Values
@@ -651,7 +694,7 @@ List of configurations that define intention sources and the authorization grant
### `spec.sources[].name`
-Specifies the name of the source that the intention allows or denies traffic from. If [`type`](#sources-type) is set to `consul`, then the value refers to the name of a Consul service. The source is not required to be registered into the Consul catalog.
+Specifies the name of the source that the intention allows or denies traffic from. If [`type`](#sources-type) is set to `consul`, then the value refers to the name of a Consul service. The source is not required to be registered into the Consul catalog.
#### Values
@@ -661,24 +704,24 @@ Specifies the name of the source that the intention allows or denies traffic fro
### `spec.sources[].peer`
-Specifies the name of a peered Consul cluster that the intention allows or denies traffic from. Refer to [Cluster peering overview](/consul/docs/connect/cluster-peering) for additional information about peers. The `peer` and `partition` fields are mutually exclusive.
+Specifies the name of a peered Consul cluster that the intention allows or denies traffic from. Refer to [Cluster peering overview](/consul/docs/connect/cluster-peering) for additional information about peers. The `peer` and `partition` fields are mutually exclusive.
#### Values
- Default: None
- Data type: String
-### `spec.sources[].namespace`
+### `spec.sources[].namespace`
-Specifies the traffic source namespace that the intention allows or denies traffic from.
+Specifies the traffic source namespace that the intention allows or denies traffic from.
#### Values
- Default: If [`peer`](#spec-sources-peer) is unspecified, defaults to the namespace specified in the [`spec.destination.namespace`](#spec-destination-namespace) field.
- Data type: String
-### `spec.sources[].partition`
+### `spec.sources[].partition`
-Specifies the name of an admin partition that the intention allows or denies traffic from. Refer to [Admin Partitions](/consul/docs/enterprise/admin-partitions) for additional information about partitions. The `peer` and `partition` fields are mutually exclusive.
+Specifies the name of an admin partition that the intention allows or denies traffic from. Refer to [Admin Partitions](/consul/docs/enterprise/admin-partitions) for additional information about partitions. The `peer` and `partition` fields are mutually exclusive.
#### Values
@@ -687,23 +730,23 @@ Specifies the name of an admin partition that the intention allows or denies tra
### `spec.sources[].action`
-Specifies the action to take when the source sends traffic to the destination service. The value is either `allow` or `deny`. Do not configure this field for L7 intentions. Configure the [`spec.sources.permissions`](#spec-sources-permissions) field instead.
+Specifies the action to take when the source sends traffic to the destination service. The value is either `allow` or `deny`. Do not configure this field for L7 intentions. Configure the [`spec.sources.permissions`](#spec-sources-permissions) field instead.
#### Values
- Default: None
-- This field is required for L4 intentions.
+- This field is required for L4 intentions.
- Data type: String value set to either `allow` or `deny`
### `spec.sources[].permissions[]`
-Specifies a list of permissions for L7 traffic sources. The list contains one or more actions and a set of match criteria for each action.
+Specifies a list of permissions for L7 traffic sources. The list contains one or more actions and a set of match criteria for each action.
-Consul applies permissions in the order specified in the configuration. Starting at the beginning of the list, Consul applies the first matching request and stops evaluating against the remaining configurations.
+Consul applies permissions in the order specified in the configuration. Starting at the beginning of the list, Consul applies the first matching request and stops evaluating against the remaining configurations.
-For requests that do not match any of the defined permissions, Consul applies the intention behavior defined in the [`acl_default_policy`](/consul/docs/agent/config/config-files#acl_default_policy) configuration.
+For requests that do not match any of the defined permissions, Consul applies the intention behavior defined in the [`acl_default_policy`](/consul/docs/agent/config/config-files#acl_default_policy) configuration.
-Do not configure this field for L4 intentions. Use the [`spec.sources.action`](#sources-action) parameter instead.
+Do not configure this field for L4 intentions. Use the [`spec.sources.action`](#sources-action) parameter instead.
`permissions` configurations only apply to services with a compatible protocol. As a result, they are not supported when the [`spec.destination.name`](#spec-destination-name) or [`spec.destination.namespace`](#spec-destination-namespace) field is configured with a wildcard because service instances or services in a namespace may use different protocols.
@@ -716,12 +759,12 @@ Do not configure this field for L4 intentions. Use the [`spec.sources.action`](#
### `spec.sources[].permissions[].action`
-Specifies the action to take when the source sends traffic to the destination service. The value is either `allow` or `deny`.
+Specifies the action to take when the source sends traffic to the destination service. The value is either `allow` or `deny`.
#### Values
- Default: None
-- This field is required.
+- This field is required.
- Data type: String value set to either `allow` or `deny`
### `spec.sources[].permissions[].http`
@@ -732,7 +775,7 @@ Specifies a set of HTTP-specific match criteria. Consul applies the action defin
- Default: None
- This field is required.
-- Data type: Map
+- Data type: Map
The following table describes the parameters that the HTTP map may contain:
@@ -746,28 +789,34 @@ The following table describes the parameters that the HTTP map may contain:
### `spec.sources[].permissions[].http[].header`
-Specifies a set of criteria for matching HTTP request headers. The request header must match all specified criteria for the permission to apply.
+Specifies a set of criteria for matching HTTP request headers. The request header must match all specified criteria for the permission to apply.
#### Values
- Default: None
- Data type: List of maps
-Each member of the `header` list is a map that contains a `name` field and at least one match criterion. The following table describes the parameters that each member of the `header` list may contain:
+Each member of the `header` list is a map that contains a `name` field and at least one match criterion.
+
+~> **Warning**: If it is possible for a header to contain multiple values, we recommend using `contains` or `regex` rather than `exact`, `prefix`, or `suffix`. Envoy internally concatenates multiple header values into a single CSV value prior to applying match rules, which may result in match rules that depend on the beginning or end of a string vulnerable to circumvention. A more robust alternative is using `contains` or, if a stricter value match is required, configuring a regex pattern that is tolerant of comma-separated values. These options are available as of Consul CE 1.20.1 and Consul Enterprise 1.20.1, 1.19.2, 1.18.3, and 1.15.15.
+
+The following table describes the parameters that each member of the `header` list may contain:
| Parameter | Description | Data type | Required |
| --- | --- | --- | --- |
| `name` | Specifies the name of the header to match. | string | required |
-| `present` | Enables a match if the header configured in the `name` field appears in the request. Consul matches on any value as long as the header key appears in the request. Do not specify `present` if `exact`, `prefix`, `suffix`, or `regex` are configured in the same `header` configuration. | boolean | optional |
-| `Exact` | Specifies a value for the header key set in the `Name` field. If the request header value matches the `exact` value, Consul applies the permission. Do not specify `exact` if `present`, `prefix`, `suffix`, or `regex` are configured in the same `header` configuration. | string | optional |
-| `prefix` | Specifies a prefix value for the header key set in the `name` field. If the request header value starts with the `prefix` value, Consul applies the permission. Do not specify `prefix` if `present`, `exact`, `suffix`, or `regex` are configured in the same `header` configuration. | string | optional |
-| `suffix` | Specifies a suffix value for the header key set in the `name` field. If the request header value ends with the `suffix` value, Consul applies the permission. Do not specify `suffix` if `present`, `exact`, `prefix`, or `regex` are configured in the same `header` configuration. | string | optional |
-| `regex` | Specifies a regular expression pattern as the value for the header key set in the `name` field. If the request header value matches the regex, Consul applies the permission. Do not specify `regex` if `present`, `exact`, `prefix`, or `suffix` are configured in the same `header` configuration. The regex syntax is proxy-specific. If using Envoy, refer to the [re2 documentation](https://github.com/google/re2/wiki/Syntax) for details. | string | optional |
+| `present` | Enables a match if the header configured in the `name` field appears in the request. Consul matches on any value as long as the header key appears in the request. Do not specify `present` if `exact`, `prefix`, `suffix`, `contains`, or `regex` are configured in the same `header` configuration. | boolean | optional |
+| `Exact` | Specifies a value for the header key set in the `Name` field. If the request header value matches the `exact` value, Consul applies the permission. Do not specify `exact` if `present`, `prefix`, `suffix`, `contains`, or `regex` are configured in the same `header` configuration. | string | optional |
+| `prefix` | Specifies a prefix value for the header key set in the `name` field. If the request header value starts with the `prefix` value, Consul applies the permission. Do not specify `prefix` if `present`, `exact`, `suffix`, `contains`, or `regex` are configured in the same `header` configuration. | string | optional |
+| `suffix` | Specifies a suffix value for the header key set in the `name` field. If the request header value ends with the `suffix` value, Consul applies the permission. Do not specify `suffix` if `present`, `exact`, `prefix`, `contains`, or `regex` are configured in the same `header` configuration. | string | optional |
+| `contains` | Specifies a contains value for the header key set in the `name` field. If the request header value includes the `contains` value, Consul applies the permission. Do not specify `contains` if `present`, `exact`, `prefix`, `suffix`, or `regex` are configured in the same `header` configuration. | string | optional |
+| `regex` | Specifies a regular expression pattern as the value for the header key set in the `name` field. If the request header value matches the regex, Consul applies the permission. Do not specify `regex` if `present`, `exact`, `prefix`, `suffix`, or `contains` are configured in the same `header` configuration. The regex syntax is proxy-specific. If using Envoy, refer to the [re2 documentation](https://github.com/google/re2/wiki/Syntax) for details. | string | optional |
+| `ignoreCase` | Ignores the case of the provided header value when matching with exact, prefix, suffix, or contains. Default is `false`. | boolean | optional |
| `invert` | Inverts the matching logic configured in the `header`. Default is `false`. | boolean | optional |
### `spec.sources[].type`
-Specifies the type of destination service that the configuration entry applies to. The only value supported is `consul`.
+Specifies the type of destination service that the configuration entry applies to. The only value supported is `consul`.
#### Values
@@ -776,7 +825,7 @@ Specifies the type of destination service that the configuration entry applies t
### `spec.sources[].description`
-Specifies a description of the intention. Consul presents the description in API responses to assist other tools integrated into the network.
+Specifies a description of the intention. Consul presents the description in API responses to assist other tools integrated into the network.
#### Values
@@ -794,9 +843,9 @@ The following examples demonstrate potential use-cases for the service intention
### L4 Intentions for specific sources and destinations
-The following example configuration entry specifies an L4 intention that denies traffic from `web` to `db` service instances, but allows traffic from `api` to `db`.
+The following example configuration entry specifies an L4 intention that denies traffic from `web` to `db` service instances, but allows traffic from `api` to `db`.
-
+
```hcl
Kind = "service-intentions"
@@ -849,7 +898,7 @@ spec:
### L4 intentions for all destinations
-In the following L4 example, the destination is configured with a `*` wildcard. As a result, traffic from `web` service instances is denied for any service in the datacenter.
+In the following L4 example, the destination is configured with a `*` wildcard. As a result, traffic from `web` service instances is denied for any service in the datacenter.
@@ -894,7 +943,7 @@ spec:
### L4 intentions for all sources
-In the following L4 example, the source is configured with a `*` wildcard. As a result, traffic from any service is denied to `db` service instances.
+In the following L4 example, the source is configured with a `*` wildcard. As a result, traffic from any service is denied to `db` service instances.
@@ -1036,7 +1085,7 @@ spec:
### gRPC
-In the following example, Consul denies requests from `frontend-web` to the `IssueRefund` gRPC service.
+In the following example, Consul denies requests from `frontend-web` to the `IssueRefund` gRPC service.
Because gRPC method calls use the [HTTP/2 protocol](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md), you can apply an HTTP path-matching rule to control traffic:
diff --git a/website/content/docs/connect/intentions/index.mdx b/website/content/docs/connect/intentions/index.mdx
index 9cb0f36ee1..25353afaab 100644
--- a/website/content/docs/connect/intentions/index.mdx
+++ b/website/content/docs/connect/intentions/index.mdx
@@ -38,6 +38,10 @@ L4 intentions mediate the ability to establish new connections. Modifying an int
L7 intentions mediate the ability to issue new requests. When an intention is modified, requests received after the modification use the latest intention rules to enforce access. Changing a connection from `allow` to `deny` does not sever the connection, but doing so blocks new requests from being processed.
+When using L7 intentions, we recommend that you review and update the [Mesh request normalization configuration](/consul/docs/connect/security#request-normalization-and-configured) to avoid unintended match rule circumvention. More details are available in the [Mesh configuration entry reference](/consul/docs/connect/config-entries/mesh#request-normalization).
+
+When you use L7 intentions with header matching and it is possible for a header to contain multiple values, we recommend using `contains` or `regex` instead of `exact`, `prefix`, or `suffix`. For more information, refer to the [service intentions configuration entry reference](/consul/docs/connect/config-entries/service-intentions#spec-sources-permissions-http-header).
+
### Caching
The intentions for services registered with a Consul agent are cached locally on the agent. Supported proxies also cache intention data in their own configurations so that they can authorize inbound connections or requests without relying on the Consul agent. All actions in the data path of connections take place within the proxy.
diff --git a/website/content/docs/connect/security.mdx b/website/content/docs/connect/security.mdx
index 42ce8d0d1e..dd92ffb0cf 100644
--- a/website/content/docs/connect/security.mdx
+++ b/website/content/docs/connect/security.mdx
@@ -26,6 +26,32 @@ of Consul.
## Checklist
+### Request Normalization Configured for L7 Intentions
+
+~> **Compatibility warning**: This feature is available as of Consul CE 1.20.1 and Consul Enterprise 1.20.1, 1.19.2, 1.18.3, and 1.15.15. We recommend upgrading to the latest version of Consul to take advantage of the latest features and improvements.
+
+Atypical traffic patterns may interfere with the enforcement of L7 intentions. For
+example, if a service makes request to a non-normalized URI path and Consul is not
+configured to force path normalization, it becomes possible to circumvent path match rules. While a
+default deny policy can limit the impact of this issue, we still recommend
+that you review your current request normalization configuration. Normalization is critical to avoid unwanted
+traffic, especially when using unrecommended security options such as a default allow intentions policy.
+
+Consul adopts a default normalization mode that adheres to [RFC 3986](
+https://tools.ietf.org/html/rfc3986#section-6), but additional options to enable stricter
+normalization are available in the cluster-wide [Mesh configuration entry](
+/consul/docs/connect/config-entries/mesh). We recommend reviewing these options and
+enabling the strictest set that does not interfere with application traffic.
+
+We also recommend that you review L7 intention header match rules for potential
+issues with multiple header values. Refer to the [service intentions
+configuration entry reference](/consul/docs/connect/config-entries/service-intentions#spec-sources-permissions-http-header)
+for more information.
+
+You do not need to enable request normalization if you are not using L7 intentions.
+However, normalization may also benefit the use of other service mesh features that
+rely on L7 attribute matching, such as [service routers](/consul/docs/connect/manage-traffic#routing).
+
### ACLs Enabled with Default Deny
Consul must be configured to use ACLs with a default deny policy. This forces
@@ -43,6 +69,10 @@ this. **If ACLs are not enabled**, deny intentions will still be enforced, but a
may edit intentions. This renders the security of the created intentions
effectively useless.
+The advantage of a default deny policy in combination with specific "allow" rules
+is that at worst, a failure of intentions due to misconfiguration will result in
+_denied_ traffic, rather than unwanted _allowed_ traffic.
+
### TCP and UDP Encryption Enabled
TCP and UDP encryption must be enabled to prevent plaintext communication
@@ -100,7 +130,7 @@ will not be encrypted or authorized via service mesh.
Envoy exposes an **unauthenticated**
[administration interface](https://www.envoyproxy.io/docs/envoy/latest/operations/admin)
-that can be used to query and modify the proxy. This interface
+that can be used to query and modify the proxy. This interface
allows potentially sensitive information to be retrieved, such as:
* Envoy configuration
diff --git a/website/content/docs/security/security-models/core.mdx b/website/content/docs/security/security-models/core.mdx
index 2f91acf34f..66dd7abca7 100644
--- a/website/content/docs/security/security-models/core.mdx
+++ b/website/content/docs/security/security-models/core.mdx
@@ -26,6 +26,10 @@ environment, but the general mechanisms for a secure Consul deployment revolve a
[authentication methods](/consul/docs/security/acl/auth-methods) can be used to enable trusted external parties to authorize
ACL token creation.
+- **Intentions** - If in use, configure service intentions to use a default-deny policy. If L7 intentions are
+ in use, enable [Mesh request normalization](/consul/docs/connect/config-entries/mesh#request-normalization)
+ and review your [header match rules](/consul/docs/connect/config-entries/service-intentions#spec-sources-permissions-http-header) to prevent malformed requests from bypassing intentions.
+
- **Namespaces** - Read and write operations can be scoped to a logical namespace to restrict
access to Consul components within a multi-tenant environment.
@@ -184,6 +188,13 @@ environment and adapt these configurations accordingly.
- **🏷 Namespace** - a named, logical scoping of Consul Enterprise resources, typically to
enable multi-tenant environments. Consul OSS clusters always operate within the "default" namespace.
+- **Intentions** - Service intentions control traffic communication between services at the network layer (L4) and
+ application layer (L7). If in use, we strongly recommend configuring intentions to use a default-deny policy.
+ When L7 intentions are in use, review your configuration for [Mesh request normalization](/consul/docs/connect/config-entries/mesh#request-normalization)
+ and use the strictest set of options suitable to your environment. At minimum, we
+ recommend keeping path normalization enabled, because this default setting prevents requests that do not conform to [RFC 3986](
+ https://tools.ietf.org/html/rfc3986#section-6) from bypassing path match rules.
+
- **Gossip Encryption** - A shared, base64-encoded 32-byte symmetric key is required to [encrypt Serf gossip
communication](/consul/tutorials/security/gossip-encryption-secure?utm_source=consul.io&utm_medium=docs) within a cluster using
AES GCM. The key size determines which AES encryption types to use; 16, 24, or 32 bytes to select AES-128, AES-192,
@@ -258,6 +269,10 @@ environment and adapt these configurations accordingly.
}
```
+- **Customize Mesh HTTP Request Normalization** - If L7 intentions are in use, we recommend configuring request normalization to
+ avoid match rule circumvention. Other normalization options, such as dropping or rejecting headers with underscores,
+ may also be appropriate depending on your requirements. Review the options in the [Mesh configuration entry](/consul/docs/connect/config-entries/mesh#request-normalization) to determine the appropriate settings for your use case.
+
- **Customize Default Limits** - Consul has a number of builtin features with default connection limits that should be
tuned to fit your environment.
diff --git a/website/content/docs/upgrading/upgrade-specific.mdx b/website/content/docs/upgrading/upgrade-specific.mdx
index bc3daf8ca8..17b28511e9 100644
--- a/website/content/docs/upgrading/upgrade-specific.mdx
+++ b/website/content/docs/upgrading/upgrade-specific.mdx
@@ -156,6 +156,10 @@ In Consul v1.15 and higher:
+### Mesh traffic request path normalization enabled by default
+
+As of Consul v1.15.15, inbound traffic to mesh proxies will have Envoy request [path normalization](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-normalize-path) applied by default. This should not interfere with the majority of service traffic, but can be disabled if needed by setting `http.incoming.request_normalization.insecure_disable_path_normalization` to `true` in the [global `mesh` configuration entry](/consul/docs/connect/config-entries/mesh#request-normalization). This setting is generally safe to change if not using L7 intentions with path matching.
+
## Consul 1.14.x
### Service Mesh Compatibility