diff --git a/app/_assets/stylesheets/index.css b/app/_assets/stylesheets/index.css index 4b5841fa5..a4c2ff4c5 100644 --- a/app/_assets/stylesheets/index.css +++ b/app/_assets/stylesheets/index.css @@ -354,6 +354,10 @@ .tabcolumn { @apply list-none flex text-sm ml-0 w-full gap-0; + + ul, li { + @apply list-none; + } } .tab-button { diff --git a/app/_gateway_entities/certificate.md b/app/_gateway_entities/certificate.md index 5ad1235e0..a13ae09b4 100644 --- a/app/_gateway_entities/certificate.md +++ b/app/_gateway_entities/certificate.md @@ -34,7 +34,7 @@ schema: faqs: - q: What's the difference between the Certificate entity and the CA Certificate entity? - a: Certificates handle [SSL/TLS termination](/kic/tls-termination-passthrough) for encrypted requests and [CA Certificates](/gateway/entities/ca-certificate/) validate client or server certificates. + a: Certificates handle SSL/TLS termination for encrypted requests and [CA Certificates](/gateway/entities/ca-certificate/) validate client or server certificates. - q: Is the Certificate entity used in {{site.konnect_short_name}} for data plane nodes as well? a: No, the data plane nodes use a [different certificate](/api/konnect/control-planes-config/). --- @@ -44,9 +44,8 @@ faqs: A Certificate object represents a public certificate, which is used to validate the sender's authorization and name. It can optionally be paired with the corresponding private key to initiate secure connections and encrypt sensitive data. {{site.base_gateway}} can use Certificates in the following ways: -* Handle [SSL/TLS termination](/kic/tls-termination-passthrough) for encrypted requests +* Handle SSL/TLS termination for one or more hostnames using the associated [SNI object](/gateway/entities/sni/) * Use as a trusted CA store when validating the peer certificate of a client or Service -* Tie a certificate and key pair to one or more hostnames using the associated [SNI object](/gateway/entities/sni/) ## Schema diff --git a/app/_gateway_entities/consumer-group.md b/app/_gateway_entities/consumer-group.md index 259ab43bc..b4f302bc3 100644 --- a/app/_gateway_entities/consumer-group.md +++ b/app/_gateway_entities/consumer-group.md @@ -53,9 +53,6 @@ Consumer Groups enable the organization and categorization of [Consumers](/gatew With Consumer Groups, you can scope plugins to specifically defined Consumer Groups and a new plugin instance will be created for each individual Consumer Group, making configurations and customizations more flexible and convenient. For all plugins available on the consumer groups scope, see the [Plugin Scopes Reference](/plugins/scopes/). -{:.info} -> **Note**: Consumer Groups plugin scoping is a feature that was added in {{site.base_gateway}} version 3.4. Running a mixed-version {{site.base_gateway}} cluster (3.4 control plane, and <=3.3 data planes) is not supported when using plugins scoped to Consumer Groups. - For example, you could define two groups, Gold and Silver, assign different rate limits to them, then process each group using a different plugin: @@ -64,46 +61,40 @@ flowchart LR A((fa:fa-user Consumers 1-5)) B(Consumer Group Gold - 10 requests/second fa:fa-user Consumer 1, fa:fa-user Consumer 2, fa:fa-user Consumer 5 ) C(Consumer Group Silver - 5 requests/minute fa:fa-user Consumer 3, fa:fa-user Consumer 4) - D(Rate Limiting Advanced) - E(Request Transformer Advanced) + D(Rate Limiting Advanced + 10 requests/second) + E(Rate Limiting Advanced + 2 requests/second) F(Gateway Service QR Code Generation) - G(Gateway Service - OCR) H(QR Code Generation service) - I(OCR service) A--> B & C subgraph id1 [Kong Gateway] direction LR B --> D --> F - subgraph id2 [Gold route] - direction LR - D - end - C --> E --> G - subgraph id3 [Silver route] - direction LR - E - end + C --> E --> F end F --> H - G --> I {% endmermaid %} +Without Consumer Groups, you would have to use five Rate Limiting Advanced plugins, once for each consumer. +Any time you change the rate limit, you would need to update every consumer individually. + +Consumer Groups allow you to manage your plugin configuration centrally, and reduce the size of your {{ site.base_gateway }} configuration at the same time. +In this example, it's the difference between using two plugins or five plugins. In your production environment, it could be the difference between two plugins and five _million_ plugins. + ## Use cases Common use cases for Consumer Groups: diff --git a/app/_gateway_entities/consumer.md b/app/_gateway_entities/consumer.md index 193da32c3..60211a097 100644 --- a/app/_gateway_entities/consumer.md +++ b/app/_gateway_entities/consumer.md @@ -19,45 +19,40 @@ faqs: a: | Credentials are necessary to authenticate Consumers via various authentication mechanisms. The credential type depends on which authentication plugin you want to use. -

+ For example, a Key Authentication plugin requires an API key, and a Basic Authentication plugin requires a username and password pair. - q: What is the difference between Consumers and Applications? a: | - Applications provide developers the ability to get access to APIs managed by {{site.base_gateway}} or {{site.konnect_short_name}} - with no interaction from the Kong admin team to generate the required credentials. -

+ Applications provide developers the ability to get access to APIs managed by {{site.base_gateway}} or {{site.konnect_short_name}} with no interaction from the Kong admin team to generate the required credentials. Applications are managed using the Developer Portal. + With Consumers, the Kong team creates Consumers, generates credentials, and shares them with the developers that need access to the APIs. - You can think of Applications as a type of Consumer in Kong that allows developers to automatically obtain credentials for, and subscribe to the required APIs. - q: What is the difference between Consumers and Developers? a: | - Developers are real users of the Dev Portal, whereas Consumers are abstractions. + A developer is a person that has registered for a Developer Portal. They can create applications and manage credentials themselves. + + Consumers are a part of your {{ site.base_gateway }} configuration and are managed by your administrators. - q: What is the difference between Consumers and RBAC Users? a: | - RBAC Users are users of Kong Manager, whereas Consumers are users (real or abstract) of the Gateway itself. + RBAC Users are users of Kong Manager, whereas Consumers are users of the services proxied by the Gateway itself. - q: Which plugins can be scoped to Consumers? a: | - Certain plugins can be scoped to Consumers (as opposed to Gateway Services, Routes, Consumer Groups, or globally). For example, you might want to - configure the Rate Limiting plugin to rate limit a specific Consumer, or use the Request Transformer plugin to edit requests for that Consumer. + Most plugins can be scoped to Consumers, with the exception of authentication plugins and plugins that control routing. + You can see the full list in the [plugin scopes compatibility reference](/plugins/scopes/). - q: Can you scope authentication plugins to Consumers? a: | - No. You can associate Consumers with an auth plugin by configuring credentials. For example, a Consumer with basic - auth credentials will use the Basic Authentication plugin. - But that plugin must be scoped to either a Route, Service, or globally, so that the Consumer can access it. - + No. Authentication plugins must be scoped to either a Route, Service, or globally. - q: Can you manage Consumers with decK? a: | - Yes, you can manage Consumers using decK, but take caution if you have a large number of Consumers. -

- If you have many Consumers in your database, don't export or manage them using decK. - decK is built for managing entity configuration. It is not meant for end user data, - which can easily grow into hundreds of thousands or millions of records. + Yes, you can manage Consumers using decK, but take caution if you have a large number of Consumers as the sync time will be high. + + To manage a large number of consumers using decK, we recommend a federated configuration management approach where consumers are placed in to Consumer Groups and managed separately from the rest of your configuration. tools: - admin-api @@ -78,45 +73,51 @@ schema: ## What is a Consumer? -A Consumer typically refers to an entity that consumes or uses the APIs managed by {{site.base_gateway}}. +A Consumer is an entity that consumes or uses the APIs managed by {{site.base_gateway}}. Consumers can be applications, services, or users who interact with your APIs. Since they are not always human, {{site.base_gateway}} calls them Consumers, because they "consume" the service. {{site.base_gateway}} allows you to define and manage Consumers, apply access control policies, and monitor their API usage. Consumers are essential for controlling access to your APIs, tracking usage, and ensuring security. -They are identified by key authentication, OAuth, or other authentication and authorization mechanisms. +They are identified by key authentication, OAuth, or other authentication and authorization mechanisms. For example, adding a Basic Auth plugin to a Gateway Service or Route allows it to identify a Consumer, or block access if credentials are invalid. -You can choose to use {{site.base_gateway}} as the primary datastore for Consumers, or you can map the Consumer list -to an existing database to keep consistency between {{site.base_gateway}} and your existing primary datastore. - By attaching a plugin directly to a Consumer, you can manage specific controls at the Consumer level, such as rate limits. + + {% mermaid %} flowchart LR -A(Consumer entity) -B(Auth plugin) -C[Upstream service] - -Client --> A -subgraph id1[{{ site.base_gateway }}] -direction LR -A--Credentials-->B +Consumer(Consumer entity) +Service(Gateway Service) +Auth(Auth plugin) +Upstream[Upstream service] +RL["Per-consumer +Rate Limiting Plugin applied"] + +Client --> Authenticate +subgraph Authenticate ["Consumer Identity Added"] + direction TB + Service --> Auth + Auth-->Consumer end +Authenticate --> RL +RL --> Upstream -B-->C {% endmermaid %} + + ## Use cases for Consumers Common use cases for Consumers: |Use case | Description| |---------|------------| -|Authentication | Client authentication is the most common reason for setting up a Consumer. If you're using an authentication plugin, you'll need a Consumer with credentials.| -|Consumer Groups | Group Consumers by sets of criteria and apply certain rules to them.| -|Rate limiting | Rate limit specific Consumers based on tiers.| +| Authentication | Client authentication is the most common reason for setting up a Consumer. If you're using an authentication plugin, you'll need a Consumer with credentials. | +| Rate limiting | Rate limit specific Consumers based on tiers. | +| Transformation | Add or remove values from response bodies based on the Consumer. | ## Schema diff --git a/app/_gateway_entities/group.md b/app/_gateway_entities/group.md index fa10697ba..74969bb3e 100644 --- a/app/_gateway_entities/group.md +++ b/app/_gateway_entities/group.md @@ -12,10 +12,10 @@ related_resources: url: /gateway/entities/rbac/ - text: Admins entity url: /gateway/entities/admin/ - - text: LDAP Authentication - url: /plugin/ldap-auth/ - - text: Workspace + - text: Workspace entity url: /gateway/entities/workspace/ + - text: LDAP Service Directory Mapping + url: /gateway/ldap-service-directory-mapping/ tier: enterprise @@ -40,24 +40,25 @@ faqs: ## What is a Group? -In {{site.base_gateway}}, the Group entity functions as a resource for [RBAC](/gateway/entities/rbac/#role-configuration). {{site.base_gateway}} Admins can map Permissions and Roles to a Group, and use the Group to simplify Role assignment across the {{site.base_gateway}} environment. +In {{site.base_gateway}}, the Group entity functions as a resource for [RBAC](/gateway/entities/rbac/#role-configuration). +{{site.base_gateway}} Admins can map Permissions and Roles to a Group, and use the Group to simplify Role assignment across the {{site.base_gateway}} environment. The Group resource can also be used to integrate identity providers like Okta with Kong Manager, letting you map relationships between your service directory mappings and Kong Manager Roles. ## Service directory mapping -With service directory mapping, Groups can be mapped to [RBAC Roles](/gateway/entities/rbac/#role-configuration). When a user logs in to Kong Manager, they are identified with their Admin username and authenticated with user credentials from a service directory, like [LDAP](/plugins/ldap-auth/). The service directory creates a relationship with the associated RBAC Roles that are defined in {{site.base_gateway}}. +With service directory mapping, Groups can be mapped to [RBAC Roles](/gateway/entities/rbac/#role-configuration). +When a user logs in to Kong Manager, they are identified with their Admin username and authenticated with user credentials from a service directory, like LDAP. +The service directory creates a relationship with the associated RBAC Roles that are defined in {{site.base_gateway}}. This happens in the following order: - 1. Roles are created in {{site.base_gateway}}. 2. Groups are created and associated with RBAC Roles. 3. Groups are associated with an external directory. 4. Permissions are assigned to {{site.base_gateway}} users based on Group assignment. -For more information, read the [LDAP](/plugins/ldap-auth/) documentation. - +For more information, read the [LDAP Service Directory Mapping](/gateway/ldap-service-directory-mapping/) documentation. ## Schema diff --git a/app/_gateway_entities/license.md b/app/_gateway_entities/license.md index 31cbe3f81..0496fcb62 100644 --- a/app/_gateway_entities/license.md +++ b/app/_gateway_entities/license.md @@ -68,20 +68,24 @@ features: - title: License File url: /gateway/entities/license/#deploy-a-license-with-a-file-on-the-node-filesystem-licensejson traditional: true - hybrid: false + hybrid: true dbless: true - title: Environment variable url: /gateway/entities/license/#deploy-a-license-with-an-environment-variable traditional: true - hybrid: false + hybrid: true dbless: true {% endfeature_table %} + +## Deploy a License + {% navtabs %} {% navtab "Admin API" %} -### Deploy a License using the Admin API + +You can deploy a License using the Admin API. The control plane sends Licenses configured through the [`/licenses` endpoint](/api/gateway/admin-ee/#/operations/post-licenses) to all data planes in the cluster. The data planes use the most recent `updated_at` License. This is the only method that automatically applies the License to data planes. @@ -91,22 +95,30 @@ data: payload: "{\"license\":{\"payload\":{\"admin_seats\":\"1\",\"customer\":\"Example Company, Inc\",\"dataplanes\":\"1\",\"license_creation_date\":\"2017-07-20\",\"license_expiration_date\":\"2017-07-20\",\"license_key\":\"00141000017ODj3AAG_a1V41000004wT0OEAU\",\"product_subscription\":\"Konnect Enterprise\",\"support_plan\":\"None\"},\"signature\":\"6985968131533a967fcc721244a979948b1066967f1e9cd65dbd8eeabe060fc32d894a2945f5e4a03c1cd2198c74e058ac63d28b045c2f1fcec95877bd790e1b\",\"version\":\"1\"}}" {% endentity_example %} -[Reload](/how-to/restart-kong-gateway-container/) the {{site.base_gateway}} nodes after adding or updating a License. - {% endnavtab %} {% navtab "license.json" %} -### Deploy a License with `license.json` + +You can deploy a License with a `license.json` file. The license data must contain straight quotes to be considered valid JSON (`'` and `"`, not `’` or `“`). Kong searches for the License by default in `/etc/kong/license.json`. +{:.info} +> The control plane **does not** propagate the License to data plane nodes. +You **must** add the License to each data plane node, and each node **must** start with the License. +The License can't be added after starting the node. + 1. Save your License to a file named `license.json`. 1. Copy the license file to the `/etc/kong`. -1. [Reload](/how-to/restart-kong-gateway-container/) the {{site.base_gateway}} nodes to apply the license by running `kong reload` from within the container. +1. [Restart](/how-to/restart-kong-gateway-container/) the {{site.base_gateway}} nodes to apply the license by running `kong restart` from within the container. {% endnavtab %} {% navtab "Environment variable" %} -### Deploy a License as an environment variable -If you deploy a License using a `KONG_LICENSE_DATA` or `KONG_LICENSE_PATH` environment variable, the control plane **does not** propagate the License to data plane nodes. You **must** add the License to each data plane node, and each node **must** start with the License. The License can't be added after starting the node. +You can deploy a License as an environment variable. + +{:.info} +> If you deploy a License using a `KONG_LICENSE_DATA` or `KONG_LICENSE_PATH` environment variable, the control plane **does not** propagate the License to data plane nodes. +You **must** add the License to each data plane node, and each node **must** start with the License. +The License can't be added after starting the node. Unlike other `KONG_*` environmental variables, the `KONG_LICENSE_DATA` and `KONG_LICENSE_PATH` can't be defined in-line as part of any `kong` CLI commands. License file environmental variables must be exported to the shell where the Nginx process runs, ahead of the `kong` CLI tool. diff --git a/app/_gateway_entities/rbac.md b/app/_gateway_entities/rbac.md index dae1e7aea..efd37b4f7 100644 --- a/app/_gateway_entities/rbac.md +++ b/app/_gateway_entities/rbac.md @@ -3,8 +3,7 @@ title: RBAC content_type: reference products: - gateway -tiers: - - enterprise +tier: enterprise tools: - admin-api entities: @@ -12,7 +11,7 @@ entities: description: The RBAC entity is what allows for the RBAC system to be administered. schema: api: gateway/admin-ee - path: /schemas/rbac + path: /schemas/RBAC related_resources: - text: Gateway Workspace entity @@ -34,11 +33,9 @@ RBAC in {{site.base_gateway}} conforms to the following core principles: * In {{site.base_gateway}} there are Users * Every user has a Role * Roles are assigned Permissions -* Every Role belongs to a [Group](/gateway/entities/group/) * A Group is a collection of Roles -{{site.base_gateway}} uses a precedence model, from most specificity to least specificity, to determine if a user has access to an endpoint. - +{{site.base_gateway}} uses a [precedence model](#rbac-precedence-order), from most specificity to least specificity, to determine if a user has access to an endpoint. ## What are Permissions? @@ -63,6 +60,8 @@ If {{site.base_gateway}} finds a matching permission for the current user, endpo This diagram helps explain how individual workspace roles and cross-workspace roles interact: + + {% mermaid %} flowchart LR subgraph team-a-roles [Team A Roles] @@ -108,6 +107,7 @@ flowchart LR {% endmermaid %} + ## RBAC Entities @@ -199,18 +199,4 @@ You can also automate the creation of Admins. For more information, see [creatin ## Schema -{% entity_schema %} - -## Create an RBAC user - -Creating an RBAC User requires [RBAC to be enabled](#enable-rbac) for {{site.base_gateway}}. - -{% entity_example %} -type: rbac -data: - name: my-user - user_token: exampletoken -headers: - admin-api: - - "Kong-Admin-Token: $ADMIN_TOKEN" -{% endentity_example %} \ No newline at end of file +{% entity_schema %} \ No newline at end of file diff --git a/app/_gateway_entities/route.md b/app/_gateway_entities/route.md index 69d918e4f..ab756f981 100644 --- a/app/_gateway_entities/route.md +++ b/app/_gateway_entities/route.md @@ -12,9 +12,17 @@ related_resources: url: /gateway/entities/service/ - text: Expressions router url: /gateway/routing/expressions/ + - text: Traditional router + url: /gateway/routing/traditional/ - text: Upstream entity url: /gateway/entities/upstream/ +next_steps: + - text: Learn about the Expressions router + url: /gateway/routing/expressions/ + - text: Learn about the Traditional router + url: /gateway/routing/traditional/ + tools: - admin-api - konnect-api @@ -26,84 +34,59 @@ schema: api: gateway/admin-ee path: /schemas/Route -faqs: - - q: How can I divert traffic from an old URL to a new one with {{site.base_gateway}}? - a: Create a new route and point it to the existing Gateway Service. The new route will proxy traffic to the existing service at the new URL. - --- ## What is a Route? -A Route is a path to a resource within an upstream application. In {{site.base_gateway}}, Routes typically map to endpoints exposed through [Gateway Services](/gateway/entities/service/). Routes determine how (and if) requests are sent to their Services after they reach {{site.base_gateway}}. Where a Service represents the backend API, a Route defines what is exposed to clients. +Routes fulfill two responsibilities in {{ site.base_gateway }}: -Routes can also define rules that match requests to associated Services. Because of this, one Route can reference multiple endpoints. Once a Route is matched, {{site.base_gateway}} proxies the request to its associated Service. A basic Route should have a name, path or paths, and reference an existing Service. - -{% mermaid %} -flowchart LR - A(API client) - B("`Route - (/mock)`") - C("`Gateway Service - (example-service)`") - D(Upstream - application) - - A <--requests - responses--> B - subgraph id1 ["` - **KONG GATEWAY**`"] - B <--requests - responses--> C - end - C <--requests - responses--> D +1. Match incoming requests and route them to the correct [Gateway Service](/gateway/entities/service/) +2. Use plugins to transform the request/response proxied using this Route - style id1 rx:10,ry:10 - -{% endmermaid %} +A Route must be attached to a [Service](/gateway/entities/service/), and _may_ have one or more [Plugin](/gateway/entities/plugin/) entities attached. ## Route and Service interaction -Routes, in conjunction with [Services](/gateway/entities/service/), let you expose your Services to applications with {{site.base_gateway}}. {{site.base_gateway}} abstracts the Service from the applications by using Routes. Since the application always uses the Route to make a request, changes to the Services, like versioning, don’t impact how applications make the request. Routes also allow the same Service to be used by multiple applications and apply different policies based on the Route used. +Routes, in conjunction with [Services](/gateway/entities/service/), let you expose your services to applications with {{site.base_gateway}}. Routes also allow the same service to be used by multiple applications and apply different policies based on the route used. For example, say you have an external application and an internal application that need to access the `example_service` Service, but the *external* application should be limited in how often it can query the Service to avoid a denial of service. If you apply a rate limit policy to the Service and the *internal* application calls it, the internal application is also limited. Routes can solve this problem. -In this example, you can create two Routes to handle the two applications, say `/external` and `/internal`, and point both of them to `example_service`. -You can configure a policy to limit how often the `/external` Route is used. -When the external application tries to access the Service via {{site.base_gateway}} using `/external`, it's rate limited. -But when the internal application accesses the Service using {{site.base_gateway}} using `/internal`, the internal application isn't limited. +In this example, you can create two Routes with different hosts to handle the two applications, say `internal.example.com` and `external.example.com`, and point both of them to `example_service`. +You can configure a policy to limit how often the external Route is used. +When the external application tries to access the Service via {{site.base_gateway}} using `external.example.com`, it's rate limited. +But when the internal application accesses the Service using {{site.base_gateway}} using `internal.example.com`, the internal application isn't limited. The following diagram illustrates this example: + + {% mermaid %} flowchart LR A(External application) - B("`Route (/external)`") - B2(Rate Limiting - plugin) + B("`Route (external.example.com)`") + B2(Rate Limiting plugin) C("`Service (example-service)`") D(Upstream application) E(Internal application) - F("`Route (/internal)`") + F("`Route (internal.example.com)`") A --request--> B E --request--> F subgraph id1 ["` **KONG GATEWAY**`"] - B --> B2 --"10 requests - per minute"--> C + B --> B2 --"10 requests per minute"--> C F ---> C end - C --transformed - and routed - requests--> D + C --> D style id1 rx:10,ry:10 {% endmermaid %} + + ## Route use cases Common use cases for Routes: @@ -113,60 +96,364 @@ Common use cases for Routes: | Rate limiting | Use Routes to set different rate limits for clients accessing the upstream application via specific paths, for example `/internal` or `/external`.

[Enable a rate limiting plugin on Routes attached to the Service](/plugins/rate-limiting-advanced/) | | Perform a simple URL rewrite | Use the Routes entity to rename an endpoint. For example, you can rename your legacy `/api/old/` upstream endpoint to a publicly accessible API endpoint named `/new/api`. | | Perform a complex URL rewrite | Use the Routes entity to rewrite a group of paths, such as replacing `/api//old` with `/new/api/`.

[Request Transformer Advanced plugin](/plugins/request-transformer-advanced/) | -| Describe paths as patterns using regular expressions | [Expressions router](/gateway/routing/expressions/) | -## How routing works +## Configuration formats -For each incoming request, {{site.base_gateway}} must determine which Service gets to handle it based on the Routes that are defined. As soon as a Route yields a match, the router stops matching and {{site.base_gateway}} uses the matched Route to [proxy the current request](/gateway/traffic-control/proxying/). +{{site.base_gateway}} provides two methods to define Routes: the traditional JSON format, and a more powerful DSL-based expressions format. +The router used is configured via the [`router_flavor`](/gateway/configuration/#router_flavor) property in `kong.conf`. -If multiple Routes match, {{site.base_gateway}} handles routing in the following order: +The router you should use depends on your use case and {{site.base_gateway}} version: +* **[Expressions router](/gateway/routing/expressions/):** The recommended method for anyone running {{site.base_gateway}} 3.4.x or later. Handles complex routing logic efficiently. +* **[Traditional router](/gateway/routing/traditional/):** The original {{ site.base_gateway }} routing configuration format. Provide your matching criteria in JSON format. -1. {{site.base_gateway}} finds Routes that match the request by comparing the defined routing attributes with the attributes in the request. -1. If multiple Routes match, the {{site.base_gateway}} router then orders all defined Routes by their [priority](#priority-matching) and uses the highest priority matching Route to handle a request. +Setting `router_flavor` to `expressions` allows you to configure both expression based and JSON based routing criteria at the same time. If an `expression` route matches, the JSON format router won't run, regardless of the JSON priority set. -{{site.base_gateway}} provides two different routers, enabled via the `router_flavor` property in `kong.conf`. The router you should use depends on your use case and {{site.base_gateway}} version: -* **[Expressions router](/gateway/routing/expressions/):** The recommended method for anyone running {{site.base_gateway}} 3.4.x or later. Can be run in both `traditional_compat` and `expressions` modes. Handles complex routing logic and regex in Routes. -* **Traditional compatibility router:** Only recommended for anyone running {{site.base_gateway}} 2.9.x or earlier. The default routing method for {{site.base_gateway}}. Doesn't handle complex routing logic. +To disable the DSL-based format, set `router_flavor` to `traditional_compat`. Only JSON routes will be accepted with this configuration. -### Path matching +## Routing criteria -Keep the following path matching criteria in mind when configuring paths: +You can match incoming requests against the following routing criteria: + +- Protocols: The protocol used to communicate with the upstream application. +- Hosts: Lists of domains that match a route +- Methods: HTTP methods that match a route +- Headers: Lists of values that are expected in the header of a request +- Port: The request's source/destination port +- SNI: The server name indicated in a TLS request + +For detailed examples of each, see the dedicated [expressions](/gateway/routing/expressions/#how-requests-are-routed-with-the-expressions-router) or [traditional](/gateway/routing/traditional/#routing-criteria) sections. + +## How routing works -* **Regex in paths:** For a path to be considered a regular expression, it must be prefixed with a `~`. You can avoid creating complex regular expressions using the [Router Expressions language](/gateway/routing/expressions/). -* **Capturing groups:** [Regex capture groups](/gateway/routing/expressions/#example-expressions) are also supported, and the matched group will be extracted from the path and available for plugins consumption. -* **Escaping special characters:** When configuring Routes with regex paths via the Admin API, be sure to URL encode your payload if necessary according to [RFC 3986](https://tools.ietf.org/html/rfc3986). -* **Normalization behavior:** To prevent trivial Route match bypass, the incoming request URI from client -is always normalized according to [RFC 3986](https://tools.ietf.org/html/rfc3986) -before router matching occurs. +For each incoming request, {{site.base_gateway}} must determine which Service will handle it based on the Routes that are defined. - Regex Route paths only use methods 1 and 2. In addition, if the decoded character becomes a regex meta character, it will be escaped with backslash. +The {{site.base_gateway}} router orders all defined Routes by their [priority](#priority-matching) and uses the highest priority matching Route to [proxy the request](/gateway/traffic-control/proxying/). ### Priority matching -If multiple Routes match, the {{site.base_gateway}} router then orders all defined Routes by their priority and uses the highest priority matching Route to handle a request. How Routes are prioritized depends on the router mode you're using. +To maximise performance, the {{site.base_gateway}} router orders all defined Routes by their priority and uses the highest priority matching Route to handle a request. How Routes are prioritized depends on the router mode you're using. + +For more information, see the detailed [expressions](/gateway/routing/expressions/#priority-matching) or [traditional](/gateway/routing/traditional/#route-priority) sections. + +### Route behavior + +The Route entity allows you to configure proxy behaviour on a per route basis by setting the `strip_path`, `preserve_host`, and `path_handling` values. + +In most cases, `strip_path` and `preserve_host` should be `false` (this is the default value), and `path_handling` should be set to `v0`. + + + +#### strip_path + + + +It may be desirable to specify a path prefix to match a route, but not +include it in the upstream request. To do so, use the `strip_path` boolean +property by configuring a route like so: + +```json +{ + "paths": ["/service"], + "strip_path": true, + "service": { + "id": "..." + } +} +``` + +Enabling this flag instructs {{site.base_gateway}} that when matching this route, and proceeding +with the proxying to a service, it should **not** include the matched part of +the URL path in the upstream request's URL. For example, the following +client's request to the above route: + +```http +GET /service/path/to/resource HTTP/1.1 +Host: ... +``` + +This causes {{site.base_gateway}} to send the following upstream request: + +```http +GET /path/to/resource HTTP/1.1 +Host: ... +``` + +The same way, if a regex path is defined on a route that has `strip_path` +enabled, the entirety of the request URL matching sequence will be stripped. +For example: + +```json +{ + "paths": ["/version/\d+/service"], + "strip_path": true, + "service": { + "id": "..." + } +} +``` + +The following HTTP request matching the provided regex path: + +```http +GET /version/1/service/path/to/resource HTTP/1.1 +Host: ... +``` + +Is proxied upstream by {{site.base_gateway}} as: -#### Traditional compatibility mode +```http +GET /path/to/resource HTTP/1.1 +Host: ... +``` -In `traditional_compat` mode, the priority of a Route is determined as -follows, by the order of descending significance: + -1. **Priority points:** A priority point is added for every `methods`, `host`, `headers`, and `snis` value that a Route has. Routes with higher priority point values will be considered before those with lower values. -2. **Wildcard hosts:** Among Routes with the same priority point value, Routes without a wildcard host specified (or no host at all) are prioritized before those that have any wildcard host specification. -3. **Header count:** The resulting groups are sorted so the Routes with a higher number of specified headers have higher priority than those with a lower number of headers. -4. **Regular expressions and prefix paths:** Routes that have a regular expression path are considered first and are ordered by their `regex_priority` value. Routes that have no regular expression path are ordered by the length of their paths. -5. **Creation date:** If all of the above are equal, the router chooses the Route that was created first using the Route's `created_at` value. +#### preserve_host -When two Routes have the same path, {{site.base_gateway}} uses a tiebreaker. For example, if the rule count for the given request is the same for both Routes `A` and `B`, then the following tiebreaker rules are applied in the order they are listed. Route `A` will be selected over `B` if: - * `A` has only plain Host headers and `B` has one or more wildcard - host headers - * `A` has more non-Host headers than `B` - * `A` has at least one regex path and `B` has only plain paths - * `A`'s longest path is longer than `B`'s longest path - * `A.created_at < B.created_at` + -#### Expressions router mode +When proxying, {{site.base_gateway}}'s default behavior is to set the upstream request's Host +header to the hostname specified in the service's `host`. The +`preserve_host` field accepts a boolean flag instructing {{site.base_gateway}} not to do so. -In [`expressions` mode](/gateway/routing/expressions/), when a request comes in, {{site.base_gateway}} evaluates Routes with a higher `priority` number first. The priority is a positive integer that defines the order of evaluation of the router. The larger the priority integer, the sooner a Route will be evaluated. In the case of duplicate priority values between two Routes in the same router, their order of evaluation is undefined. +For example, when the `preserve_host` property is not changed and a route is +configured like so: + +```json +{ + "hosts": ["service.com"], + "service": { + "id": "..." + } +} +``` + +A possible request from a client to {{site.base_gateway}} could be: + +```http +GET / HTTP/1.1 +Host: service.com +``` + +{{site.base_gateway}} would extract the Host header value from the service's `host` property, , +and would send the following upstream request: + +```http +GET / HTTP/1.1 +Host: +``` + +However, by explicitly configuring a Route with `preserve_host=true`: + +```json +{ + "hosts": ["service.com"], + "preserve_host": true, + "service": { + "id": "..." + } +} +``` + +And assuming the same request from the client: + +```http +GET / HTTP/1.1 +Host: service.com +``` + +{{site.base_gateway}} would preserve the Host on the client request and would send the following +upstream request instead: + +```http +GET / HTTP/1.1 +Host: service.com +``` + + + +#### path_handling + + + +The `path_handling` parameter accepts `v0` or `v1`. + +* `v0` is the behavior used in Kong 0.x, 2.x, and 3.x. It treats `service.path`, `route.path` and request path as *segments* of a URL. It will always join them via slashes. Given a service path `/s`, route path `/r` and request path `/re`, the concatenated path will be `/s/re`. If the resulting path is a single slash, no further transformation is done to it. If it's longer, then the trailing slash is removed. + +* `v1` is the behavior used in Kong 1.x. It treats `service.path` as a *prefix*, and ignores the initial slashes of the request and route paths. Given service path `/s`, route path `/r` and request path `/re`, the concatenated path will be `/sre`. + +{:.warning} +> `path_handling` v1 is not supported in the `expressions` router and may be removed in a future version of {{ site.base_gateway }}. We **strongly** recommend using `v0`. + +Both versions of the algorithm detect "double slashes" when combining paths, replacing them by single +slashes. + +
+ +Expand this block to see a table showing detailed v0 and v1 examples + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
service.pathroute.pathrequestroute.strip_pathroute.path_handlingrequest pathupstream path
/s/fv0reqfalsev0/fv0/req/s/fv0/req
/s/fv0blankfalsev0/fv0/s/fv0
/s/fv1reqfalsev1/fv1/req/sfv1/req
/s/fv1blankfalsev1/fv1/sfv1
/s/tv0reqtruev0/tv0/req/s/req
/s/tv0blanktruev0/tv0/s
/s/tv1reqtruev1/tv1/req/s/req
/s/tv1blanktruev1/tv1/s
/s/fv0/reqfalsev0/fv0/req/s/fv0/req
/s/fv0/blankfalsev0/fv0//s/fv01/
/s/fv1/reqfalsev1/fv1/req/sfv1/req
/s/fv1/blankfalsev1/fv1//sfv1/
/s/tv0/reqtruev0/tv0/req/s/req
/s/tv0/blanktruev0/tv0//s/
/s/tv1/reqtruev1/tv1/req/sreq
/s/tv1/blanktruev1/tv1//s
+ +
### Routing performance recommendations diff --git a/app/_gateway_entities/service.md b/app/_gateway_entities/service.md index 6b9673c52..097591108 100644 --- a/app/_gateway_entities/service.md +++ b/app/_gateway_entities/service.md @@ -4,7 +4,7 @@ content_type: reference entities: - service -description: A Gateway Service is an abstraction of an upstream application that services requests. +description: A Gateway Service represents your actual backend API or microservice. related_resources: - text: Routes entity @@ -34,17 +34,15 @@ api_specs: ## What is a Gateway Service? -A Gateway Service is an abstraction of an upstream application that services requests. -Services can store collections of objects like plugin configurations, and policies, and they can be associated with routes. +A Gateway Service represents your actual backend API or microservice. -When defining a Service, the administrator provides a name and the upstream application connection information. -The connection details can be provided in the URL field as a single string, or by providing individual values for protocol, host, port, and path individually. +For simple deployments, the upstream URL can be provided directly in the Service. For sophisticated traffic management needs, a Service can point at an [Upstream](/gateway/entities/upstream/). -Gateway Services have a one-to-many relationship with upstream applications, which allows administrators to create sophisticated traffic management behaviors. +Gateway Services, in conjunction with [Routes](/gateway/entities/route/), let you expose your services to clients with {{site.base_gateway}}. -Gateway Services, in conjunction with [Routes](/gateway/entities/route/), let you expose your services to clients with {{site.base_gateway}}. -{{site.base_gateway}} abstracts the service from the clients by using Routes. -Since the client always calls the Route, changes to the Services (like versioning) don't impact how clients make the call. +[Plugins](/gateway/entities/plugin/) can be attached to a Service, and will run against every request that triggers a request to the Service that they're attached to. + + {% mermaid %} flowchart LR @@ -70,6 +68,8 @@ flowchart LR {% endmermaid %} + + ## Schema {% entity_schema %} diff --git a/app/_gateway_entities/target.md b/app/_gateway_entities/target.md index ddf3d2f53..29db28136 100644 --- a/app/_gateway_entities/target.md +++ b/app/_gateway_entities/target.md @@ -28,12 +28,25 @@ schema: ## What is a Target? A Target is an IP address/hostname with a port that identifies an instance of a backend service. -Each [Upstream](/gateway/entities/upstream/) can have many Targets. Targets are used by Upstreams for [load balancing](https://docs.konghq.com/gateway/latest/how-kong-works/load-balancing/). For example, if you have an `example_upstream` Upstream, you can point it to two different Targets: `httpbin.konghq.com` and `httpbun.com`. This is so that if one of the servers (like `httpbin.konghq.com`) is unavailable, it automatically detects the problem and routes all traffic to the working server (`httpbun.com`). +Each [Upstream](/gateway/entities/upstream/) can have many Targets. Targets are used by Upstreams for [load balancing](/gateway/entities/upstream/#load-balancing-algorithms). For example, if you have an `example_upstream` Upstream, you can point it to two different Targets: `httpbin.konghq.com` and `httpbun.com`. This is so that if one of the servers (like `httpbin.konghq.com`) is unavailable, it automatically detects the problem and routes all traffic to the working server (`httpbun.com`). The following diagram illustrates how Targets are used by Upstreams for load balancing: {% include entities/upstreams-targets-diagram.md %} +## Using hostnames + +A `target` can also have a hostname instead of an IP address. +In that case, the name is resolved and all entries found are individually added to the load balancer. + +For example, let's say you add `api.host.com:123` with `weight=100`: + +* If the hostname `api.host.com` resolves to an A record with 2 IP addresses, both IP addresses are added as a target, each with `weight=100` and port 123. +* If the hostname resolves to an SRV record, then the `port` and `weight` fields from the DNS record are used, and override the port and weight set in the Target. + +The balancer honors the DNS record's `ttl` setting. Upon expiry, it queries the nameserver and updates the balancer. +When a DNS record has `ttl=0`, the hostname is added as a single target, with the specified weight. The nameserver is queried for every request, adding latency to the request. + ## Schema {% entity_schema %} diff --git a/app/_gateway_entities/upstream.md b/app/_gateway_entities/upstream.md index 80ce4567e..a22e2b39f 100644 --- a/app/_gateway_entities/upstream.md +++ b/app/_gateway_entities/upstream.md @@ -26,6 +26,8 @@ related_resources: url: /gateway/routing/ - text: Expressions router url: /gateway/routing/expressions/ + - text: Health checks and circuit breakers + url: /gateway/health-checks-circuit-breakers/ schema: api: gateway/admin-ee @@ -34,18 +36,19 @@ schema: ## What is an Upstream? -An Upstream refers to the service applications sitting behind {{site.base_gateway}}, to which client requests are forwarded. In {{site.base_gateway}}, an Upstream represents a virtual hostname and can be used to [health check](https://docs.konghq.com/gateway/latest/how-kong-works/health-checks/#active-health-checks), [circuit break](https://docs.konghq.com/gateway/latest/how-kong-works/health-checks/#passive-health-checks-circuit-breakers), and [load balance](https://docs.konghq.com/gateway/latest/how-kong-works/load-balancing/) incoming requests over multiple [Gateway Services](/gateway/entities/service/). In addition, the Upstream entity has more advanced functionality algorithms like least-connections, consistent-hashing, and lowest-latency. +An Upstream refers to the service applications sitting behind {{site.base_gateway}}, to which client requests are forwarded. +In {{site.base_gateway}}, an Upstream represents a virtual hostname and can be used to [health check](/gateway/health-checks-circuit-breakers/), [circuit break](/gateway/health-checks-circuit-breakers/), and [load balance](#load-balancing-algorithms) incoming requests over multiple [Gateway Services](/gateway/entities/service/). In addition, the Upstream entity has more advanced functionality algorithms like least-connections, consistent-hashing, and lowest-latency. ## Upstream and Gateway Service interaction -You can configure a Service to point to an Upstream instead of a host. -For example, if you have a Service called `example_service` and an Upstream called `example_upstream`, you can point `example_service` to `example_upstream` instead of specifying a host. -The `example_upstream` Upstream can then point to two different [Targets](/gateway/entities/target/): `httpbin.konghq.com` and `httpbun.com`. +You can configure a Service to point to an Upstream instead of a host. +For example, if you have a Service called `example_service` and an Upstream called `example_upstream`, you can point `example_service` to `example_upstream` instead of specifying a host. +The `example_upstream` Upstream can then point to two different [Targets](/gateway/entities/target/): `httpbin.konghq.com` and `httpbun.com`. In a real environment, the Upstream points to the same Service running on multiple systems. -This setup allows you to load balance between upstream targets. -For example, if an application is deployed across two different servers or upstream targets, {{site.base_gateway}} needs to load balance across both servers. -If one of the servers (like `httpbin.konghq.com` in the previous example) is unavailable, it automatically detects the problem and routes all traffic to the working server (`httpbun.com`). +This setup allows you to load balance between upstream targets. +For example, if an application is deployed across two different servers or upstream targets, {{site.base_gateway}} needs to load balance across both servers. +If one of the servers (like `httpbin.konghq.com` in the previous example) is unavailable, it automatically detects the problem and routes all traffic to the working server (`httpbun.com`). The following diagram shows how Upstreams interact with other {{site.base_gateway}} entities: @@ -55,11 +58,111 @@ The following diagram shows how Upstreams interact with other {{site.base_gatewa The following are examples of common use cases for Upstreams: -| Use case | Description | -|----------|-------------| -| Load balance | When an Upstream points to multiple upstream targets, you can configure the Upstream entity to load balance traffic between the targets. If you don't need to load balance, we recommend using the `host` header on a [Route](/gateway/entities/route/) as the preferred method for routing a request and proxying traffic.| -| Health check | Configure Upstreams to dynamically mark a target as healthy or unhealthy. This is an active check where a specific HTTP or HTTPS endpoint in the target is periodically requested and the health of the target is determined based on its response. | -| Circuit break | Configure Upstreams to allow {{site.base_gateway}} to passively analyze the ongoing traffic being proxied and determine the health of targets based on their behavior responding to requests.

**Note:** This feature is not supported in hybrid mode. | +| Use case | Description | +| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Load balance | When an Upstream points to multiple upstream targets, you can configure the Upstream entity to load balance traffic between the targets. If you don't need to load balance, we recommend using the `host` header on a [Route](/gateway/entities/route/) as the preferred method for routing a request and proxying traffic. | +| Health check | Configure Upstreams to dynamically mark a target as healthy or unhealthy. This is an active check where a specific HTTP or HTTPS endpoint in the target is periodically requested and the health of the target is determined based on its response. | +| Circuit break | Configure Upstreams to allow {{site.base_gateway}} to passively analyze the ongoing traffic being proxied and determine the health of targets based on their behavior responding to requests.

**Note:** This feature is not supported in hybrid mode. | + +## Load balancing algorithms + +The load balancer supports the following load-balancing algorithms: + +- `round-robin` +- `consistent-hashing` +- `least-connections` +- `latency` + +### Round-Robin + +The round-robin algorithm is done in a weighted manner. It provides identical +results to the default DNS based load-balancing, but due to it being an `upstream`, +the additional features for health-checks and circuit-breakers are also available. + +When choosing this algorithm, consider the following: + +- Provides good distribution of requests. +- Remains fairly static, as only DNS updates or `target` updates can influence the distribution of traffic. +- Doesn't improve cache-hit ratios. + +### Consistent-Hashing + +With the consistent-hashing algorithm, a configurable client input is used to +calculate a hash value. This hash value is then tied to a specific backend +server. + +A common example would be to use the `consumer` as a hash input. Since this ID is +the same for every request from that user, it ensures that the same user is +handled consistently by the same backend server. This allows for cache +optimizations on the backend, since each of the servers only serves a fixed subset +of the users, and can improve its cache-hit ratio for user-related data. + +This algorithm implements the [ketama principle](https://github.com/RJ/ketama) to +maximize hashing stability and minimize consistency loss upon changes to the list +of known backends. + +The input for the consistent-hashing algorithm can be one of the following options: + +| Option | Description | +|--------|-------------| +| `none` | Doesn't use `consistent-hashing`, uses `round-robin` instead (default). Hashing is disabled. | +| `consumer` | Uses the Consumer ID as the hash input. If no Consumer ID is available, it will fall back on the Credential ID (for example, in case of an external authentication mechanism like LDAP). | +| `ip` | Uses the originating IP address as the hash input. Review the configuration settings for [determining the real IP](/gateway/configuration/#real_ip_config) when using this option. | +| `header` | Uses a specified header as the hash input. The header name is specified in either of the Upstream's `hash_on_header` or `hash_fallback_header` fields, depending on whether `header` is a primary or fallback attribute, respectively. | +| `cookie` | Use a specified cookie with a specified path as the hash input. The cookie name is specified in the Upstream's `hash_on_cookie` field and the path is specified in the Upstream's `hash_on_cookie_path` field. If the specified cookie is not present in the request, it will be set by the response. The generated cookie will have a random UUID value, which is then preserved in the cookie.

The `hash_fallback` setting is invalid and can't be used if `cookie` is the primary hashing mechanism. | + +The `consistent-hashing` algorithm supports a primary and a fallback hashing attribute. +If the primary fails (for example, if the primary is set to `consumer`, but no Consumer is authenticated), +the fallback attribute is used. This maximizes upstream cache hits. + +The consistent-hashing balancer is designed to work both with a single node as well +as in a cluster. + +When choosing this algorithm, consider the following: + +- Improves backend cache-hit ratios. +- Requires enough cardinality in the hash inputs to distribute evenly. For example, hashing on a header that only has 2 possible values doesn't make sense. +- The cookie-based approach works well for browser-based requests, but less so for machine-to-machine (M2M) clients, which will often omit the cookie. +- When using the hashing approach in a Kong cluster, add `target` entities by their IP address, and avoid using hostnames in the balancer. + The balancers will slowly diverge, as the DNS TTL only has second precision, and renewal is determined by when a name is actually requested. + Additionally, some nameservers don't return all entries, which makes the problem worse. + This problem can be mitigated by balancer rebuilds and higher TTL settings. + +### Least-Connections + +The `least-connections` algorithm keeps track of the number of in-flight requests for each backend. +The weights are used to calculate the connection capacity of a backend. Requests are +routed towards the backend with the highest spare capacity. + +When choosing this algorithm, consider the following: + +- Provides good distribution of traffic. +- Doesn't improve cache-hit ratios. +- This option is more dynamic, since slower backends will have more connections open, and + new requests will be routed to other backends automatically. + +### Latency + +The `latency` algorithm is based on peak EWMA (Exponentially Weighted Moving Average), +which ensures that the balancer selects the backend by the lowest latency +(`upstream_response_time`). The latency metric used is the full request cycle, from +TCP connect to body response time. Since it's a moving average, the metrics will +decay over time. + +Target weights aren't taken into account. + +When choosing this algorithm, consider the following: + +- Provides good distribution of traffic, provided there is enough base load to keep the metrics alive, since they are always decaying. +- The algorithm is very dynamic, since it will constantly optimize loads. +- Latency-based load balancing works best with low variance in latencies, meaning mostly similar-shaped traffic and even workloads for the backends. + For example, using this algorithm with a GraphQL backend serving small-fast queries as well big-slow ones will result in high variance in the latency metrics, which will skew the metrics. +- You must properly set up the backend capacity and ensure proper network latency to prevent resource starvation. + For example, you could use 2 servers: a small capacity server close by (low network latency), and a high capacity server far away (high latency). + Most traffic will be routed to the small one until its latency starts going up. + However, the latency going up means the small server is likely suffering from resource starvation. + In this case, the algorithm will keep the small server in a constant state of resource starvation, which is most likely not efficient. +- This option is not suitable for long-lived connections like websockets or server-sent events (SSE). ## Schema @@ -70,6 +173,6 @@ The following are examples of common use cases for Upstreams: {% entity_example %} type: upstream data: - name: example-upstream - algorithm: round-robin -{% endentity_example %} \ No newline at end of file + name: example-upstream + algorithm: round-robin +{% endentity_example %} diff --git a/app/_gateway_entities/vault.md b/app/_gateway_entities/vault.md index 4577d33b7..4f397515d 100644 --- a/app/_gateway_entities/vault.md +++ b/app/_gateway_entities/vault.md @@ -11,9 +11,9 @@ related_resources: url: /secrets-management/ - text: Workspaces url: /gateway/entities/workspace/ - - text: RBAC + - text: RBAC url: /gateway/entities/rbac/ - + faqs: - q: What types of fields can be used in Vaults? @@ -41,9 +41,11 @@ schema: --- ## What is a Vault? -In {{site.base_gateway}}, the Vault object is used to store secrets. A secret is any sensitive piece of information required for API gateway -operations. Secrets can be used as part of the core {{site.base_gateway}} configuration, in plugins, or in configuration associated -with APIs serviced by the gateway. + +Vaults allow you to securely store and then reference secrets from within other entities. This ensures that secrets aren't visible in plaintext throughout the platform, in places such as `kong.conf`, +declarative configuration files, logs, or the UI. + +For example, you could store a certificate and a key in a Vault, then reference them from a [Certificate entity](/gateway/entities/certificate/). This way, the certificate and key are not stored in the entity directly and are more secure. Some of the most common types of secrets used by {{site.base_gateway}} include: @@ -52,20 +54,19 @@ Some of the most common types of secrets used by {{site.base_gateway}} include: * API keys * Sensitive configuration fields, generally used for authentication, hashing, signing, or encryption -## Vault use cases - -Vaults allow you to securely store and then reference secrets from within other entities. This ensures that secrets aren't visible in plaintext throughout the platform, in places such as `kong.conf`, -declarative configuration files, logs, or the UI. - -For example, you could store a certificate and a key in a Vault, then reference them from a [Certificate entity](/gateway/entities/certificate/). This way, the certificate and key are not stored in the entity directly and are more secure. - ## How do I add secrets to a Vault? -You can add secrets to Vaults in one of the following ways: +You can add secrets to Vaults in one of the following ways: * Environment variables * {{site.konnect_short_name}} Config Store * Supported third-party backend vault +## How do I configure access to a Vault? + +Each vault has its own required configuration. You can provide this configuration by creating a Vault entity, or by configuring specific environment variables before starting {{ site.base_gateway }}. + +For more information, choose a Vault below to see the specific configuration required. + ## Supported backends {% feature_table %} @@ -79,8 +80,8 @@ columns: key: supports_konnect features: - - title: Environment variable1 - url: /gateway/entities/vault/#store-secrets-as-environment-variables + - title: Environment variable + url: /gateway/entities/vault/#store-secrets-as-environment-variables oss: true enterprise: true supports_konnect: true @@ -111,8 +112,6 @@ features: supports_konnect: true {% endfeature_table %} -1 You can use environment variables as a Vaults backend either with or without using the Vaults entity. - ## How do I reference secrets stored in a Vault? When you want to use a secret stored in a Vault, you can reference the secret with a `vault` reference. You can use the `vault` reference in places such as `kong.conf`, declarative configuration files, logs, or in the UI. @@ -138,18 +137,39 @@ Would point to a secret object called `pg` inside a HashiCorp Vault, which may r `{vault://hcv/pg/username}`. +Vault references must be used for the whole referenced value. Imagine that you're calling an upstream service with the authentication token `ABC123`: + +{% feature_table %} +item_title: Works +columns: + - title: Configuration Value + key: config + - title: Vault Value + key: vault +features: + - title: ❌ + config: 'Bearer {vault://hcv/myservice-auth-token}' + vault: ABC123 + - title: ✅ + config: '{vault://hcv/myservice-auth-token}' + vault: Bearer ABC123 +{% endfeature_table %} + ## Secret rotation in Vaults -By default, {{site.base_gateway}} automatically rotates secrets *once every minute* in the background. You can also configure how often {{site.base_gateway}} rotates secrets using the Vault entity configuration. +By default, {{site.base_gateway}} automatically refreshes secrets *once every minute* in the background. +You can also configure how often {{site.base_gateway}} refreshes secrets using the Vault entity configuration. -There are two types of rotation configuration available: -* Rotate periodically using TTLs: For example, check for a new TLS certificate once per day. -* Rotate on failure: For example, on a database authentication failure, check if the secrets were updated, and try again. +There are two types of refresh configuration available: +* Refresh periodically using TTLs: For example, check for a new TLS certificate once per day. +* Refresh on failure: For example, on a database authentication failure, check if the secrets were updated, and try again. For more information, see [Secret management](/secrets-management/). ## Best practices for Vaults +@TODO: Move this to deck docs when available + ### General best practices To keep your environment secure and avoid taking down your proxies by accident, make sure to: diff --git a/app/_gateway_entities/workspace.md b/app/_gateway_entities/workspace.md index fe7e90036..097cf6626 100644 --- a/app/_gateway_entities/workspace.md +++ b/app/_gateway_entities/workspace.md @@ -8,9 +8,6 @@ description: Workspaces provide a way to segment {{site.base_gateway}} entities. tools: - admin-api - - kic - - deck - - terraform tier: enterprise schema: @@ -47,13 +44,13 @@ faqs: --- - ## What is a Workspace? Workspaces are a way of namespacing {{site.base_gateway}} entities so they can be managed independently. Workspaces work in combination with RBAC to create isolated environments for teams to operate independently of each other. Workspaces can't share entities, like Services, between them, and only Workspace Admins with the correct permissions, in the Workspace, can manage them. Workspaces support [multi-tenancy](/gateway/multi-tenancy/) by isolating {{site.base_gateway}} configuration objects. When paired with RBAC, {{site.base_gateway}} administrators can effectively create tenants within the control plane. The Workspace administrators have segregated and secure access to only their portion of the {{site.base_gateway}} configuration in Kong Manager, the Admin API, and the declarative configuration tool decK. + {% mermaid %} flowchart LR @@ -80,6 +77,8 @@ flowchart LR {% endmermaid %} + + ### How does {{site.base_gateway}} resolve entity conflicts between Workspaces? Routing rules are configured at the data plane level. The data plane routes client traffic based on the configuration applied across all Workspaces. Configuring entities related to routing, such as [Gateway Services](/gateway/entities/service/) and [Routes](/gateway/entities/route/), alter the client traffic routing behavior of the data plane, but {{site.base_gateway}} will always attempt to ensure that routing rules don't contain conflicts. @@ -88,13 +87,12 @@ To route traffic to the appropriate Workspace, {{site.base_gateway}} uses a conf When a Service or Route is **created** or **modified**, the {{site.base_gateway}} Router checks for the existence of that object before allowing the operation to proceed in this order: -1. If the Service or Route created is totally unique and does not match an existing entity, the new entity is created. -2. If an existing Service or Route object that matches the one being created is found, a `409 Conflict` error is returned. -3. If an equivalent Service or a Route is found in a different Workspace, the new entity is created. -4. If an equivalent Service or Route is found in a different Workspace, and the host is a wildcard: - a. If the host field matches in both Workspaces, a `409 Conflict` error is returned. - b. If the host field does not match, the new entity can be created. - c. If the host is an absolute value, a `409 Conflict` error is returned. +1. If the Service or Route created is unique across all Workspaces, the new entity is created. +1. If an existing Service or Route object that matches the one being created is found in the current Workspace, a `409 Conflict` error is returned. +2. If an equivalent Service or Route is found in a different Workspace, and the host is provided: + 1. If the host field matches in both Workspaces, a `409 Conflict` error is returned. + 1. If the host field does not match, the new entity can be created. + 1. If the host is an absolute value, a `409 Conflict` error is returned. ## Roles, groups, and permissions diff --git a/app/_how-tos/bootstrap-rbac.md b/app/_how-tos/bootstrap-rbac.md index 616760137..e2520c31e 100644 --- a/app/_how-tos/bootstrap-rbac.md +++ b/app/_how-tos/bootstrap-rbac.md @@ -5,6 +5,9 @@ content_type: how_to products: - gateway +tools: + - deck + works_on: - on-prem @@ -19,4 +22,21 @@ min_version: gateway: '3.4' --- -@todo Create a super-admin in KGW set up default workspaces and teams validate isolated workspace. \ No newline at end of file +@todo Create a super-admin in KGW set up default workspaces and teams validate isolated workspace. + +Maybe https://docs.konghq.com/gateway/latest/production/access-control/enable-rbac/ ? + + +## Create an RBAC user + +Creating an RBAC User requires [RBAC to be enabled](#enable-rbac) for {{site.base_gateway}}. + +{% entity_example %} +type: rbac +data: + name: my-user + user_token: exampletoken +headers: + admin-api: + - "Kong-Admin-Token: $ADMIN_TOKEN" +{% endentity_example %} \ No newline at end of file diff --git a/app/_includes/entities/permissions-table.md b/app/_includes/entities/permissions-table.md index 93e17508e..56b28f8aa 100644 --- a/app/_includes/entities/permissions-table.md +++ b/app/_includes/entities/permissions-table.md @@ -4,7 +4,7 @@ By default, when {{site.base_gateway}} is configured, the starting user is confi | Role | Description | | ----------- | ----------- | -| Admin | Full access to all endpoints, across all Workspaces, except the RBAC Admin API | +| `admin` | Full access to all endpoints, across all Workspaces, except the RBAC Admin API | | `super-admin` | Full access to all endpoints, across all Workspaces, ability to assign and modify RBAC permissions. | |`read-only`| Read access to all endpoints, across all Workspaces| diff --git a/app/_landing_pages/gateway/entities.yaml b/app/_landing_pages/gateway/entities.yaml index 7763409e2..2583157cc 100644 --- a/app/_landing_pages/gateway/entities.yaml +++ b/app/_landing_pages/gateway/entities.yaml @@ -66,11 +66,11 @@ rows: - type: entity_card config: entity: ca_certificate + - columns: - blocks: - type: entity_card config: entity: vault - - columns: - blocks: - type: entity_card config: @@ -79,11 +79,6 @@ rows: - type: entity_card config: entity: key-set - - blocks: - - type: entity_card - config: - entity: keyring - - header: type: h2 diff --git a/app/_layouts/with_aside.html b/app/_layouts/with_aside.html index b4cbb6584..9ce5d4a70 100644 --- a/app/_layouts/with_aside.html +++ b/app/_layouts/with_aside.html @@ -24,7 +24,7 @@ {% if page.toc != false %}
- {% include toc.html html=content h_min=2 h_max=2 id='toc' anchor_class='tab-button__vertical scroll-to' class="tabcolumn" %} + {% include toc.html html=content h_min=2 h_max=3 id='toc' anchor_class='tab-button__vertical scroll-to' class="tabcolumn" %}
{% endif %} diff --git a/app/gateway/health-checks-circuit-breakers.md b/app/gateway/health-checks-circuit-breakers.md new file mode 100644 index 000000000..05d6f4c06 --- /dev/null +++ b/app/gateway/health-checks-circuit-breakers.md @@ -0,0 +1,17 @@ +--- +title: Health checks and circuit breakers +content_type: reference +layout: reference + +products: + - gateway + +description: | + Kong supports two kinds of health checks, which can be used separately or in conjunction: active and passive (also known as circuit breakers). + +--- + +@todo + +Use https://docs.konghq.com/gateway/latest/how-kong-works/health-checks/ +Probably need a separate how-to as well - how do you actually enable and use a health check? What entities are involved (Upstream, Targets)? Does any of this info actually belong in the Upstream or Target entity docs? \ No newline at end of file diff --git a/app/_gateway_entities/keyring.md b/app/gateway/keyring.md similarity index 99% rename from app/_gateway_entities/keyring.md rename to app/gateway/keyring.md index 8eeb7bbab..dadc83c95 100644 --- a/app/_gateway_entities/keyring.md +++ b/app/gateway/keyring.md @@ -1,8 +1,10 @@ --- title: Keyring content_type: reference -entities: - - keyring +layout: reference + +products: + - gateway description: | A Keyring is a mechanism that encrypts sensitive data fields, such as consumer secrets, before storing them in the database. diff --git a/app/gateway/ldap-service-directory-mapping.md b/app/gateway/ldap-service-directory-mapping.md new file mode 100644 index 000000000..9ff68f4d9 --- /dev/null +++ b/app/gateway/ldap-service-directory-mapping.md @@ -0,0 +1,19 @@ +--- +title: LDAP Service Directory Mapping +content_type: reference +layout: reference + +products: + - gateway + +description: | + Service directory mapping allows organizations to use their LDAP Directory for authentication and authorization in {{site.base_gateway}}. + +tier: enterprise + +--- + +@todo + +Use https://docs.konghq.com/gateway/latest/kong-manager/auth/ldap/service-directory-mapping/ +Probably need a separate how-to as well. \ No newline at end of file diff --git a/app/gateway/routing/expressions.md b/app/gateway/routing/expressions.md index 9a12216b4..4c5287bdb 100644 --- a/app/gateway/routing/expressions.md +++ b/app/gateway/routing/expressions.md @@ -14,6 +14,8 @@ related_resources: url: /gateway/entities/route/ - text: Expressions repository url: https://github.com/Kong/atc-router + - text: Traditional router + url: /gateway/routing/traditional/ min_version: gateway: '3.0' @@ -22,11 +24,15 @@ breadcrumbs: - /gateway/ faqs: - - q: When should I use the expressions router in place of (or alongside) the traditional router? - a: We recommend using the expressions router if you are running {{site.base_gateway}} 3.0.x or later. After enabling expressions, traditional match fields on the Route object (such as `paths` and `methods`) remain configurable. You may specify Expressions in the new `expression` field. However, these cannot be configured simultaneously with traditional match fields. Additionally, a new `priority` field, used in conjunction with the expression field, allows you to specify the order of evaluation for Expression Routes. + - q: Is there a performance difference between the traditional router and expressions? + a: Both traditional and expressions modes use the same routing engine internally. Traditional mode configures routes with JSON, and expressions uses a DSL. + - q: Why would I choose expressions over the traditional router? + a: The expressions router provides more routing flexibility, including fast exact matching that is not available in the traditional router. + - q: When should I keep using the traditional router over expressions? + a: If you are working with APIOps pipelines that manipulate the route using `deck file patch`, we recommend using the JSON format used by the traditional router. --- -The expressions router is a collection of [Routes](/gateway/entities/route/) that are all evaluated against incoming requests until a match can be found. This allows for more complex routing logic than the traditional router and ensures good runtime matching performance. +The expressions router provides a Domain Specific Language (DSL) that allows for complex routing rule definition. The expressions router ensures good runtime matching performance by providing specific routing comparisons such as non-regex equality checks that are not available in the traditional router. You can do the following with the expressions router: * Prefix-based path matching @@ -43,10 +49,9 @@ In your `kong.conf` file, set `router_flavor = expressions` and restart your {{s ## How requests are routed with the expressions router -At runtime, {{site.base_gateway}} builds two separate routers for the HTTP and Stream (TCP, TLS, UDP) subsystem. When a request/connection comes in, {{site.base_gateway}} looks at which field your configured Routes require, -and supplies the value of these fields to the router execution context. -Routes are inserted into each router with the appropriate `priority` field set. The priority is a positive integer that defines the order of evaluation of the router. The bigger the priority, the sooner a Route will be evaluated. In the case of duplicate priority values between two Routes in the same router, their order of evaluation is undefined. The router is -updated incrementally as configured Routes change. +At runtime, {{site.base_gateway}} builds two separate routers for the HTTP and Stream (TCP, TLS, UDP) subsystem. When a request/connection comes in, {{site.base_gateway}} looks at which field your configured Routes require, and supplies the value of these fields to the router execution context. + +Routes are inserted into each router with the appropriate `priority` field set. The priority is a positive integer that defines the order of evaluation of the router. The bigger the priority, the sooner a Route is evaluated. In the case of duplicate priority values between two Routes in the same router, their order of evaluation is undefined. The router is updated incrementally as configured Routes change. As soon as a Route yields a match, the router stops matching and the matched Route is used to process the current request/connection. @@ -85,7 +90,7 @@ This section explains how to optimize the expressions you write to get the most ### Number of routes -#### Route matching priority order +#### Priority matching Expressions routes are always evaluated in the descending `priority` order they were defined. Therefore, it is helpful to put more likely matched routes before (as in, higher priority) @@ -166,7 +171,7 @@ http.path == "/foo/bar" || http.path == "/foo/bar/" http.path ~ r#"^/foo/?$"# ``` -## Expressions router reference +## Expressions router reference This reference explains the different configurable entities for the expressions router. @@ -257,13 +262,13 @@ features: -In addition, expressions also supports one composite type, `Array`. Array types are written as `Type[]`. +In addition, the expressions router also supports one composite type, `Array`. Array types are written as `Type[]`. For example: `String[]`, `Int[]`. Currently, arrays can only be present in field values. They are used in case one field could contain multiple values. For example, `http.headers.x` or `http.queries.x`. #### Matching fields -The following table describes the available matching fields, as well as their associated type when using an expressions based router. +The following table describes the available matching fields, as well as their associated type when using an expressions-based router. @@ -398,9 +403,9 @@ The expressions language supports a rich set of operators that can be performed | `>` | Greater than | Field value is greater than the constant value | | `<=` | Less than or equal | Field value is less than or equal to the constant value | | `<` | Less than | Field value is less than the constant value | -| `in` | In | Field value is inside the constant value. This operator is used with `IpAddr` and `IpCidr` types to perform an efficient IP list check. For example, `net.src.ip in 192.168.0.0/24` will only return `true` if the value of `net.src.ip` is within `192.168.0.0/24`. | -| `not in` | Not in | Field value is not inside the constant value. This operator is used with `IpAddr` and `IpCidr` types to perform an efficient IP list check. For example, `net.src.ip in 192.168.0.0/24` will only return `true` if the value of `net.src.ip` is within `192.168.0.0/24`. | -| `contains` | Contains | Field value contains the constant value. This operator is used to check the existence of a string inside another string. For example, `http.path contains "foo"` will return `true` if `foo` can be found anywhere inside `http.path`. This will match a `http.path` that looks like `/foo`, `/abc/foo`, or `/xfooy`, for example. | +| `in` | In | Field value is inside the constant value. This operator is used with `IpAddr` and `IpCidr` types to perform an efficient IP list check. For example, `net.src.ip in 192.168.0.0/24` only returns `true` if the value of `net.src.ip` is within `192.168.0.0/24`. | +| `not in` | Not in | Field value is not inside the constant value. This operator is used with `IpAddr` and `IpCidr` types to perform an efficient IP list check. For example, `net.src.ip in 192.168.0.0/24` only returns `true` if the value of `net.src.ip` is within `192.168.0.0/24`. | +| `contains` | Contains | Field value contains the constant value. This operator is used to check the existence of a string inside another string. For example, `http.path contains "foo"` returns `true` if `foo` can be found anywhere inside `http.path`. This will match a `http.path` that looks like `/foo`, `/abc/foo`, or `/xfooy`, for example. | | `&&` | And | Returns `true` if **both** expressions on the left and right side evaluates to `true` | | `||` | Or | Returns `true` if **any** expressions on the left and right side evaluates to `true` | | | `(Expression)` | Parenthesis | Groups expressions together to be evaluated first | @@ -442,9 +447,9 @@ Depending on the field type, only certain content types and operators are suppor | Prefix based path matching | `http.path ^= "/foo/bar"` | Matches HTTP requests that have a path starting with `/foo/bar` | | Regex based path matching | `http.path ~ r#"/foo/bar/\d+"#` | N/A | | Case insensitive path matching | `lower(http.path) == "/foo/bar"` | Ignores case when performing the path match. | -| Match by header value ("all" style matching) | `http.headers.x_foo ~ r#"bar\d"#` | If there are multiple header values for `X-Foo` and the client sends more than one `X-Foo` header with different values, the above example will ensure **each** instance of the value will match the regex `r#"bar\d"#`. This is called "all" style matching. | +| Match by header value ("all" style matching) | `http.headers.x_foo ~ r#"bar\d"#` | If there are multiple header values for `X-Foo` and the client sends more than one `X-Foo` header with different values, the above example ensures that **each** instance of the value matches the regex `r#"bar\d"#`. This is called "all" style matching. | | Match by header value ("any" style matching) | `any(http.headers.x_foo) ~ r#"bar\d"#` | Returns `true` for the predicate as soon as any of the values pass the comparison. Can be combined with other transformations, like `lower()`. | -| Regex captures | `http.path ~ r#"/foo/(?P.+)"#` | You can define regex capture groups in any regex operation which will be made available later for plugins to use. Currently, this is only supported with the `http.path` field. The matched value of `component` will be made available later to plugins such as [Request Transformer Advanced](/plugins/request-transformer-advanced/). | +| Regex captures | `http.path ~ r#"/foo/(?P.+)"#` | You can define regex capture groups in any regex operation, which will be made available later for plugins to use. Currently, this is only supported with the `http.path` field. The matched value of `component` will be made available later to plugins such as [Request Transformer Advanced](/plugins/request-transformer-advanced/). | ### TCP, TLS, and UDP examples diff --git a/app/gateway/routing/traditional.md b/app/gateway/routing/traditional.md new file mode 100644 index 000000000..52e4d8250 --- /dev/null +++ b/app/gateway/routing/traditional.md @@ -0,0 +1,540 @@ +--- +title: Traditional router + +description: "The traditional router is a collection of Routes that are all evaluated against incoming requests until a match can be found." + +content_type: reference +layout: reference + +products: + - gateway + +related_resources: + - text: Route entity + url: /gateway/entities/route/ + - text: SNI entity + url: /gateway/entities/sni/ + - text: Expressions router + url: /gateway/routing/expressions/ + +min_version: + gateway: "3.0" + +breadcrumbs: + - /gateway/ + +faqs: + - q: When should I use the traditional router? + a: | + If you are working with APIOps pipelines that manipulate the route using `deck file patch`, we recommend using the JSON format used by the traditional router. + +--- + +The traditional router is {{ site.base_gateway }}'s original routing configuration format. It uses JSON to provide a list of routing criteria, including `host`, `path`, and `headers`. + +Routing based on JSON configuration is available when [`router_flavor`](/gateway/configuration/#router_flavor) is set to `traditional_compat` _or_ `expressions` in `kong.conf`. + +## Routing criteria + +{{site.base_gateway}} supports native proxying of HTTP/HTTPS, TCP/TLS, and GRPC/GRPCS protocols. +Each of these protocols accept a different set of routing attributes: + +- `http`: `methods`, `hosts`, `headers`, `paths` (and `snis`, if `https`) +- `tcp`: `sources`, `destinations` (and `snis`, if `tls`) +- `grpc`: `hosts`, `headers`, `paths` (and `snis`, if `grpcs`) + +Note that all of these fields are **optional**, but at least **one of them** +must be specified. + +For a request to match a route: + +- The request **must** include **all** of the configured fields +- The values of the fields in the request **must** match at least one of the + configured values. While the field configurations accept one or more values, + a request needs only one of the values to be considered a match. + +Let's go through a few examples. Consider a route configured like the following: + +```json +{ + "hosts": ["example.com", "foo-service.com"], + "paths": ["/foo", "/bar"], + "methods": ["GET"] +} +``` + +Some of the possible requests matching this route would look like the following: + +```http +GET /foo HTTP/1.1 +Host: example.com +``` + +```http +GET /bar HTTP/1.1 +Host: foo-service.com +``` + +```http +GET /foo/hello/world HTTP/1.1 +Host: example.com +``` + +All three of these requests satisfy all the conditions set in the route +definition. + +However, the following requests would **not** match the configured conditions: + +```http +GET / HTTP/1.1 +Host: example.com +``` + +```http +POST /foo HTTP/1.1 +Host: example.com +``` + +```http +GET /foo HTTP/1.1 +Host: foo.com +``` + +All three of these requests satisfy only two of configured conditions. The +first request's path is not a match for any of the configured `paths`, same for +the second request's HTTP method, and the third request's Host header. + +Now that we understand how the routing properties work together, let's explore +each property individually. + +### Host header + +{{site.base_gateway}} supports routing by arbitrary HTTP headers. A special case of this +feature is routing by the Host header. + +Routing a request based on its Host header is the most straightforward way to +proxy traffic through {{site.base_gateway}}, especially since this is the intended usage of the +HTTP Host header. {{site.base_gateway}} makes it easy to do via the `hosts` field of the route +entity. + +`hosts` accepts multiple values, which must be comma-separated when specifying +them via the Admin API: + +```bash +curl -i -X POST http://localhost:8001/routes/ \ + --header 'Content-Type: application/json' \ + --data '{"hosts":["example.com", "foo-service.com"]}' +``` + +To satisfy the `hosts` condition of this route, any incoming request from a +client must now have its Host header set to one of: + +``` +Host: example.com +``` + +or: + +``` +Host: foo-service.com +``` + +Similarly, any other header can be used for routing: + +```sh +curl -i -X POST http://localhost:8001/routes/ \ + --data 'headers.region=north' +``` + +Incoming requests containing a `Region` header set to `North` are routed to +said route. + +#### Using wildcard hostnames + +To provide flexibility, {{site.base_gateway}} allows you to specify hostnames with wildcards in +the `hosts` field. Wildcard hostnames allow any matching Host header to satisfy +the condition, and thus match a given Route. + +Wildcard hostnames **must** contain **only one** asterisk at the leftmost +**or** rightmost label of the domain. For example: + +- `*.example.com` would allow Host values such as `a.example.com` and + `x.y.example.com` to match. +- `example.*` would allow Host values such as `example.com` and `example.org` + to match. + +A complete example would look like this: + +```json +{ + "hosts": ["*.example.com", "service.com"] +} +``` + +Which would allow the following requests to match this route: + +```http +GET / HTTP/1.1 +Host: an.example.com +``` + +```http +GET / HTTP/1.1 +Host: service.com +``` + +### Headers + +It's possible to route requests by other headers besides `Host`. + +To do this, use the `headers` property in your route: + +```json +{ + "headers": { "version": ["v1", "v2"] }, + "service": { + "id": "..." + } +} +``` + +Given a request with a header such as: + +```http +GET / HTTP/1.1 +version: v1 +``` + +This request will be routed through to the Service. The same happens with this one: + +```http +GET / HTTP/1.1 +version: v2 +``` + +This request isn't routed to the Service: + +```http +GET / HTTP/1.1 +version: v3 +``` + +{:.info} +> **Note**: The `headers` keys are a logical `AND` and their values a logical `OR`. + +### Path + +Another way for a route to be matched is via request paths. To satisfy this +routing condition, a client request's normalized path **must** be prefixed with one of the +values of the `paths` attribute. + +For example, with a route configured like so: + +```json +{ + "paths": ["/service", "/hello/world"] +} +``` + +The following requests would be matched: + +```http +GET /service HTTP/1.1 +Host: example.com +``` + +```http +GET /service/resource?param=value HTTP/1.1 +Host: example.com +``` + +```http +GET /hello/world/resource HTTP/1.1 +Host: anything.com +``` + +For each of these requests, {{site.base_gateway}} detects that their normalized URL path is prefixed with +one of the routes' `paths` values. By default, {{site.base_gateway}} would then proxy the +request upstream without changing the URL path. + +When proxying with path prefixes, **the longest paths get evaluated first**. +This allows you to define two routes with two paths, such as `/service` and +`/service/resource`, and ensure that the former doesn't overshadow the latter. + +#### Using regex in paths + +For a path to be considered a regular expression, it must be prefixed with a `~`: + +``` +paths: ["~/foo/bar$"] +``` + +Any path that isn't prefixed with a `~` is considered plain text: + +``` +"paths": ["/users/\d+/profile", "/following"] +``` + +For more information about how the router processes regular expressions, see the [routing performance considerations](/gateway/entities/route/#routing-performance-recommendations). + +##### Regex evaluation order + +The router evaluates routes using the `regex_priority` field of the +`Route` where a route is configured. Higher `regex_priority` values +mean higher priority. + +```json +[ + { + "paths": ["~/status/d+"], + "regex_priority": 0 + }, + { + "paths": ["~/version/d+/status/d+"], + "regex_priority": 6 + }, + { + "paths": ["/version"] + }, + { + "paths": ["~/version/any/"] + } +] +``` + +In this scenario, {{site.base_gateway}} evaluates incoming requests against the following +defined URIs, in this order: + +1. `/version/\d+/status/\d+` +2. `/status/\d+` +3. `/version/any/` +4. `/version` + +Routers with a large number of regexes can consume traffic intended for other rules. +Regular expressions are much more expensive to build and execute and can't be optimized easily. +You can avoid creating complex regular expressions using the [Router Expressions language](/gateway/routing/expressions/). + +If you see unexpected behavior, use the Kong debug header to help track down the source: + +1. In `kong.conf`, set [`allow_debug_header=on`](/gateway/configuration/#allow_debug_header). +1. Send `Kong-Debug: 1` in your request headers to indicate the matched route ID in the response headers for + troubleshooting purposes. + +As usual, a request must still match a Route's `hosts` and `methods` properties +as well, and {{site.base_gateway}} traverses your Routes until it finds one that [matches +the most rules](#route-priority). + +##### Capture groups + +Capture groups are also supported, and the matched group will be extracted +from the path and available for plugins consumption. Consider the +following regex: + +``` +/version/(?\d+)/users/(?\S+) +``` + +And the following request path: + +``` +/version/1/users/john +``` + +{{site.base_gateway}} considers the request path a match, and if the overall Route is +matched (considering other routing attributes), the extracted capture groups +will be available from the plugins in the `ngx.ctx` variable: + +```lua +local router_matches = ngx.ctx.router_matches + +-- router_matches.uri_captures is: +-- { "1", "john", version = "1", user = "john" } +``` + +#### Path matching + +Keep the following path matching criteria in mind when configuring paths: + +1. **Regex in paths:** For a path to be considered a regular expression, it must be prefixed with a `~`. +You can avoid creating complex regular expressions using the [Router Expressions language](/gateway/routing/expressions/). +1. **Capture groups:** [Regex capture groups](/gateway/routing/expressions/#example-expressions) are also supported, and the matched group is extracted from the path and available for plugin consumption. +1. **Escaping special characters:** When configuring Routes with regex paths via the Admin API, be sure to URL encode your payload if necessary according to [RFC 3986](https://tools.ietf.org/html/rfc3986). +1. **Normalization behavior:** To prevent Route match bypasses, the incoming request URI from the client is always normalized according to [RFC 3986](https://tools.ietf.org/html/rfc3986) before router matching occurs. + +#### Path normalization + +To prevent trivial route match bypass, the incoming request URI from the client +is always normalized according to [RFC 3986](https://tools.ietf.org/html/rfc3986) +before router matching occurs. Specifically, the following normalization techniques are +used for incoming request URIs, which are selected because they generally don't change +semantics of the request URI: + +1. Percent-encoded triplets are converted to uppercase. For example: `/foo%3a` becomes `/foo%3A`. +2. Percent-encoded triplets of unreserved characters are decoded. For example: `/fo%6F` becomes `/foo`. +3. Dot segments are removed as necessary. For example: `/foo/./bar/../baz` becomes `/foo/baz`. +4. Duplicate slashes are merged. For example: `/foo//bar` becomes `/foo/bar`. + +The values in the `paths` attribute of the Route object are also normalized. This is achieved by first determining +if the path is a plain text or regex path. Based on the result, different normalization techniques +are used: +* Plain text route path: Uses the same normalization technique as above, that is, methods 1 through 4. +* Regex route path: Only uses methods 1 and 2. In addition, if the decoded character becomes a regex +meta character, it will be escaped with a backslash. + +{{site.base_gateway}} normalizes any incoming request URI before performing router +matches. As a result, any request URI sent over to the upstream services will also +be in normalized form, which preserves the original URI semantics. + +### HTTP method + +The `methods` field allows matching the requests depending on their HTTP +method. It accepts multiple values. Its default value is empty, where the HTTP +method is not used for routing. + +The following route allows routing via `GET` and `HEAD`: + +```json +{ + "methods": ["GET", "HEAD"], + "service": { + "id": "..." + } +} +``` + +This route would be matched with the following requests: + +```http +GET / HTTP/1.1 +Host: ... +``` + +```http +HEAD /resource HTTP/1.1 +Host: ... +``` + +This route wouldn't match a `POST` or `DELETE` request. This allows for much more +granularity when configuring plugins on Routes. For example, you might have two routes pointing to the same service: +one with unlimited unauthenticated `GET` requests, and a second one allowing only authenticated and rate-limited +`POST` requests (by applying the authentication and rate limiting plugins to +those requests). + +### Source + +{:.info} +> **Note:** This section only applies to TCP and TLS routes. + +The `sources` routing attribute allows +matching a route by a list of incoming connection IP and/or port sources. + +The following route allows routing via a list of source IP/ports: + +```json +{ + "protocols": ["tcp", "tls"], + "sources": [ + { "ip": "10.1.0.0/16", "port": 1234 }, + { "ip": "10.2.2.2" }, + { "port": 9123 } + ], + "id": "..." +} +``` + +TCP or TLS connections originating from IPs in CIDR range "10.1.0.0/16" or IP +address "10.2.2.2" or Port "9123" would match such route. + +### Destination + +{:.info} +> **Note:** This section only applies to TCP and TLS routes. + +The `destinations` attribute, similarly to `sources`, +allows matching a route by a list of incoming connection IP and/or port, but +uses the destination of the TCP/TLS connection as routing attribute. + +### SNI + +When using secure protocols (`https`, `grpcs`, or `tls`), a +[Server Name Indication](/gateway/entities/sni/) can be used as a routing attribute. +The following route allows routing via SNIs: + +```json +{ + "snis": ["foo.test", "example.com"], + "id": "..." +} +``` + +Incoming requests with a matching hostname set in the TLS connection's SNI +extension would be routed to this route. +SNI routing also applies to other protocols carried over TLS, such as HTTPS. +If multiple SNIs are specified in the route, any of them can match the incoming request's SNI. + +The SNI is indicated at TLS handshake time and can't be modified after the TLS connection has +been established. This means, for example, that multiple requests reusing the same keepalive connection +will have the same SNI hostname while performing router matches, regardless of the value in the `Host` header. + +## Route priority + +In `traditional_compat` mode, the priority of a Route is determined as follows, by the order of descending significance: + +1. **Priority points:** A priority point is added for every `methods`, `host`, `headers`, and `snis` value that a Route has. +Routes with higher priority point values are considered before those with lower values. +2. **Wildcard hosts:** Among Routes with the same priority point value, Routes without a wildcard host specified (or no host at all) are prioritized before those that have any wildcard host specification. +3. **Header count:** The resulting groups are sorted so the Routes with a higher number of specified headers have higher priority than those with a lower number of headers. +4. **Regular expressions and prefix paths:** Routes that have a regular expression path are considered first and are ordered by their `regex_priority` value. +Routes that have no regular expression path are ordered by the length of their paths. +5. **Creation date:** If all of the above are equal, the router chooses the Route that was created first using the Route's `created_at` value. + +For example, if two Routes are configured like so: + +```json +{ + "hosts": ["example.com"], + "service": { + "id": "..." + } +}, +{ + "hosts": ["example.com"], + "methods": ["POST"], + "service": { + "id": "..." + } +} +``` + +The second route has a `hosts` field **and** a `methods` field, so it is +evaluated first by {{site.base_gateway}}. By doing so, we avoid the first route "shadowing" +calls intended for the second one. + +Thus, this request matches the first route: + +```http +GET / HTTP/1.1 +Host: example.com +``` + +And this request matches the second one: + +```http +POST / HTTP/1.1 +Host: example.com +``` + +Following this logic, if a third route was to be configured with a `hosts` +field, a `methods` field, and a `paths` field, it would be evaluated first by +{{site.base_gateway}}. + +If the rule count for the given request is the same in two routes `A` and +`B`, then the following tiebreaker rules will be applied in the order they +are listed. Route `A` will be selected over `B` if: + +- `A` has only plain Host headers and `B` has one or more wildcard + host headers +- `A` has more non-Host headers than `B` +- `A` has at least one regex path and `B` has only plain paths +- `A`'s longest path is longer than `B`'s longest path +- `A.created_at < B.created_at`