+
+---
+
+[clustering]: /enterprise/{{page.kong_version}}/clustering
+[cli]: /enterprise/{{page.kong_version}}/cli
+[active]: /enterprise/{{page.kong_version}}/health-checks-circuit-breakers/#active-health-checks
+[healthchecks]: /enterprise/{{page.kong_version}}/health-checks-circuit-breakers
+[secure-admin-api]: /enterprise/{{page.kong_version}}/secure-admin-api
+[proxy-reference]: /enterprise/{{page.kong_version}}/proxy
+
diff --git a/app/enterprise/0.36-x/admin-api/rbac/reference.md b/app/enterprise/0.36-x/admin-api/rbac/reference.md
index 5ca178b74a59..eeeca7f6954d 100644
--- a/app/enterprise/0.36-x/admin-api/rbac/reference.md
+++ b/app/enterprise/0.36-x/admin-api/rbac/reference.md
@@ -1,5 +1,7 @@
---
title: RBAC Reference
+redirect_from:
+ - /enterprise/latest/setting-up-admin-api-rbac
book: rbac
---
@@ -18,26 +20,25 @@ There are 4 basic entities involving RBAC.
`developer`.
- **role_endpoint**: A set of enabled or disabled (see `negative`
parameter) actions (`read`, `create`, `update`, `delete`)
- `endpoint`. Example: Role `developer` has 1 role_endpoint: `read &
- write` to endpoint `/routes`
+ `endpoint`. Example: Role `developer` has 1 role_endpoint: `read & write` to endpoint `/routes`
- **role_entity**: A set of enabled or disabled (see `negative`
parameter) actions (`read`, `create`, `update`, `delete`)
- `entity`. Example: Role `developer` has 1 role_entity: `read & write
- & delete` to entity `283fccff-2d4f-49a9-8730-dc8b71ec2245`.
+ `entity`. Example: Role `developer` has 1 role_entity: `read & write & delete` to entity `283fccff-2d4f-49a9-8730-dc8b71ec2245`.
## Add a User
+
**Endpoint**
/rbac/users
**Request Body**
-| Attribute | Description |
-| --------- | ----------- |
-| `name` | The RBAC user name. |
-| `user_token` | The authentication token to be presented to the Admin API. The value will be hashed and cannot be fetched in plaintext. |
-| `enabled`
optional | A flag to enable or disable the user. By default, users are enabled. |
-| `comment`
optional | A string describing the RBAC user object. |
+| Attribute | Description |
+| --------------------- | ----------------------------------------------------------------------------------------------------------------------- |
+| `name` | The RBAC user name. |
+| `user_token` | The authentication token to be presented to the Admin API. The value will be hashed and cannot be fetched in plaintext. |
+| `enabled`
optional | A flag to enable or disable the user. By default, users are enabled. |
+| `comment`
optional | A string describing the RBAC user object. |
**Response**
@@ -56,15 +57,17 @@ HTTP 201 Created
"user_token_ident": "4d870"
}
```
-___
+
+---
## Retrieve a User
+
**Endpoint**
/rbac/users/{name_or_id}
| Attribute | Description |
-| --------- | ----------- |
+| ------------ | --------------------------- |
| `name_or_id` | The RBAC user name or UUID. |
**Response**
@@ -83,9 +86,11 @@ HTTP 200 OK
"user_token_ident": "4d870"
}
```
-___
+
+---
## List Users
+
**Endpoint**
/rbac/users/
@@ -122,26 +127,27 @@ HTTP 200 OK
}
```
-⚠️ **Note**: **RBAC Users** associated with **Admins** will _not_ be
-listed with **`GET`** `/rbac/users`. Instead, use
-[**`GET`** `/admins`](/enterprise/{{page.kong_version}}/admin-api/admins/reference/#list-admins)
+⚠️ **Note**: **RBAC Users** associated with **Admins** will _not_ be
+listed with **`GET`** `/rbac/users`. Instead, use
+[**`GET`** `/admins`](/enterprise/{{page.kong_version}}/admin-api/admins/reference/#list-admins)
to list all **Admins**.
-___
+---
## Update a User
+
**Endpoint**
/rbac/users/{name_or_id}
| Attribute | Description |
-| --------- | ----------- |
+| ------------ | --------------------------- |
| `name_or_id` | The RBAC user name or UUID. |
**Request Body**
| Attribute | Description |
-| --------- | ----------- |
+| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- |
| `user_token`
optional | The authentication token to be presented to the Admin API. If this value is not present, the token will automatically be generated. |
| `enabled`
optional | A flag to enable or disable the user. By default, users are enabled. |
| `comment`
optional | A string describing the RBAC user object. |
@@ -163,15 +169,17 @@ HTTP 200 OK
"user_token_ident": "4d870"
}
```
-___
+
+---
## Delete a User
+
**Endpoint**
/rbac/users/{name_or_id}
| Attribute | Description |
-| --------- | ----------- |
+| ------------ | --------------------------- |
| `name_or_id` | The RBAC user name or UUID. |
**Response**
@@ -179,15 +187,17 @@ ___
```
HTTP 204 No Content
```
-___
+
+---
## Add a Role
+
**Endpoint**
/rbac/roles
| Attribute | Description |
-| --------- | ----------- |
+| --------------------- | ----------------------------------------- |
| `name` | The RBAC role name. |
| `comment`
optional | A string describing the RBAC user object. |
@@ -206,15 +216,17 @@ HTTP 201 Created
"name": "service_reader"
}
```
-___
+
+---
## Retrieve a Role
+
Endpoint
/rbac/roles/{name_or_id}
| Attribute | Description |
-| --------- | ----------- |
+| ------------ | --------------------------- |
| `name_or_id` | The RBAC role name or UUID. |
**Response**
@@ -231,9 +243,11 @@ HTTP 200 OK
"name": "service_reader"
}
```
-___
+
+---
## List Roles
+
**Endpoint**
/rbac/roles
@@ -275,9 +289,11 @@ HTTP 200 OK
"next": null
}
```
-___
+
+---
## Update or Create a Role
+
**Endpoint**
/rbac/roles
@@ -285,7 +301,7 @@ ___
**Request Body**
| Attribute | Description |
-| --------- | ----------- |
+| --------------------- | ----------------------------------------- |
| `name` | The RBAC role name. |
| `comment`
optional | A string describing the RBAC user object. |
@@ -293,8 +309,7 @@ The behavior of `PUT` endpoints is the following: if the request payload **does
not** contain an entity's primary key (`id` for Users), the entity will be
created with the given payload. If the request payload **does** contain an
entity's primary key, the payload will "replace" the entity specified by the
-given primary key. If the primary key is **not** that of an existing entity, `404
-NOT FOUND` will be returned.
+given primary key. If the primary key is **not** that of an existing entity, `404 NOT FOUND` will be returned.
**Response**
@@ -321,18 +336,19 @@ HTTP 200 OK
```
## Update a Role
+
**Endpoint**
/rbac/roles/{name_or_id}
-| Attribute | Description |
-| --------- | ----------- |
+| Attribute | Description |
+| ------------ | ---------------------- |
| `name_or_id` | The RBAC role or UUID. |
**Request Body**
| Attribute | Description |
-| --------- | ----------- |
+| --------------------- | ----------------------------------------- |
| `comment`
optional | A string describing the RBAC role object. |
**Response**
@@ -350,40 +366,42 @@ HTTP 200 OK
"name": "service_reader"
}
```
-___
+
+---
## Delete a Role
+
**Endpoint**
/rbac/role/{name_or_id}
-| Attribute | Description |
-| --------- | ----------- |
-| `name` | The RBAC role name. |
+| Attribute | Description |
+| --------- | ------------------- |
+| `name` | The RBAC role name. |
**Response**
```
HTTP 204 No Content
```
-___
+
+---
## Add a Role Endpoint Permission
+
**Endpoint**
/rbac/roles/{name_or_id}/endpoints
-
-| Attribute | Description |
-| --------- | ----------- |
-| `name_or_id` | The RBAC role name. |
-
+| Attribute | Description |
+| ------------ | ------------------- |
+| `name_or_id` | The RBAC role name. |
**Request Body**
| Attribute | Description |
-| --------- | ----------- |
-| `workspace` | Workspace tied to the endpoint. Defaults to the default permission. Special value of "*" means **all** workspaces are affected |
+| --------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
+| `workspace` | Workspace tied to the endpoint. Defaults to the default permission. Special value of "\*" means **all** workspaces are affected |
| `endpoint` | Endpoint associated with this permission. |
| `negative` | If true, explicitly disallow the actions associated with the permissions tied to this endpoint. By default this value is false. |
| `actions` | One or more actions associated with this permission. This is a comma separated string (read,create,update,delete) |
@@ -393,12 +411,13 @@ ___
exact matches, or contain wildcards, represented by `*`.
- Exact matches; eg:
- * /apis/
- * /apis/foo
+
+ - /apis/
+ - /apis/foo
- Wildcards; eg:
- * /apis/*
- * /apis/*/plugins
+ - /apis/\*
+ - /apis/\*/plugins
Where `*` replaces exactly one segment between slashes (or the end of
the path).
@@ -414,12 +433,7 @@ HTTP 201 Created
```json
{
- "actions": [
- "delete",
- "create",
- "update",
- "read"
- ],
+ "actions": ["delete", "create", "update", "read"],
"created_at": 1557764505,
"endpoint": "/consumers",
"negative": false,
@@ -433,12 +447,13 @@ HTTP 201 Created
---
## Retrieve a Role Endpoint Permission
+
**Endpoint**
/rbac/roles/{name_or_id}/endpoints/{worspace_name_or_id}/{endpoint}
| Attribute | Description |
-| --------- | ----------- |
+| --------------------- | -------------------------------------------- |
| `name_or_id` | The RBAC role name or UUID. |
| `worspace_name_or_id` | The worspace name or UUID. |
| `endpoint` | The endpoint associated with this permisson. |
@@ -451,12 +466,7 @@ HTTP 200 OK
```json
{
- "actions": [
- "delete",
- "create",
- "update",
- "read"
- ],
+ "actions": ["delete", "create", "update", "read"],
"created_at": 1557764505,
"endpoint": "/consumers",
"negative": false,
@@ -469,15 +479,14 @@ HTTP 200 OK
---
-
-
## List Role Endpoints Permissions
+
**Endpoint**
/rbac/roles/{role_name_or_id}/endpoints
| Attribute | Description |
-| --------- | ----------- |
+| ----------------- | --------------------------- |
| `role_name_or_id` | The RBAC role name or UUID. |
**Response**
@@ -490,12 +499,7 @@ HTTP 200 OK
{
"data": [
{
- "actions": [
- "delete",
- "create",
- "update",
- "read"
- ],
+ "actions": ["delete", "create", "update", "read"],
"created_at": 1557764505,
"endpoint": "/consumers",
"negative": false,
@@ -505,9 +509,7 @@ HTTP 200 OK
"workspace": "default"
},
{
- "actions": [
- "read"
- ],
+ "actions": ["read"],
"created_at": 1557764438,
"endpoint": "/services",
"negative": false,
@@ -523,22 +525,23 @@ HTTP 200 OK
---
## Update a Role Endpoint Permission
+
**Endpoint**
/rbac/roles/{name_or_id}/endpoints/{worspace_name_or_id}/{endpoint}
| Attribute | Description |
-| --------- | ----------- |
+| --------------------- | -------------------------------------------- |
| `name_or_id` | The RBAC role name or UUID. |
| `worspace_name_or_id` | The worspace name or UUID. |
| `endpoint` | The endpoint associated with this permisson. |
**Request Body**
-| Attribute | Description |
-| --------- | ----------- |
-| `negative` | If true, explicitly disallow the actions associated with the permissions tied to this resource. By default this value is false. |
-| `actions` | One or more actions associated with this permission. |
+| Attribute | Description |
+| ---------- | ------------------------------------------------------------------------------------------------------------------------------- |
+| `negative` | If true, explicitly disallow the actions associated with the permissions tied to this resource. By default this value is false. |
+| `actions` | One or more actions associated with this permission. |
**Response**
@@ -548,12 +551,7 @@ HTTP 200 OK
```json
{
- "actions": [
- "delete",
- "create",
- "update",
- "read"
- ],
+ "actions": ["delete", "create", "update", "read"],
"created_at": 1557764438,
"endpoint": "/services",
"negative": false,
@@ -566,15 +564,14 @@ HTTP 200 OK
---
-
-
## Delete a Role Endpoint Permission
+
**Endpoint**
/rbac/roles/{name_or_id}/endpoints/{worspace_name_or_id}/{endpoint}
| Attribute | Description |
-| --------- | ----------- |
+| --------------------- | -------------------------------------------- |
| `name_or_id` | The RBAC role name or UUID. |
| `worspace_name_or_id` | The worspace name or UUID. |
| `endpoint` | The endpoint associated with this permisson. |
@@ -587,20 +584,20 @@ HTTP 204 No Content
---
-
-
## Add a Role Entity Permission
+
**Endpoint**
+
/rbac/roles/{name_or_id}/entities
| Attribute | Description |
-| --------- | ----------- |
+| ------------ | --------------------------- |
| `name_or_id` | The RBAC role name or UUID. |
**Request Body**
| Attribute | Description |
-| --------- | ----------- |
+| --------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `negative` | If true, explicitly disallow the actions associated with the permissions tied to this resource. By default this value is false. |
| `entity_id` | id of the entity associated with this permission. |
| `actions` | One or more actions associated with this permission. |
@@ -612,7 +609,6 @@ workspace. Future entities belonging to that workspace will get the
same permissions. A wildcard `*` will be interpreted as **all
entities** in the system.
-
**Response**
```
@@ -621,11 +617,7 @@ HTTP 201 Created
```json
{
- "actions": [
- "delete",
- "create",
- "read"
- ],
+ "actions": ["delete", "create", "read"],
"created_at": 1557771505,
"entity_id": "*",
"entity_type": "wildcard",
@@ -639,13 +631,15 @@ HTTP 201 Created
---
## Retrieve a Role Entity Permission
+
**Endpoint**
+
/rbac/roles/{name_or_id}/entities/{entity_id}
-| Attribute | Description |
-| --------- | ----------- |
-| `name_or_id` | The RBAC permission name or UUID. |
-| `entity_id` | id of the entity associated with this permission. |
+| Attribute | Description |
+| ------------ | ------------------------------------------------- |
+| `name_or_id` | The RBAC permission name or UUID. |
+| `entity_id` | id of the entity associated with this permission. |
**Response**
@@ -655,11 +649,7 @@ HTTP 200 Ok
```json
{
- "actions": [
- "delete",
- "create",
- "read"
- ],
+ "actions": ["delete", "create", "read"],
"created_at": 1557771505,
"entity_id": "*",
"entity_type": "wildcard",
@@ -675,11 +665,12 @@ HTTP 200 Ok
## List Entity Permissons
**Endpoint**
+
/rbac/roles/{name_or_id}/entities
-| Attribute | Description |
-| --------- | ----------- |
-| `name_or_id` | The RBAC permisson name or UUID. |
+| Attribute | Description |
+| ------------ | -------------------------------- |
+| `name_or_id` | The RBAC permisson name or UUID. |
**Response**
@@ -691,11 +682,7 @@ HTTP 200 Ok
{
"data": [
{
- "actions": [
- "delete",
- "create",
- "read"
- ],
+ "actions": ["delete", "create", "read"],
"created_at": 1557771505,
"entity_id": "*",
"entity_type": "wildcard",
@@ -709,22 +696,24 @@ HTTP 200 Ok
```
---
+
## Update an Entity Permission
+
**Endpoint**
/rbac/roles/{name_or_id}/entities/{entity_id}
-| Attribute | Description |
-| --------- | ----------- |
-| `name_or_id` | The RBAC role name or UUID. |
-| `entity_id` | The entity name or UUID. |
+| Attribute | Description |
+| ------------ | --------------------------- |
+| `name_or_id` | The RBAC role name or UUID. |
+| `entity_id` | The entity name or UUID. |
**Request Body**
-| Attribute | Description |
-| --------- | ----------- |
+| Attribute | Description |
+| ---------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `negative` | If true, explicitly disallow the actions associated with the permissions tied to this resource. By default this value is false. |
-| `actions` | One or more actions associated with this permission. |
+| `actions` | One or more actions associated with this permission. |
**Response**
@@ -734,9 +723,7 @@ HTTP 200 OK
```json
{
- "actions": [
- "update"
- ],
+ "actions": ["update"],
"created_at": 1557771505,
"entity_id": "*",
"entity_type": "wildcard",
@@ -750,12 +737,13 @@ HTTP 200 OK
---
## Delete an Entity Permission
+
**Endpoint**
/rbac/roles/{name_or_id}/entities/{entity_id}
| Attribute | Description |
-| --------- | ----------- |
+| ------------ | --------------------------- |
| `name_or_id` | The RBAC role name or UUID. |
| `entity_id` | The entity name or UUID. |
@@ -768,39 +756,31 @@ HTTP 204 No Content
---
## List Role Permissions
+
**Endpoint**
+
/rbac/roles/{name_or_id}/permissions/
| Attribute | Description |
-| --------- | ----------- |
+| ------------ | --------------------------- |
| `name_or_id` | The RBAC role name or UUID. |
-
**Response**
```
HTTP 200 OK
```
+
```json
{
"endpoints": {
"*": {
"*": {
- "actions": [
- "delete",
- "create",
- "update",
- "read"
- ],
+ "actions": ["delete", "create", "update", "read"],
"negative": false
},
"/*/rbac/*": {
- "actions": [
- "delete",
- "create",
- "update",
- "read"
- ],
+ "actions": ["delete", "create", "update", "read"],
"negative": true
}
}
@@ -810,19 +790,19 @@ HTTP 200 OK
```
## Add a User to a Role
+
**Endpoint**
/rbac/users/{name_or_id}/roles
| Attribute | Description |
-| --------- | ----------- |
+| ------------ | --------------------------- |
| `name_or_id` | The RBAC role name or UUID. |
-
**Request Body**
-| Attribute | Description |
-| --------- | ----------- |
+| Attribute | Description |
+| --------- | --------------------------------------------------------- |
| `roles` | Comma-separated list of role names to assign to the user. |
**Response**
@@ -830,6 +810,7 @@ HTTP 200 OK
```
HTTP 201 Created
```
+
```json
{
"roles": [
@@ -852,23 +833,24 @@ HTTP 201 Created
```
---
+
## List a User's Roles
+
**Endpoint**
/rbac/users/{name_or_id}/roles
| Attribute | Description |
-| --------- | ----------- |
+| ------------ | --------------------------- |
| `name_or_id` | The RBAC role name or UUID. |
-
**Response**
```
HTTP 200 OK
```
-```json
+```json
{
"roles": [
{
@@ -896,20 +878,21 @@ HTTP 200 OK
```
---
+
## Delete a Role from a User
+
**Endpoint**
/rbac/users/{name_or_id}/roles
| Attribute | Description |
-| --------- | ----------- |
+| ------------ | --------------------------- |
| `name_or_id` | The RBAC role name or UUID. |
-
**Request Body**
| Attribute | Description |
-| --------- | ----------- |
+| --------- | --------------------------------------------------------- |
| `roles` | Comma-separated list of role names to assign to the user. |
**Response**
@@ -921,12 +904,13 @@ HTTP 204 No Content
---
## List a User's Permissions
+
**Endpoint**
/rbac/users/{name_or_id}/permissions
| Attribute | Description |
-| --------- | ----------- |
+| ------------ | --------------------------- |
| `name_or_id` | The RBAC role name or UUID. |
**Response**
@@ -934,19 +918,17 @@ HTTP 204 No Content
```
HTTP 200 OK
```
+
```json
{
"endpoints": {
"*": {
"*": {
- "actions": [
- "read"
- ],
+ "actions": ["read"],
"negative": false
}
}
},
"entities": {}
}
-
```
diff --git a/app/enterprise/0.36-x/admin-api/vitals/vitals-prometheus-strategy.md b/app/enterprise/0.36-x/admin-api/vitals/vitals-prometheus-strategy.md
index d490f3a929fb..a075aaedf8ac 100644
--- a/app/enterprise/0.36-x/admin-api/vitals/vitals-prometheus-strategy.md
+++ b/app/enterprise/0.36-x/admin-api/vitals/vitals-prometheus-strategy.md
@@ -22,7 +22,8 @@ using default config that listens on port `9090`.
The latest release of StatsD exporter can be found at the
[Bintray](https://bintray.com/kong/statsd-exporter). The binary is distributed
-with some specific features like min/max gauges and Unix domain socket support.
+with some specific features like min/max gauges. Alternatively, a
+[Docker image](https://bintray.com/kong/statsd-exporter-docker) is also available.
StatsD exporter needed to configured with a set of mapping rules to translate
the StatsD UDP events to Prometheus metrics. A default set of mapping rules can
@@ -37,12 +38,15 @@ $ ./statsd_exporter --statsd.mapping-config=statsd.rules.yaml \
The StatsD mapping rules file must be configured to match the metrics sent from
Kong. To learn how to customize the StatsD events name, please refer to
-[Enable Vitals with Prometheus strategy in Kong](#enable-Vitals-with-prometheus-strategy-in-kong)
+[Enable Vitals with Prometheus strategy in Kong](#enable-vitals-with-prometheus-strategy-in-kong)
section.
StatsD exporter can run either on a separate node from Kong (to avoid resource
competition with Kong), or on the same host with Kong (to reduce unnecessary
-network overhead).
+network overhead). Note that feeding metrics from multiple Kong nodes into a single
+StatsD exporter is currently not supported, as it would result in a metrics conflict.
+It's also recommended to match the number of Kong nodes to StatsD exporters for
+better scalability.
In this guide, we assume StatsD exporter is running on hostname `statsd-node`,
using default config that listens to UDP traffic on port `9125` and the metrics
@@ -129,8 +133,8 @@ $ export KONG_VITALS_STATSD_PREFIX=kong-vitals
```yaml
# in statsd.rules
mappings:
-# by API
-- match: kong-vitals.api.*.request.count
+# by Service
+- match: kong.service.*.request.count
name: "kong_requests_proxy"
labels:
job: "kong_metrics"
diff --git a/app/enterprise/0.36-x/admin-api/workspaces/examples.md b/app/enterprise/0.36-x/admin-api/workspaces/examples.md
index f7714120ebf3..3899c5337f49 100644
--- a/app/enterprise/0.36-x/admin-api/workspaces/examples.md
+++ b/app/enterprise/0.36-x/admin-api/workspaces/examples.md
@@ -488,4 +488,4 @@ Next: [RBAC Overview ›](/enterprise/{{page.kong_version}}/rbac/overview)
---
-[services]: /{{page.kong_version}}/admin-api/#service-object
+[services]: /enterprise/{{page.kong_version}}/admin-api/#service-object
diff --git a/app/enterprise/0.36-x/admin-api/workspaces/reference.md b/app/enterprise/0.36-x/admin-api/workspaces/reference.md
index 46c1ab15e7d7..e11712fdfd4a 100644
--- a/app/enterprise/0.36-x/admin-api/workspaces/reference.md
+++ b/app/enterprise/0.36-x/admin-api/workspaces/reference.md
@@ -1,16 +1,18 @@
---
title: Workspaces Reference
+redirect_from:
+ - /admin-api/workspaces
book: workspaces
workspace_body: |
- Attribute | Description
- ---:| ---
- `name` | The **Workspace** name.
+ Attribute | Description
+ ---:| ---
+ `name` | The **Workspace** name.
workspace_entities_body: |
- Attribute | Description
- ---:| ---
- `entities`| Comma-delimited list of entity identifiers
+ Attribute | Description
+ ---:| ---
+ `entities`| Comma-delimited list of entity identifiers
---
## Introduction
@@ -149,22 +151,21 @@ HTTP 200 OK
/workspaces/{id}
-Attributes | Description
----:| ---
-`id`
**conditional** | The **Workspace's** unique ID, if replacing it.*
+| Attributes | Description |
+| ----------------------: | ------------------------------------------------- |
+| `id`
**conditional** | The **Workspace's** unique ID, if replacing it.\* |
-* The behavior of `PUT` endpoints is the following: if the request payload **does
-not** contain an entity's primary key (`id` for Workspaces), the entity will be
-created with the given payload. If the request payload **does** contain an
-entity's primary key, the payload will "replace" the entity specified by the
-given primary key. If the primary key is **not** that of an existing entity, `404
-NOT FOUND` will be returned.
+- The behavior of `PUT` endpoints is the following: if the request payload **does
+ not** contain an entity's primary key (`id` for Workspaces), the entity will be
+ created with the given payload. If the request payload **does** contain an
+ entity's primary key, the payload will "replace" the entity specified by the
+ given primary key. If the primary key is **not** that of an existing entity, `404 NOT FOUND` will be returned.
#### Request Body
-Attribute | Description
----:| ---
-`name` | The **Workspace** name.
+| Attribute | Description |
+| --------: | ----------------------- |
+| `name` | The **Workspace** name. |
**Response**
@@ -210,15 +211,17 @@ HTTP 200 OK
}
```
+The behavior of `PUT` endpoints prevents the renaming of a **Workspace**.
+
### Retrieve a Workspace
**Endpoint**
/workspaces/{name or id}
-Attributes | Description
----:| ---
-`name or id`
**required** | The unique identifier **or** the name of the **Workspace** to retrieve
+| Attributes | Description |
+| ---------------------------: | ---------------------------------------------------------------------- |
+| `name or id`
**required** | The unique identifier **or** the name of the **Workspace** to retrieve |
**Response**
@@ -233,8 +236,8 @@ HTTP 200 OK
"portal_developer_meta_fields": "[{\"label\":\"Full Name\",\"title\":\"full_name\",\"validator\":{\"required\":true,\"type\":\"string\"}}]"
},
"created_at": 1557504202,
- "id": "c663cca5-c6f6-474a-ae44-01f62aba16a9",
- "meta": { },
+ "id": "c663cca5-c6f6-474a-ae44-01f62aba16a9",
+ "meta": {},
"name": "rocket-team"
}
```
@@ -245,9 +248,9 @@ HTTP 200 OK
/workspaces/{name or id}/meta
-Attributes | Description
----:| ---
-`name or id`
**required** | The unique identifier **or** the name of the **Workspace** to retrieve
+| Attributes | Description |
+| ---------------------------: | ---------------------------------------------------------------------- |
+| `name or id`
**required** | The unique identifier **or** the name of the **Workspace** to retrieve |
#### Response
@@ -288,11 +291,11 @@ HTTP 200 OK
/workspaces/{name or id}
-Attributes | Description
----:| ---
-`name or id`
**required** | The unique identifier **or** the name of the **Workspace** to delete
+| Attributes | Description |
+| ---------------------------: | -------------------------------------------------------------------- |
+| `name or id`
**required** | The unique identifier **or** the name of the **Workspace** to delete |
-**Note:** All entities within a **Workspace** must be deleted before the
+**Note:** All entities within a **Workspace** must be deleted before the
**Workspace** itself can be.
**Response**
@@ -307,15 +310,15 @@ HTTP 204 No Content
/workspaces/{name or id}
-Attributes | Description
----:| ---
-`name or id`
**required** | The unique identifier **or** the name of the **Workspace** to patch
+| Attributes | Description |
+| ---------------------------: | ------------------------------------------------------------------- |
+| `name or id`
**required** | The unique identifier **or** the name of the **Workspace** to patch |
#### Request Body
-Attributes | Description
----:| ---
-`comment` | A string describing the **Workspace**
+| Attributes | Description |
+| ---------: | ------------------------------------- |
+| `comment` | A string describing the **Workspace** |
The behavior of `PATCH` endpoints prevents the renaming of a **Workspace**.
@@ -431,7 +434,7 @@ HTTP 200 OK
}
```
-In this case, the **Workspace** references two Services.
+In this case, the **Workspace** references two Services.
### Delete entities from a Workspace
@@ -487,4 +490,4 @@ HTTP 204 No Content
---
-[Admin API]: /{{page.kong_version}}/admin-api/
+[Admin API]: /enterprise/{{page.kong_version}}/admin-api/
diff --git a/app/enterprise/0.36-x/auth.md b/app/enterprise/0.36-x/auth.md
new file mode 100644
index 000000000000..f190620128e8
--- /dev/null
+++ b/app/enterprise/0.36-x/auth.md
@@ -0,0 +1,215 @@
+---
+title: Authentication Reference
+---
+
+## Introduction
+
+Traffic to your upstream services (APIs or microservices) is typically controlled by the application and
+configuration of various Kong [authentication plugins][plugins]. Since Kong's Service entity represents
+a 1-to-1 mapping of your own upstream services, the simplest scenario is to configure authentication
+plugins on the Services of your choosing.
+
+## Generic authentication
+
+The most common scenario is to require authentication and to not allow access for any unauthenticated request.
+To achieve this any of the authentication plugins can be used. The generic scheme/flow of those plugins
+works as follows:
+
+1. Apply an auth plugin to a Service, or globally (you cannot apply one on consumers)
+2. Create a `consumer` entity
+3. Provide the consumer with authentication credentials for the specific authentication method
+4. Now whenever a request comes in Kong will check the provided credentials (depends on the auth type) and
+it will either block the request if it cannot validate, or add consumer and credential details
+in the headers and forward the request
+
+The generic flow above does not always apply, for example when using external authentication like LDAP,
+then there is no consumer to be identified, and only the credentials will be added in the forwarded headers.
+
+The authentication method specific elements and examples can be found in each [plugin's documentation][plugins].
+
+## Consumers
+
+The easiest way to think about consumers is to map them one-on-one to users. Yet, to Kong this does not matter.
+The core principle for consumers is that you can attach plugins to them, and hence customize request behaviour.
+So you might have mobile apps, and define one consumer for each app, or version of it. Or have a consumer per
+platform, e.g. an android consumer, an iOS consumer, etc.
+
+It is an opaque concept to Kong and hence they are called "consumers" and not "users".
+
+## Anonymous Access
+
+Kong has the ability to configure a given Service to allow **both** authenticated **and** anonymous access.
+You might use this configuration to grant access to anonymous users with a low rate-limit, and grant access
+to authenticated users with a higher rate limit.
+
+To configure a Service like this, you first apply your selected authentication plugin, then create a new
+consumer to represent anonymous users, then configure your authentication plugin to allow anonymous
+access. Here is an example, which assumes you have already configured a Service named `example-service` and
+the corresponding route:
+
+1. ### Create an example Service and a Route
+
+ Issue the following cURL request to create `example-service` pointing to mockbin.org, which will echo
+ the request:
+
+ ```bash
+ $ curl -i -X POST \
+ --url http://localhost:8001/services/ \
+ --data 'name=example-service' \
+ --data 'url=http://mockbin.org/request'
+ ```
+
+ Add a route to the Service:
+
+ ```bash
+ $ curl -i -X POST \
+ --url http://localhost:8001/services/example-service/routes \
+ --data 'paths[]=/auth-sample'
+ ```
+
+ The url `http://localhost:8000/auth-sample` will now echo whatever is being requested.
+
+2. ### Configure the key-auth Plugin for your Service
+
+ Issue the following cURL request to add a plugin to a Service:
+
+ ```bash
+ $ curl -i -X POST \
+ --url http://localhost:8001/services/example-service/plugins/ \
+ --data 'name=key-auth'
+ ```
+
+ Be sure to note the created Plugin `id` - you'll need it in step 5.
+
+3. ### Verify that the key-auth plugin is properly configured
+
+ Issue the following cURL request to verify that the [key-auth][key-auth]
+ plugin was properly configured on the Service:
+
+ ```bash
+ $ curl -i -X GET \
+ --url http://localhost:8000/auth-sample
+ ```
+
+ Since you did not specify the required `apikey` header or parameter, and you have not yet
+ enabled anonymous access, the response should be `403 Forbidden`:
+
+ ```http
+ HTTP/1.1 403 Forbidden
+ ...
+
+ {
+ "message": "No API key found in headers or querystring"
+ }
+ ```
+
+4. ### Create an anonymous Consumer
+
+ Every request proxied by Kong must be associated with a Consumer. You'll now create a Consumer
+ named `anonymous_users` (that Kong will utilize when proxying anonymous access) by issuing the
+ following request:
+
+ ```bash
+ $ curl -i -X POST \
+ --url http://localhost:8001/consumers/ \
+ --data "username=anonymous_users"
+ ```
+
+ You should see a response similar to the one below:
+
+ ```http
+ HTTP/1.1 201 Created
+ Content-Type: application/json
+ Connection: keep-alive
+
+ {
+ "username": "anonymous_users",
+ "created_at": 1428555626000,
+ "id": "bbdf1c48-19dc-4ab7-cae0-ff4f59d87dc9"
+ }
+ ```
+
+ Be sure to note the Consumer `id` - you'll need it in the next step.
+
+5. ### Enable anonymous access
+
+ You'll now re-configure the key-auth plugin to permit anonymous access by issuing the following
+ request (**replace the sample uuids below by the `id` values from step 2 and 4**):
+
+ ```bash
+ $ curl -i -X PATCH \
+ --url http://localhost:8001/plugins/
\
+ --data "config.anonymous="
+ ```
+
+ The `config.anonymous=` parameter instructs the key-auth plugin on this Service to permit
+ anonymous access, and to associate such access with the Consumer `id` we received in the previous step. It is
+ required that you provide a valid and pre-existing Consumer `id` in this step - validity of the Consumer `id`
+ is not currently checked when configuring anonymous access, and provisioning of a Consumer `id` that doesn't already
+ exist will result in an incorrect configuration.
+
+6. ### Check anonymous access
+
+ Confirm that your Service now permits anonymous access by issuing the following request:
+
+ ```bash
+ $ curl -i -X GET \
+ --url http://localhost:8000/auth-sample
+ ```
+
+ This is the same request you made in step #3, however this time the request should succeed, because you
+ enabled anonymous access in step #5.
+
+ The response (which is the request as Mockbin received it) should have these elements:
+
+ ```json
+ {
+ ...
+ "headers": {
+ ...
+ "x-consumer-id": "713c592c-38b8-4f5b-976f-1bd2b8069494",
+ "x-consumer-username": "anonymous_users",
+ "x-anonymous-consumer": "true",
+ ...
+ },
+ ...
+ }
+ ```
+
+ It shows the request was successful, but anonymous.
+
+## Multiple Authentication
+
+Kong supports multiple authentication plugins for a given Service, allowing
+different clients to utilize different authentication methods to access a given Service or Route.
+
+The behaviour of the auth plugins can be set to do either a logical `AND`, or a logical `OR` when evaluating
+multiple authentication credentials. The key to the behaviour is the `config.anonymous` property.
+
+- `config.anonymous` not set
+ If this property is not set (empty) then the auth plugins will always perform authentication and return
+ a `40x` response if not validated. This results in a logical `AND` when multiple auth plugins are being
+ invoked.
+- `config.anonymous` set to a valid consumer id
+ In this case the auth plugin will only perform authentication if it was not already authenticated. When
+ authentication fails, it will not return a `40x` response, but set the anonymous consumer as the consumer. This
+ results in a logical `OR` + 'anonymous access' when multiple auth plugins are being invoked.
+
+**NOTE 1**: Either all or none of the auth plugins must be configured for anonymous access. The behaviour is
+undefined if they are mixed.
+
+**NOTE 2**: When using the `AND` method, the last plugin executed will be the one setting the credentials
+passed to the upstream service. With the `OR` method, it will be the first plugin that successfully authenticates
+the consumer, or the last plugin that will set its configured anonymous consumer.
+
+**NOTE 3**: When using the OAuth2 plugin in an `AND` fashion, then also the OAuth2 endpoints for requesting
+tokens etc. will require authentication by the other configured auth plugins.
+
+
+ When multiple authentication plugins are enabled in an
OR fashion on a given Service, and it is desired that
+ anonymous access be forbidden, then the
request-termination plugin should be
+ configured on the anonymous consumer. Failure to do so will allow unauthorized requests.
+
+
+[plugins]: https://konghq.com/plugins/
+[key-auth]: /plugins/key-authentication
diff --git a/app/enterprise/0.36-x/clustering.md b/app/enterprise/0.36-x/clustering.md
new file mode 100644
index 000000000000..fcf427def903
--- /dev/null
+++ b/app/enterprise/0.36-x/clustering.md
@@ -0,0 +1,297 @@
+---
+title: Clustering Reference
+---
+
+## Introduction
+
+A Kong cluster allows you to scale the system horizontally by adding more
+machines to handle more incoming requests. They will all share the same
+configuration since they point to the same database. Kong nodes pointing to the
+**same datastore** will be part of the same Kong cluster.
+
+You need a load-balancer in front of your Kong cluster to distribute traffic
+across your available nodes.
+
+## What a Kong cluster does and doesn't do
+
+**Having a Kong cluster does not mean that your clients traffic will be
+load-balanced across your Kong nodes out of the box.** You still need a
+load-balancer in front of your Kong nodes to distribute your traffic. Instead,
+a Kong cluster means that those nodes will share the same configuration.
+
+For performance reasons, Kong avoids database connections when proxying
+requests, and caches the contents of your database in memory. The cached
+entities include Services, Routes, Consumers, Plugins, Credentials, etc... Since those
+values are in memory, any change made via the Admin API of one of the nodes
+needs to be propagated to the other nodes.
+
+This document describes how those cached entities are being invalidated and how
+to configure your Kong nodes for your use case, which lies somewhere between
+performance and consistency.
+
+[Back to TOC](#table-of-contents)
+
+## Single node Kong clusters
+
+A single Kong node connected to a database (Cassandra or PostgreSQL) creates a
+Kong cluster of one node. Any changes applied via the Admin API of this node
+will instantly take effect. Example:
+
+Consider a single Kong node `A`. If we delete a previously registered Service:
+
+```bash
+$ curl -X DELETE http://127.0.0.1:8001/services/test-service
+```
+
+Then any subsequent request to `A` would instantly return `404 Not Found`, as
+the node purged it from its local cache:
+
+```bash
+$ curl -i http://127.0.0.1:8000/test-service
+```
+
+[Back to TOC](#table-of-contents)
+
+## Multiple nodes Kong clusters
+
+In a cluster of multiple Kong nodes, other nodes connected to the same database
+would not instantly be notified that the Service was deleted by node `A`. While
+the Service is **not** in the database anymore (it was deleted by node `A`), it is
+**still** in node `B`'s memory.
+
+All nodes perform a periodic background job to synchronize with changes that
+may have been triggered by other nodes. The frequency of this job can be
+configured via:
+
+* [db_update_frequency][db_update_frequency] (default: 5 seconds)
+
+Every `db_update_frequency` seconds, all running Kong nodes will poll the
+database for any update, and will purge the relevant entities from their cache
+if necessary.
+
+If we delete a Service from node `A`, this change will not be effective in node
+`B` until node `B`s next database poll, which will occur up to
+`db_update_frequency` seconds later (though it could happen sooner).
+
+This makes Kong clusters **eventually consistent**.
+
+[Back to TOC](#table-of-contents)
+
+## What is being cached?
+
+All of the core entities such as Services, Routes, Plugins, Consumers, Credentials are
+cached in memory by Kong and depend on their invalidation via the polling
+mechanism to be updated.
+
+Additionally, Kong also caches **database misses**. This means that if you
+configure a Service with no plugin, Kong will cache this information. Example:
+
+On node `A`, we add a Service and a Route:
+
+```bash
+# node A
+$ curl -X POST http://127.0.0.1:8001/services \
+ --data "name=example-service" \
+ --data "url=http://example.com"
+
+$ curl -X POST http://127.0.0.1:8001/services/example-service/routes \
+ --data "paths[]=/example"
+```
+
+(Note that we used `/services/example-service/routes` as a shortcut: we
+could have used the `/routes` endpoint instead, but then we would need to
+pass `service_id` as an argument, with the UUID of the new Service.)
+
+A request to the Proxy port of both node `A` and `B` will cache this Service, and
+the fact that no plugin is configured on it:
+
+```bash
+# node A
+$ curl http://127.0.0.1:8000/example
+HTTP 200 OK
+...
+```
+
+```bash
+# node B
+$ curl http://127.0.0.2:8000/example
+HTTP 200 OK
+...
+```
+
+Now, say we add a plugin to this Service via node `A`'s Admin API:
+
+```bash
+# node A
+$ curl -X POST http://127.0.0.1:8001/services/example-service/plugins \
+ --data "name=example-plugin"
+```
+
+Because this request was issued via node `A`'s Admin API, node `A` will locally
+invalidate its cache and on subsequent requests, it will detect that this API
+has a plugin configured.
+
+However, node `B` hasn't run a database poll yet, and still caches that this
+API has no plugin to run. It will be so until node `B` runs its database
+polling job.
+
+**Conclusion**: all CRUD operations trigger cache invalidations. Creation
+(`POST`, `PUT`) will invalidate cached database misses, and update/deletion
+(`PATCH`, `DELETE`) will invalidate cached database hits.
+
+[Back to TOC](#table-of-contents)
+
+## How to configure database caching?
+
+You can configure 3 properties in the Kong configuration file, the most
+important one being `db_update_frequency`, which determine where your Kong
+nodes stand on the performance vs consistency trade off.
+
+Kong comes with default values tuned for consistency, in order to let you
+experiment with its clustering capabilities while avoiding "surprises". As you
+prepare a production setup, you should consider tuning those values to ensure
+that your performance constraints are respected.
+
+### 1. [db_update_frequency][db_update_frequency] (default: 5s)
+
+This value determines the frequency at which your Kong nodes will be polling
+the database for invalidation events. A lower value will mean that the polling
+job will be executed more frequently, but that your Kong nodes will keep up
+with changes you apply. A higher value will mean that your Kong nodes will
+spend less time running the polling jobs, and will focus on proxying your
+traffic.
+
+**Note**: changes propagate through the cluster in up to `db_update_frequency`
+seconds.
+
+[Back to TOC](#table-of-contents)
+
+### 2. [db_update_propagation][db_update_propagation] (default: 0s)
+
+If your database itself is eventually consistent (ie: Cassandra), you **must**
+configure this value. It is to ensure that the change has time to propagate
+across your database nodes. When set, Kong nodes receiving invalidation events
+from their polling jobs will delay the purging of their cache for
+`db_update_propagation` seconds.
+
+If a Kong node connected to an eventual consistent database was not delaying
+the event handling, it could purge its cache, only to cache the non-updated
+value again (because the change hasn't propagated through the database yet)!
+
+You should set this value to an estimate of the amount of time your database
+cluster takes to propagate changes.
+
+**Note**: when this value is set, changes propagate through the cluster in
+up to `db_update_frequency + db_update_propagation` seconds.
+
+[Back to TOC](#table-of-contents)
+
+### 3. [db_cache_ttl][db_cache_ttl] (default: 0s)
+
+The time (in seconds) for which Kong will cache database entities (both hits
+and misses). This Time-To-Live value acts as a safeguard in case a Kong node
+misses an invalidation event, to avoid it from running on stale data for too
+long. When the TTL is reached, the value will be purged from its cache, and the
+next database result will be cached again.
+
+By default no data is invalidated based on this TTL (the default value is `0`).
+This is usually fine: Kong nodes rely on invalidation events, which are handled
+at the db store level (Cassandra/PosgreSQL). If you are concerned that a Kong
+node might miss invalidation event for any reason, you should set a TTL. Otherwise
+the node might run with a stale value in its cache for an undefined amount of time,
+until the cache is manually purged, or the node is restarted.
+
+[Back to TOC](#table-of-contents)
+
+### 4. When using Cassandra
+
+If you use Cassandra as your Kong database, you **must** set
+[db_update_propagation][db_update_propagation] to a non-zero value. Since
+Cassandra is eventually consistent by nature, this will ensure that Kong nodes
+do not prematurely invalidate their cache, only to fetch and catch a
+not up-to-date entity again. Kong will present you a warning logs if you did
+not configure this value when using Cassandra.
+
+Additionally, you might want to configure `cassandra_consistency` to a value
+like `QUORUM` or `LOCAL_QUORUM`, to ensure that values being cached by your
+Kong nodes are up-to-date values from your database.
+
+[Back to TOC](#table-of-contents)
+
+## Interacting with the cache via the Admin API
+
+If for some reason, you wish to investigate the cached values, or manually
+invalidate a value cached by Kong (a cached hit or miss), you can do so via the
+Admin API `/cache` endpoint.
+
+### Inspect a cached value
+
+**Endpoint**
+
+/cache/{cache_key}
+
+**Response**
+
+If a value with that key is cached:
+
+```
+HTTP 200 OK
+...
+{
+ ...
+}
+```
+
+Else:
+
+```
+HTTP 404 Not Found
+```
+
+**Note**: retrieving the `cache_key` for each entity being cached by Kong is
+currently an undocumented process. Future versions of the Admin API will make
+this process easier.
+
+[Back to TOC](#table-of-contents)
+
+### Purge a cached value
+
+**Endpoint**
+
+/cache/{cache_key}
+
+**Response**
+
+```
+HTTP 204 No Content
+...
+```
+
+**Note**: retrieving the `cache_key` for each entity being cached by Kong is
+currently an undocumented process. Future versions of the Admin API will make
+this process easier.
+
+[Back to TOC](#table-of-contents)
+
+### Purge a node's cache
+
+**Endpoint**
+
+/cache
+
+**Response**
+
+```
+HTTP 204 No Content
+```
+
+**Note**: be wary of using this endpoint on a warm, production running node.
+If the node is receiving a lot of traffic, purging its cache at the same time
+will trigger many requests to your database, and could cause a
+[dog-pile effect](https://en.wikipedia.org/wiki/Cache_stampede).
+
+[Back to TOC](#table-of-contents)
+
+[db_update_frequency]: /enterprise/{{page.kong_version}}/property-reference/#db_update_frequency
+[db_update_propagation]: /enterprise/{{page.kong_version}}/property-reference/#db_update_propagation
+[db_cache_ttl]: /enterprise/{{page.kong_version}}/property-reference/#db_cache_ttl
diff --git a/app/enterprise/0.36-x/deployment/installation/centos.md b/app/enterprise/0.36-x/deployment/installation/centos.md
index 4e02f192eca3..fd35f1006e8b 100644
--- a/app/enterprise/0.36-x/deployment/installation/centos.md
+++ b/app/enterprise/0.36-x/deployment/installation/centos.md
@@ -30,7 +30,7 @@ To complete this guide you will need:
Copy the file to your home directory:
```
- $ scp kong-enterprise-edition-0.35-1.el7.noarch.rpm @@Note: Your version may be different based on when you obtained the rpm
@@ -235,5 +235,5 @@ setup reach out to your **Support contact** or head over to the
## Next Steps
Work through Kong Enterprise's series of
-[Getting Started](/enterprise/latest/getting-started) guides to get the most
+[Getting Started](/enterprise/{{page.kong_version}}/getting-started) guides to get the most
out of Kong Enterprise.
diff --git a/app/enterprise/0.36-x/deployment/installation/ubuntu.md b/app/enterprise/0.36-x/deployment/installation/ubuntu.md
index 8f205f617217..2dbff2aedc66 100644
--- a/app/enterprise/0.36-x/deployment/installation/ubuntu.md
+++ b/app/enterprise/0.36-x/deployment/installation/ubuntu.md
@@ -30,7 +30,7 @@ To complete this guide you will need:
Copy the file to your home directory:
```
- $ scp kong-enterprise-edition-0.35.xxx.xxx.deb @@Note: Your version may be different based on when you obtained the package
@@ -193,5 +193,5 @@ setup reach out to your **Support contact** or head over to the
## Next Steps
Work through Kong Enterprise's series of
-[Getting Started](/enterprise/latest/getting-started) guides to get the most
+[Getting Started](/enterprise/{{page.kong_version}}/getting-started) guides to get the most
out of Kong Enterprise.
diff --git a/app/enterprise/0.36-x/deployment/migrations.md b/app/enterprise/0.36-x/deployment/migrations.md
index a5bb6ee97310..64cfc1a6ac75 100644
--- a/app/enterprise/0.36-x/deployment/migrations.md
+++ b/app/enterprise/0.36-x/deployment/migrations.md
@@ -15,7 +15,6 @@ title: Migrating to 0.36
* Instances where the Portal and Files API are on different hostnames require that they at least share a common root, and that the `cookie_domain` setting of the Portal session configuration be that common root. For example, if the Portal itself is at `portal.kong.example` and the Files API is at `files.kong.example`, `cookie_domain=.kong.example`.
* Portal-related `rbac_role_endpoints` will be updated to adhere to changes in the Dev Portal API. This only applies to Portal-related endpoints that were present in or set by Kong Manager; any user-generated endpoints will need to be updated manually. The endpoints that will be updated automatically are as follows:
-
```
'/portal/*' => '/developers/*', '/files/*'
'/portal/developers' => '/developers/*'
diff --git a/app/enterprise/0.36-x/developer-portal/configuration/authentication/oidc.md b/app/enterprise/0.36-x/developer-portal/configuration/authentication/oidc.md
index 2680d766a2d8..6e8f6effecb0 100644
--- a/app/enterprise/0.36-x/developer-portal/configuration/authentication/oidc.md
+++ b/app/enterprise/0.36-x/developer-portal/configuration/authentication/oidc.md
@@ -21,10 +21,14 @@ OIDC for the Dev Portal can be enabled in three ways:
- via the [the command line](#enable-oidc-via-the-command-line)
- via the [the Kong configuration file](#enable-oidc-via-the-kongconf)
+**Warning:** Configuring OIDC authentication for Dev Portal via Kong Manger or with the Admin API will take precedence over any kong.conf 'portal_auth_conf' configuration. Be sure to use only one of the configuration methods.
+
### Portal Session Plugin Config
-Session Plugin Config does not apply when using OpenID Connect.
+Session Plugin Config does not apply when using OpenID Connect. Any session
+configuration is defined in the configuration object itself and not
+in a separate portal session configuration object as it is with other Dev Portal authentication options.
### Sample Configuration Object
@@ -40,8 +44,8 @@ Provder:
"client_id": [""],
"login_action": "redirect",
"logout_redirect_uri": ["http://localhost:8003 (http://localhost:8003/)"],
- "ssl_verify": false,
"consumer_claim": ["email"],
+ "redirect_uri": ["https://localhost:8004/auth"],
"forbidden_redirect_uri": ["http://localhost:8003/unauthorized"],
"client_secret": [""],
"issuer": "https://accounts.google.com/",
@@ -49,17 +53,8 @@ Provder:
"login_redirect_uri": ["http://localhost:8003 (http://localhost:8003/)"],
"login_redirect_mode": "query"
}
-
```
-The values above can be replaced with their corresponding values for a custom
-OIDC configuration:
-
- - `` - Client ID provided by IdP
- * For Example, Google credentials can be found here:
- https://console.cloud.google.com/projectselector/apis/credentials
- - `` - Client secret provided by IdP
-
If `portal_gui_host` and `portal_api_url` are set to share a domain but differ
in regards to subdomain, `redirect_uri` and `session_cookie_domain` need to be
configured to allow OpenID-Connect to apply the session correctly.
@@ -76,9 +71,8 @@ Example:
"login_redirect_uri": ["https://example.portal.com (https://example.portal.com/)"],
"login_action": "redirect",
"logout_redirect_uri": ["https://example.portal.com (https://example.portal.com/)"],
- "ssl_verify": false,
"consumer_claim": ["email"],
- "redirect_uri": ["https://exampleapi.portal.com/auth"],
+ "redirect_uri": ["https://example.portalapi.com/auth"],
"session_cookie_domain": ".portal.com",
"forbidden_redirect_uri": ["https://example.portal.com/unauthorized"],
"client_secret": ["` - Client ID provided by IdP. For Example, Google credentials can be found here: https://console.cloud.google.com/projectselector/apis/credentials
+* `` - Client secret provided by IdP
+* The `redirect_uri` the Portal API's '/auth' endpoint.
+* The `session_cookie_domain` is the shared domain of the portal GUI `portal_gui_host` and portal API `portal_api_url` if they have different subdomains.
+
### Enable OIDC via Kong Manager
1. Navigate to the Dev Portal's **Settings** page
@@ -112,8 +112,8 @@ curl -X PATCH http://localhost:8001/workspaces/ \
"config.portal_auth_conf=
```
->**Warning** This will automatically authenticate the Dev Portal with Key
->Auth. Anyone currently viewing the Dev Portal will lose access on the
+>**Warning** This will automatically authenticate the Dev Portal with OIDC
+>. Anyone currently viewing the Dev Portal will lose access on the
>next page refresh.
### Enable OIDC via the Kong.conf
@@ -130,5 +130,5 @@ portal_auth="openid-connect"
Then set `portal_auth_conf` property to your
customized [**Configuration JSON Object**](#/sample-configuration-object)
-This will set every Dev Portal to use Key Authentication by default when
+This configuration will set every Dev Portal to use OIDC by default when
initialized, regardless of Workspace.
diff --git a/app/enterprise/0.36-x/developer-portal/configuration/index.md b/app/enterprise/0.36-x/developer-portal/configuration/index.md
index 0b53bb50b892..fdd661eaecde 100644
--- a/app/enterprise/0.36-x/developer-portal/configuration/index.md
+++ b/app/enterprise/0.36-x/developer-portal/configuration/index.md
@@ -1,5 +1,7 @@
---
title: Dev Portal Configuration
+redirect_from:
+ - /developer-portal/configuration/enable-the-dev-portal
---
diff --git a/app/enterprise/0.36-x/getting-started/add-consumer.md b/app/enterprise/0.36-x/getting-started/add-consumer.md
index 78a1e3cf29a3..5dc3769237bb 100644
--- a/app/enterprise/0.36-x/getting-started/add-consumer.md
+++ b/app/enterprise/0.36-x/getting-started/add-consumer.md
@@ -54,8 +54,8 @@ $ curl -i -X POST \
## 3. Verify Validity of Consumer Credentials
The authorization header must be base64 encoded. For example, if the credential
-uses Aladdin as the username and OpenSesame as the password, then the field’s
-value is the base64-encoding of Aladdin:OpenSesame, or QWxhZGRpbjpPcGVuU2VzYW1l.
+uses `Aladdin` as the username and `OpenSesame` as the password, then the field’s
+value is the base64-encoding of `Aladdin:OpenSesame`, or `QWxhZGRpbjpPcGVuU2VzYW1l`.
Then the Authorization (or Proxy-Authorization) header must appear as:
diff --git a/app/enterprise/0.36-x/getting-started/add-service.md b/app/enterprise/0.36-x/getting-started/add-service.md
index f18372ac4a41..27272b312b74 100644
--- a/app/enterprise/0.36-x/getting-started/add-service.md
+++ b/app/enterprise/0.36-x/getting-started/add-service.md
@@ -5,9 +5,7 @@ title: How to Add a Service and Route
### Introduction
This guide walks through the creation and configuration of a
-**Service and Route** via **Kong Manager** in **Kong Enterprise**. To do this with
-via the **command line** read Kong's guide to
-[Configuring a Service](/latest/getting-started/configuring-a-service/).
+**Service and Route** via **Kong Manager** in **Kong Enterprise**.
For the purpose of this guide, we’ll create a **Service** pointing to the Mockbin
API. Mockbin is an “echo” type public website that returns requests back to
@@ -20,10 +18,9 @@ including adding **Services and Routes**, is made via requests on to the
### Prerequisites
-- **Kong Enterprise** is [installed](/enterprise/{{page.kong_version}}/deployment/installation)
-- **Kong Enterprise** is [started](/enterprise/{{page.kong_version}}/getting-started/start-kong)
-- **Super Admin** or [**Admin**](/enterprise/{{page.kong_version}}/getting-started/add-admin)
-access to **Kong Manager**
+* [`enforce_rbac = on`](/enterprise/{{page.kong_version}}/property-reference/#enforce_rbac)
+* Kong Enterprise has [started](/enterprise/{{page.kong_version}}/getting-started/start-kong)
+* Logged in to Kong Manager as a **Super Admin**
### Step 1 - Create a New Service
diff --git a/app/enterprise/0.36-x/getting-started/enable-plugin.md b/app/enterprise/0.36-x/getting-started/enable-plugin.md
index b927c6a426b9..d45e9d926ce8 100644
--- a/app/enterprise/0.36-x/getting-started/enable-plugin.md
+++ b/app/enterprise/0.36-x/getting-started/enable-plugin.md
@@ -15,11 +15,10 @@ Plugin via the command line, checkout the
### Prerequisites
-- **Kong Enterprise** is [installed](/enterprise/{{page.kong_version}}/deployment/installation)
-- **Kong Enterprise** is [started](/enterprise/{{page.kong_version}}/getting-started/start-kong)
-- A [**Service and Route**](/enterprise/{{page.kong_version}}/getting-started/add-service)
-(optional)
-- **admin** or **super-admin** privileges
+* [`enforce_rbac = on`](/enterprise/{{page.kong_version}}/property-reference/#enforce_rbac)
+* Kong Enterprise has [started](/enterprise/{{page.kong_version}}/getting-started/start-kong)
+* Logged in to Kong Manager as a **Super Admin**
+- _Optionally_ created a [**Service and Route**](/enterprise/{{page.kong_version}}/getting-started/add-service)
### How to Enable a Plugin in Kong Manager
diff --git a/app/enterprise/0.36-x/getting-started/index.md b/app/enterprise/0.36-x/getting-started/index.md
index 4e7c76ec73d2..90bb0c9c3363 100644
--- a/app/enterprise/0.36-x/getting-started/index.md
+++ b/app/enterprise/0.36-x/getting-started/index.md
@@ -10,9 +10,7 @@ guides is designed to help you familiarize yourself with Kong Enterprise's featu
and capabilities, with practical steps to start Kong Enterprise securely, access
Kong Manager as a **Super Admin**, and create new entities such as **Services**.
-Each guide also contains links to more in-depth material. Note that Kong
- Enterprise 0.35 includes Kong 1.0 at its core, so CLI commands and most Admin
- API endpoints are documented in standard [Kong documentation](/1.0.x/).
+Each guide also contains links to more in-depth material.
If you have any issues or further questions, please
[contact Support](https://support.konghq.com/support/s/) and they will be happy
diff --git a/app/enterprise/0.36-x/getting-started/start-kong.md b/app/enterprise/0.36-x/getting-started/start-kong.md
index 0fe368704b15..afcc51a015ba 100644
--- a/app/enterprise/0.36-x/getting-started/start-kong.md
+++ b/app/enterprise/0.36-x/getting-started/start-kong.md
@@ -94,7 +94,7 @@ $ kong start [-c /path/to/kong.conf]
```
**Note:** the CLI accepts a configuration option (`-c /path/to/kong.conf`)
-allowing you to point to [your own configuration](/1.0.x/configuration/#configuration-loading).
+allowing you to point to [your own configuration](/enterprise/{{page.kong_version}}/property-reference/#configuration-loading).
## Step 4
diff --git a/app/enterprise/0.36-x/health-checks-circuit-breakers.md b/app/enterprise/0.36-x/health-checks-circuit-breakers.md
new file mode 100644
index 000000000000..42d16e52217b
--- /dev/null
+++ b/app/enterprise/0.36-x/health-checks-circuit-breakers.md
@@ -0,0 +1,321 @@
+---
+title: Health Checks and Circuit Breakers Reference
+---
+
+## Introduction
+
+You can make an API proxied by Kong use a [ring-balancer][ringbalancer], configured
+by adding an [upstream][upstream] entity that contains one or more [target][ringtarget]
+entities, each target pointing to a different IP address (or hostname) and
+port. The ring-balancer will balance load among the various targets, and based
+on the [upstream][upstream] configuration, will perform health checks on the targets,
+making them as healthy or unhealthy whether they are responsive or not. The
+ring-balancer will then only route traffic to healthy targets.
+
+Kong supports two kinds of health checks, which can be used separately or in
+conjunction:
+
+* **active checks**, 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;
+
+* **passive checks** (also known as **circuit breakers**), where Kong analyzes
+the ongoing traffic being proxied and determines the health of targets based
+on their behavior responding requests.
+
+## Healthy and unhealthy targets
+
+The objective of the health checks functionality is to dynamically mark
+targets as healthy or unhealthy, **for a given Kong node**. There is
+no cluster-wide synchronization of health information: each Kong node
+determines the health of its targets separately. This is desirable since at a
+given point one Kong node may be able to connect to a target successfully
+while another node is failing to reach it: the first node will consider
+it healthy, while the second will mark it as unhealthy and start routing
+traffic to other targets of the upstream.
+
+Either an active probe (on active health checks) or a proxied request
+(on passive health checks) produces data which is used to determine
+whether a target is healthy or unhealthy. A request may produce a TCP
+error, timeout, or produce an HTTP status code. Based on this
+information, the health checker updates a series of internal counters:
+
+* If the returned status code is one configured as "healthy", it will
+increment the "Successes" counter for the target and clear all its other
+counters;
+* If it fails to connect, it will increment the "TCP failures" counter
+for the target and clear the "Successes" counter;
+* If it times out, it will increment the "timeouts" counter
+for the target and clear the "Successes" counter;
+* If the returned status code is one configured as "unhealthy", it will
+increment the "HTTP failures" counter for the target and clear the "Successes" counter.
+
+If any of the "TCP failures", "HTTP failures" or "timeouts" counters reaches
+their configured threshold, the target will be marked as unhealthy.
+
+If the "Successes" counter reaches its configured threshold, the target will be
+marked as healthy.
+
+The list of which HTTP status codes are "healthy" or "unhealthy", and the
+individual thresholds for each of these counters are configurable on a
+per-upstream basis. Below, we have an example of a configuration for an
+Upstream entity, showcasing the default values of the various fields
+available for configuring health checks. A description of each
+field is included in the [Admin API][addupstream] reference documentation.
+
+```json
+{
+ "name": "service.v1.xyz",
+ "healthchecks": {
+ "active": {
+ "concurrency": 10,
+ "healthy": {
+ "http_statuses": [ 200, 302 ],
+ "interval": 0,
+ "successes": 0
+ },
+ "http_path": "/",
+ "timeout": 1,
+ "unhealthy": {
+ "http_failures": 0,
+ "http_statuses": [ 429, 404, 500, 501,
+ 502, 503, 504, 505 ],
+ "interval": 0,
+ "tcp_failures": 0,
+ "timeouts": 0
+ }
+ },
+ "passive": {
+ "healthy": {
+ "http_statuses": [ 200, 201, 202, 203,
+ 204, 205, 206, 207,
+ 208, 226, 300, 301,
+ 302, 303, 304, 305,
+ 306, 307, 308 ],
+ "successes": 0
+ },
+ "unhealthy": {
+ "http_failures": 0,
+ "http_statuses": [ 429, 500, 503 ],
+ "tcp_failures": 0,
+ "timeouts": 0
+ }
+ }
+ },
+ "slots": 10
+}
+```
+
+If all targets of an upstream are unhealthy, Kong will respond to requests
+to the upstream with `503 Service Unavailable`.
+
+Note:
+
+1. health checks operate only on [*active* targets][targetobject] and do not
+ modify the *active* status of a target in the Kong database.
+2. unhealthy targets will not be removed from the loadbalancer, and hence will
+ not have any impact on the balancer layout when using the hashing algorithm
+ (they will just be skipped).
+3. The [DNS caveats][dnscaveats] and [balancer caveats][balancercaveats]
+ also apply to health checks. If using hostnames for the targets, then make
+ sure the DNS server always returns the full set of IP addresses for a name,
+ and does not limit the response. *Failing to do so might lead to health
+ checks not being executed.*
+
+## Types of health checks
+
+### Active health checks
+
+Active health checks, as the name implies, actively probe targets for
+their health. When active health checks are enabled in an upstream entity,
+Kong will periodically issue HTTP or HTTPS requests to a configured path at each target
+of the upstream. This allows Kong to automatically enable and disable targets
+in the balancer based on the [probe results](#healthy-and-unhealthy-targets).
+
+The periodicity of active health checks can be configured separately for
+when a target is healthy or unhealthy. If the `interval` value for either
+is set to zero, the checking is disabled at the corresponding scenario.
+When both are zero, active health checks are disabled altogether.
+
+
+Note: Active health checks currently only support HTTP/HTTPS targets. They
+do not apply to Upstreams assigned to Services with the protocol attribute set to "tcp" or "tls".
+
+
+[Back to TOC](#table-of-contents)
+
+### Passive health checks (circuit breakers)
+
+Passive health checks, also known as circuit breakers, are
+checks performed based on the requests being proxied by Kong (HTTP/HTTPS/TCP),
+with no additional traffic being generated. When a target becomes
+unresponsive, the passive health checker will detect that and mark
+the target as unhealthy. The ring-balancer will start skipping this
+target, so no more traffic will be routed to it.
+
+Once the problem with a target is solved and it is ready to receive
+traffic again, the Kong administrator can manually inform the
+health checker that the target should be enabled again, via an
+Admin API endpoint:
+
+```bash
+$ curl -i -X POST http://localhost:8001/upstreams/my_upstream/targets/10.1.2.3:1234/healthy
+HTTP/1.1 204 No Content
+```
+
+This command will broadcast a cluster-wide message so that the "healthy"
+status is propagated to the whole [Kong cluster][clustering]. This will cause Kong nodes to
+reset the health counters of the health checkers running in all workers of the
+Kong node, allowing the ring-balancer to route traffic to the target again.
+
+Passive health checks have the advantage of not producing extra
+traffic, but they are unable to automatically mark a target as
+healthy again: the "circuit is broken", and the target needs to
+be re-enabled again by the system administrator.
+
+
+[Back to TOC](#table-of-contents)
+
+## Summary of pros and cons
+
+* Active health checks can automatically re-enable a target in the
+ring balancer as soon as it is healthy again. Passive health checks cannot.
+* Passive health checks do not produce additional traffic to the
+target. Active health checks do.
+* An active health checker demands a known URL with a reliable status response
+in the target to be configured as a probe endpoint (which may be as
+simple as `"/"`). Passive health checks do not demand such configuration.
+* By providing a custom probe endpoint for an active health checker,
+an application may determine its own health metrics and produce a status
+code to be consumed by Kong. Even though a target continues to serve
+traffic which looks healthy to the passive health checker,
+it would be able to respond to the active probe with a failure
+status, essentially requesting to be relieved from taking new traffic.
+
+It is possible to combine the two modes. For example, one can enable
+passive health checks to monitor the target health based solely on its
+traffic, and only use active health checks while the target is unhealthy,
+in order to re-enable it automatically.
+
+## Enabling and disabling health checks
+
+### Enabling active health checks
+
+To enable active health checks, you need to specify the configuration items
+under `healthchecks.active` in the [Upstream object][upstreamobjects] configuration. You
+need to specify the necessary information so that Kong can perform periodic
+probing on the target, and how to interpret the resulting information.
+
+You can use the `healthchecks.active.type` field to specify whether to perform
+HTTP or HTTPS probes (setting it to `"http"` or `"https"`), or by simply
+testing if the connection to a given host and port is successful
+(setting it to `"tcp"`).
+
+For configuring the probe, you need to specify:
+
+* `healthchecks.active.http_path` - The path that should be used when
+issuing the HTTP GET request to the target. The default value is `"/"`.
+* `healthchecks.active.timeout` - The connection timeout limit for the
+HTTP GET request of the probe. The default value is 1 second.
+* `healthchecks.active.concurrency` - Number of targets to check concurrently
+in active health checks.
+
+You also need to specify positive values for intervals, for running
+probes:
+
+* `healthchecks.active.healthy.interval` - Interval between active health
+checks for healthy targets (in seconds). A value of zero indicates that active
+probes for healthy targets should not be performed.
+* `healthchecks.active.unhealthy.interval` - Interval between active health
+checks for unhealthy targets (in seconds). A value of zero indicates that active
+probes for unhealthy targets should not be performed.
+
+This allows you to tune the behavior of the active health checks, whether you
+want probes for healthy and unhealthy targets to run at the same interval, or
+one to be more frequent than the other.
+
+If you are using HTTPS healthchecks, you can also specify the following
+fields:
+
+* `healthchecks.active.https_verify_certificate` - Whether to check the
+validity of the SSL certificate of the remote host when performing active
+health checks using HTTPS.
+* `healthchecks.active.https_sni` - The hostname to use as an SNI
+(Server Name Identification) when performing active health checks
+using HTTPS. This is particularly useful when Targets are configured
+using IPs, so that the target host's certificate can be verified
+with the proper SNI.
+
+Note that failed TLS verifications will increment the "TCP failures" counter;
+the "HTTP failures" refer only to HTTP status codes, whether probes are done
+through HTTP or HTTPS.
+
+Finally, you need to configure how Kong should interpret the probe, by setting
+the various thresholds on the [health
+counters](#healthy-and-unhealthy-targets), which, once reached will trigger a
+status change. The counter threshold fields are:
+
+* `healthchecks.active.healthy.successes` - Number of successes in active
+probes (as defined by `healthchecks.active.healthy.http_statuses`) to consider
+a target healthy.
+* `healthchecks.active.unhealthy.tcp_failures` - Number of TCP failures
+or TLS verification failures in active probes to consider a target unhealthy.
+* `healthchecks.active.unhealthy.timeouts` - Number of timeouts in active
+probes to consider a target unhealthy.
+* `healthchecks.active.unhealthy.http_failures` - Number of HTTP failures in
+active probes (as defined by `healthchecks.active.unhealthy.http_statuses`) to
+consider a target unhealthy.
+
+### Enabling passive health checks
+
+Passive health checks do not feature a probe, as they work by interpreting
+the ongoing traffic that flows from a target. This means that to enable
+passive checks you only need to configure its counter thresholds:
+
+* `healthchecks.passive.healthy.successes` - Number of successes in proxied
+traffic (as defined by `healthchecks.passive.healthy.http_statuses`) to
+consider a target healthy, as observed by passive health checks. This needs to
+be positive when passive checks are enabled so that healthy traffic resets the
+unhealthy counters.
+* `healthchecks.passive.unhealthy.tcp_failures` - Number of TCP failures in
+proxied traffic to consider a target unhealthy, as observed by passive health
+checks.
+* `healthchecks.passive.unhealthy.timeouts` - Number of timeouts in proxied
+traffic to consider a target unhealthy, as observed by passive health checks.
+* `healthchecks.passive.unhealthy.http_failures` - Number of HTTP failures in
+proxied traffic (as defined by `healthchecks.passive.unhealthy.http_statuses`)
+to consider a target unhealthy, as observed by passive health checks.
+
+### Disabling health checks
+
+In all counter thresholds and intervals specified in the `healthchecks`
+configuration, setting a value to zero means that the functionality the field
+represents is disabled. Setting a probe interval to zero disables a probe.
+Likewise, you can disable certain types of checks by setting their counter
+thresholds to zero. For example, to not consider timeouts when performing
+healthchecks, you can set both `timeouts` fields (for active and passive
+checks) to zero. This gives you a fine-grained control of the behavior of the
+health checker.
+
+In summary, to completely disable active health checks for an upstream, you
+need to set both `healthchecks.active.healthy.interval` and
+`healthchecks.active.unhealthy.interval` to `0`.
+
+To completely disable passive health checks, you need to set all counter
+thresholds under `healthchecks.passive` for its various counters to zero.
+
+All counter thresholds and intervals in `healthchecks` are zero by default,
+meaning that health checks are completely disabled by default in newly created
+upstreams.
+
+[Back to TOC](#table-of-contents)
+
+[ringbalancer]: /enterprise/{{page.kong_version}}/loadbalancing#ring-balancer
+[ringtarget]: /enterprise/{{page.kong_version}}/loadbalancing#target
+[upstream]: /enterprise/{{page.kong_version}}/loadbalancing#upstream
+[targetobject]: /enterprise/{{page.kong_version}}/admin-api#target-object
+[addupstream]: /enterprise/{{page.kong_version}}/admin-api#add-upstream
+[clustering]: /enterprise/{{page.kong_version}}/clustering
+[upstreamobjects]: /enterprise/{{page.kong_version}}/admin-api#upstream-objects
+[balancercaveats]: /enterprise/{{page.kong_version}}/loadbalancing#balancing-caveats
+[dnscaveats]: /enterprise/{{page.kong_version}}/loadbalancing#dns-caveats
diff --git a/app/enterprise/0.36-x/index.md b/app/enterprise/0.36-x/index.md
index 1676db937b91..38fba432894d 100644
--- a/app/enterprise/0.36-x/index.md
+++ b/app/enterprise/0.36-x/index.md
@@ -18,7 +18,7 @@ title: Kong Enterprise Documentation
diff --git a/app/enterprise/0.36-x/kong-manager/reset-password.md b/app/enterprise/0.36-x/kong-manager/reset-password.md
index 48e6435bd099..6042296c723d 100644
--- a/app/enterprise/0.36-x/kong-manager/reset-password.md
+++ b/app/enterprise/0.36-x/kong-manager/reset-password.md
@@ -5,10 +5,10 @@ toc: false
### Table of contents
-* [Passwords and RBAC Tokens](passwords-and-rbac-tokens)
-* [How to Reset a Forgotten Password in Kong Manager](how-to-reset-a-forgotten-password-in-kong-manager)
-* [How to Reset a Password from within Kong Manager](how-to-reset-a-password-from-within-kong-manager)
-* [How to Reset an RBAC Token in Kong Manager](how-to-reset-an-rbac-token-in-kong-manager)
+* [Passwords and RBAC Tokens](#passwords-and-rbac-tokens)
+* [How to Reset a Forgotten Password in Kong Manager](#how-to-reset-a-forgotten-password-in-kong-manager)
+* [How to Reset a Password from within Kong Manager](#how-to-reset-a-password-from-within-kong-manager)
+* [How to Reset an RBAC Token in Kong Manager](#how-to-reset-an-rbac-token-in-kong-manager)
## Passwords and RBAC Tokens
@@ -32,10 +32,24 @@ Prerequisites:
Steps:
1. At the login page, click **Forgot Password** beneath the login field.
+
+
+
2. Enter the email address associated with the account.
+
+
+
3. Click the link from the email.
+
+
+
4. Reset the password. Note that you will need to provide it again immediately after the reset is complete.
-5. Log in with the new password.
+
+
+
+5. Log in with the new password.
+
+
## How to Reset a Password from within Kong Manager
@@ -49,8 +63,13 @@ Prerequisites:
Steps:
1. At the **top right corner**, after hovering over the **account name**, select **Profile**.
+
+
+
2. In the **Reset Password** section, fill in the fields and click the **Reset Password** button.
+
+
## How to Reset an RBAC Token in Kong Manager
Prerequisites:
@@ -63,7 +82,17 @@ Prerequisites:
Steps:
1. At the **top right corner**, after hovering over the **account name**, select **Profile**.
+
+
+
2. In the **Reset RBAC Token** section at the bottom, click **Reset Token**.
+
+
+
3. Type in a new token and click **Reset**.
+
+
+
4. To copy the token, click the **Copy** button at the right.
+
diff --git a/app/enterprise/0.36-x/loadbalancing.md b/app/enterprise/0.36-x/loadbalancing.md
new file mode 100644
index 000000000000..ccb24bd8aa5c
--- /dev/null
+++ b/app/enterprise/0.36-x/loadbalancing.md
@@ -0,0 +1,374 @@
+---
+title: Loadbalancing reference
+---
+
+## Introduction
+
+Kong provides multiple ways of load balancing requests to multiple backend
+services: a straightforward DNS-based method, and a more dynamic ring-balancer
+that also allows for service registry without needing a DNS server.
+
+## DNS-based loadbalancing
+
+When using DNS-based load balancing, the registration of the backend services
+is done outside of Kong, and Kong only receives updates from the DNS server.
+
+Every Service that has been defined with a `host` containing a hostname
+(instead of an IP address) will automatically use DNS-based load balancing
+if the name resolves to multiple IP addresses, provided the hostname does not
+resolve to an `upstream` name or a name in your DNS hostsfile.
+
+The DNS record `ttl` setting (time to live) determines how often the information
+is refreshed. When using a `ttl` of 0, every request will be resolved using its
+own DNS query. Obviously this will have a performance penalty, but the latency of
+updates/changes will be very low.
+
+[Back to TOC](#table-of-contents)
+
+### A records
+
+An A record contains one or more IP addresses. Hence, when a hostname
+resolves to an A record, each backend service must have its own IP address.
+
+Because there is no `weight` information, all entries will be treated as equally
+weighted in the load balancer, and the balancer will do a straight forward
+round-robin.
+
+[Back to TOC](#table-of-contents)
+
+### SRV records
+
+An SRV record contains weight and port information for all of its IP addresses.
+A backend service can be identified by a unique combination of IP address
+and port number. Hence, a single IP address can host multiple instances of the
+same service on different ports.
+
+Because the `weight` information is available, each entry will get its own
+weight in the load balancer and it will perform a weighted round-robin.
+
+Similarly, any given port information will be overridden by the port information from
+the DNS server. If a Service has attributes `host=myhost.com` and `port=123`,
+and `myhost.com` resolves to an SRV record with `127.0.0.1:456`, then the request
+will be proxied to `http://127.0.0.1:456/somepath`, as port `123` will be
+overridden by `456`.
+
+[Back to TOC](#table-of-contents)
+
+### DNS priorities
+
+The DNS resolver will start resolving the following record types in order:
+
+ 1. The last successful type previously resolved
+ 2. SRV record
+ 3. A record
+ 4. CNAME record
+
+This order is configurable through the [`dns_order` configuration property][dns-order-config].
+
+[Back to TOC](#table-of-contents)
+
+### DNS caveats
+
+- Whenever the DNS record is refreshed a list is generated to handle the
+weighting properly. Try to keep the weights as multiples of each other to keep
+the algorithm performant, e.g., 2 weights of 17 and 31 would result in a structure
+with 527 entries, whereas weights 16 and 32 (or their smallest relative
+counterparts 1 and 2) would result in a structure with merely 3 entries,
+especially with a very small (or even 0) `ttl` value.
+
+- Some nameservers do not return all entries (due to UDP packet size) in those
+cases (for example Consul returns a maximum of 3) a given Kong node will only
+use the few upstream service instances provided by the nameserver. In this
+scenario, it is possible that the pool of upstream instances will be loaded
+inconsistently, because the Kong node is effectively unaware of some of the
+instances, due to the limited information provided by the nameserver.
+To mitigate this use a different nameserver, use IP
+addresses instead of names, or make sure you use enough Kong nodes to still
+have all upstream services being used.
+
+- When the nameserver returns a `3 name error`, then that is a valid response
+for Kong. If this is unexpected, first validate the correct name is being
+queried for, and second check your nameserver configuration.
+
+- The initial pick of an IP address from a DNS record (A or SRV) is not
+randomized. So when using records with a `ttl` of 0, the nameserver is
+expected to randomize the record entries.
+
+[Back to TOC](#table-of-contents)
+
+## Ring-balancer
+
+When using the ring-balancer, the adding and removing of backend services will
+be handled by Kong, and no DNS updates will be necessary. Kong will act as the
+service registry. Nodes can be added/deleted with a single HTTP request and
+will instantly start/stop receiving traffic.
+
+Configuring the ring-balancer is done through the `upstream` and `target`
+entities.
+
+ - `target`: an IP address or hostname with a port number where a backend
+ service resides, eg. "192.168.100.12:80". Each target gets an additional
+ `weight` to indicate the relative load it gets. IP addresses can be
+ in both IPv4 and IPv6 format.
+ - `upstream`: a 'virtual hostname' which can be used in a Route `host`
+ field, e.g., an upstream named `weather.v2.service` would get all requests
+ from a Service with `host=weather.v2.service`.
+
+[Back to TOC](#table-of-contents)
+
+### Upstream
+
+Each upstream gets its own ring-balancer. Each `upstream` can have many
+`target` entries attached to it, and requests proxied to the 'virtual hostname'
+will be load balanced over the targets. A ring-balancer has a pre-defined
+number of slots, and based on the target weights the slots get assigned to the
+targets of the upstream.
+
+Adding and removing targets can be done with a simple HTTP request on the
+Admin API. This operation is relatively cheap. Changing the upstream
+itself is more expensive as the balancer will need to be rebuilt when the
+number of slots change for example.
+
+The only occurrence where the balancer will be rebuilt automatically is when
+the target history is cleaned; other than that, it will only rebuild upon changes.
+
+Within the balancer there are the positions (from 1 to `slots`),
+which are __randomly distributed__ on the ring.
+The randomness is required to make invoking the ring-balancer cheap at
+runtime. A simple round-robin over the wheel (the positions) will do to
+provide a well distributed weighted round-robin over the `targets`, whilst
+also having cheap operations when inserting/deleting targets.
+
+The number of slots to use per target should (at least) be around 100 to make
+sure the slots are properly distributed. Eg. for an expected maximum of 8
+targets, the `upstream` should be defined with at least `slots=800`, even if
+the initial setup only features 2 targets.
+
+The tradeoff here is that the higher the number of slots, the better the random
+distribution, but the more expensive the changes are (add/removing targets)
+
+Detailed information on adding and manipulating
+upstreams is available in the `upstream` section of the
+[Admin API reference][upstream-object-reference].
+
+[Back to TOC](#table-of-contents)
+
+### Target
+
+Because the `upstream` maintains a history of changes, targets can only be
+added, not modified nor deleted. To change a target, just add a new entry for
+the target, and change the `weight` value. The last entry is the one that will
+be used. As such setting `weight=0` will disable a target, effectively
+deleting it from the balancer. Detailed information on adding and manipulating
+targets is available in the `target` section of the
+[Admin API reference][target-object-reference].
+
+The targets will be automatically cleaned when there are 10x more inactive
+entries than active ones. Cleaning will involve rebuilding the balancer, and
+hence is more expensive than just adding a target entry.
+
+A `target` can also have a hostname instead of an IP address. In that case
+the name will be resolved and all entries found will individually be added to
+the ring balancer, e.g., adding `api.host.com:123` with `weight=100`. The
+name 'api.host.com' resolves to an A record with 2 IP addresses. Then both
+ip addresses will be added as target, each getting `weight=100` and port 123.
+__NOTE__: the weight is used for the individual entries, not for the whole!
+
+Would it resolve to an SRV record, then also the `port` and `weight` fields
+from the DNS record would be picked up, and would overrule the given port `123`
+and `weight=100`.
+
+The balancer will honor the DNS record's `ttl` setting and requery and update
+the balancer when it expires.
+
+__Exception__: When a DNS record has `ttl=0`, the hostname will be added
+as a single target, with the specified weight. Upon every proxied request
+to this target it will query the nameserver again.
+
+[Back to TOC](#table-of-contents)
+
+### Balancing algorithms
+
+By default a ring-balancer will use a weighted-round-robin scheme. The alternative
+would be to use the hash-based algorithm. The input for the hash can be either
+`none`, `consumer`, `ip`, `header`, or `cookie`. When set to `none` the
+weighted-round-robin scheme will be used, and hashing will be disabled.
+
+There are two options, a primary and a fallback in case the primary fails
+(e.g., if the primary is set to `consumer`, but no consumer is authenticated)
+
+The different hashing options:
+
+- `none`: Do not use hashing, but use weighted-round-robin instead (default).
+
+- `consumer`: Use the consumer id as the hash input. This option will fallback
+ on the credential id if no consumer id is available (in case of external auth
+ like ldap).
+
+- `ip`: The remote (originating) IP address will be used as input. Review the
+ configuration settings for [determining the real IP][real-ip-config] when
+ using this.
+
+- `header`: Use a specified header (in either `hash_on_header` or `hash_fallback_header`
+ field) as input for the hash.
+
+- `cookie`: Use a specified cookie name (in the `hash_on_cookie` field) with a
+ specified path (in the `hash_on_cookie_path` field, default `"/"`) as input for
+ the hash. If the cookie is not present in the request, it will be set by the
+ response. Hence, the `hash_fallback` setting is invalid if `cookie` is the primary
+ hashing mechanism.
+
+The hashing algorithm is based on 'consistent-hashing' (or the 'ketama principle')
+which makes sure that when the balancer gets modified by changing the targets
+(adding, removing, failing, or changing weights) only the minimum number of
+hashing losses occur. This will maximize upstream cache hits.
+
+For more information on the exact settings see the `upstream` section of the
+[Admin API reference][upstream-object-reference].
+
+[Back to TOC](#table-of-contents)
+
+### Balancing caveats
+
+The ring-balancer is designed to work both with a single node as well as in a cluster.
+For the weighted-round-robin algorithm there isn't much difference, but when using
+the hash based algorithm it is important that all nodes build the exact same
+ring-balancer to make sure they all work identical. To do this the balancer
+must be build in a deterministic way.
+
+- Do not use hostnames in the balancer as the
+balancers might/will slowly diverge because the DNS ttl has only second precision
+and renewal is determined by when a name is actually requested. On top of this is
+the issue with some nameservers not returning all entries, which exacerbates
+this problem. So when using the hashing approach in a Kong cluster, add `target`
+entities only by their IP address, and never by name.
+
+- When picking your hash input make sure the input has enough variance to get
+to a well distributed hash. Hashes will be calculated using the CRC-32 digest.
+So for example, if your system has thousands of users, but only a few consumers, defined
+per platform (eg. 3 consumers: Web, iOS and Android) then picking the `consumer`
+hash input will not suffice, using the remote IP address by setting the hash to
+`ip` would provide more variance in the input and hence a better distribution
+in the hash output. However, if many clients will be behind the same NAT gateway (e.g. in
+call center), `cookie` will provide a better distribution than `ip`.
+
+[Back to TOC](#table-of-contents)
+
+# Blue-Green Deployments
+
+Using the ring-balancer a [blue-green deployment][blue-green-canary] can be easily orchestrated for
+a Service. Switching target infrastructure only requires a `PATCH` request on a
+Service, to change its `host` value.
+
+Set up the "Blue" environment, running version 1 of the address service:
+
+```bash
+# create an upstream
+$ curl -X POST http://kong:8001/upstreams \
+ --data "name=address.v1.service"
+
+# add two targets to the upstream
+$ curl -X POST http://kong:8001/upstreams/address.v1.service/targets \
+ --data "target=192.168.34.15:80"
+ --data "weight=100"
+$ curl -X POST http://kong:8001/upstreams/address.v1.service/targets \
+ --data "target=192.168.34.16:80"
+ --data "weight=50"
+
+# create a Service targeting the Blue upstream
+$ curl -X POST http://kong:8001/services/ \
+ --data "name=address-service" \
+ --data "host=address.v1.service" \
+ --data "path=/address"
+
+# finally, add a Route as an entry-point into the Service
+$ curl -X POST http://kong:8001/services/address-service/routes/ \
+ --data "hosts[]=address.mydomain.com"
+```
+
+Requests with host header set to `address.mydomain.com` will now be proxied
+by Kong to the two defined targets; 2/3 of the requests will go to
+`http://192.168.34.15:80/address` (`weight=100`), and 1/3 will go to
+`http://192.168.34.16:80/address` (`weight=50`).
+
+Before deploying version 2 of the address service, set up the "Green"
+environment:
+
+```bash
+# create a new Green upstream for address service v2
+$ curl -X POST http://kong:8001/upstreams \
+ --data "name=address.v2.service"
+
+# add targets to the upstream
+$ curl -X POST http://kong:8001/upstreams/address.v2.service/targets \
+ --data "target=192.168.34.17:80"
+ --data "weight=100"
+$ curl -X POST http://kong:8001/upstreams/address.v2.service/targets \
+ --data "target=192.168.34.18:80"
+ --data "weight=100"
+```
+
+To activate the Blue/Green switch, we now only need to update the Service:
+
+```bash
+# Switch the Service from Blue to Green upstream, v1 -> v2
+$ curl -X PATCH http://kong:8001/services/address-service \
+ --data "host=address.v2.service"
+```
+
+Incoming requests with host header set to `address.mydomain.com` will now be
+proxied by Kong to the new targets; 1/2 of the requests will go to
+`http://192.168.34.17:80/address` (`weight=100`), and the other 1/2 will go to
+`http://192.168.34.18:80/address` (`weight=100`).
+
+As always, the changes through the Kong Admin API are dynamic and will take
+effect immediately. No reload or restart is required, and no in progress
+requests will be dropped.
+
+[Back to TOC](#table-of-contents)
+
+# Canary Releases
+
+Using the ring-balancer, target weights can be adjusted granularly, allowing
+for a smooth, controlled [canary release][blue-green-canary].
+
+Using a very simple 2 target example:
+
+```bash
+# first target at 1000
+$ curl -X POST http://kong:8001/upstreams/address.v2.service/targets \
+ --data "target=192.168.34.17:80"
+ --data "weight=1000"
+
+# second target at 0
+$ curl -X POST http://kong:8001/upstreams/address.v2.service/targets \
+ --data "target=192.168.34.18:80"
+ --data "weight=0"
+```
+
+By repeating the requests, but altering the weights each time, traffic will
+slowly be routed towards the other target. For example, set it at 10%:
+
+```bash
+# first target at 900
+$ curl -X POST http://kong:8001/upstreams/address.v2.service/targets \
+ --data "target=192.168.34.17:80"
+ --data "weight=900"
+
+# second target at 100
+$ curl -X POST http://kong:8001/upstreams/address.v2.service/targets \
+ --data "target=192.168.34.18:80"
+ --data "weight=100"
+```
+
+The changes through the Kong Admin API are dynamic and will take
+effect immediately. No reload or restart is required, and no in progress
+requests will be dropped.
+
+[Back to TOC](#table-of-contents)
+
+[upstream-object-reference]: /enterprise/{{page.kong_version}}/admin-api#upstream-object
+[target-object-reference]: /enterprise/{{page.kong_version}}/admin-api#target-object
+[dns-order-config]: /enterprise/{{page.kong_version}}/property-reference/#dns_order
+[real-ip-config]: /enterprise/{{page.kong_version}}/property-reference/#real_ip_header
+[blue-green-canary]: http://blog.christianposta.com/deploy/blue-green-deployments-a-b-testing-and-canary-releases/
diff --git a/app/enterprise/0.36-x/logging.md b/app/enterprise/0.36-x/logging.md
new file mode 100644
index 000000000000..8b35b3f48477
--- /dev/null
+++ b/app/enterprise/0.36-x/logging.md
@@ -0,0 +1,151 @@
+---
+title: Logging Reference
+toc: false
+---
+
+## Removing Certain Elements From Your Kong Logs
+
+With new regulations surrounding protecting private data like GDPR, there is a chance you may need to change your logging habits. If you use Kong as your API Gateway, this can be done in a single location to take effect on all of your APIs. This guide will walk you through one approach to accomplishing this, but there are always different approaches for different needs. Please note, these changes will effect the output of the NGINX access logs. This will not have any effect on Kong's logging plugins.
+
+For this example, let’s say you want to remove any instances of an email address from your kong logs. The emails addresses may come through in different ways, for example something like `/apiname/v2/verify/alice@example.com` or `/v3/verify?alice@example.com`. In order to keep these from being added to the logs, we will need to use a custom NGINX template.
+
+## Log Levels
+
+Log levels are set in [Kong's configuration](/enterprise/{{page.kong_version}}/property-reference/#log_level). Following are the log levels in increasing order of their severity, `debug`, `info`,
+`notice`, `warn`, `error` and `crit`.
+
+- *`debug`:* It provides debug information about the plugin's runloop and each individual plugin or other components. Only to be used during debugging since it is too chatty.
+- *`info`/`notice`:* Kong does not make a big difference between both these levels. Provides information about normal behavior most of which can be ignored.
+- *`warn`:* To log any abnormal behavior that doesn't result in dropped transactions but requires further investigation, `warn` level should be used.
+- *`error`:* Used for logging errors that result in a request being dropped (for example getting an HTTP 500 error). The rate of such logs need to be monitored.
+- *`crit`:* This level is used when Kong is working under critical conditions and not working properly thereby affecting several clients. Nginx also provides `alert` and `emerg` levels but currently Kong doesn't make use of these levels making `crit` the highest severity log level.
+
+By default `notice` is the log level that used and also recommended. However if the logs turn out to be too chatty they can be bumped up to a higher level like `warn`.
+
+## Removing Certain Elements From Your Kong Logs
+
+With new regulations surrounding protecting private data like GDPR, there is a chance you may need to change your logging habits. If you use Kong as your API Gateway, this can be done in a single location to take effect on all of your Services. This guide will walk you through one approach to accomplishing this, but there are always different approaches for different needs. Please note, these changes will effect the output of the NGINX access logs. This will not have any effect on Kong's logging plugins.
+
+For this example, let’s say you want to remove any instances of an email address from your kong logs. The emails addresses may come through in different ways, for example something like `/servicename/v2/verify/alice@example.com` or `/v3/verify?alice@example.com`. In order to keep these from being added to the logs, we will need to use a custom NGINX template.
+
+To start using a custom NGINX template, first get a copy of our template. This can be found [https://docs.konghq.com/latest/configuration/#custom-nginx-templates-embedding-kong](https://docs.konghq.com/latest/configuration/#custom-nginx-templates-embedding-kong) or copied from below
+
+```
+# ---------------------
+# custom_nginx.template
+# ---------------------
+
+worker_processes ${{NGINX_WORKER_PROCESSES}}; # can be set by kong.conf
+daemon ${{NGINX_DAEMON}}; # can be set by kong.conf
+
+pid pids/nginx.pid; # this setting is mandatory
+error_log logs/error.log ${{LOG_LEVEL}}; # can be set by kong.conf
+
+events {
+ use epoll; # custom setting
+ multi_accept on;
+}
+
+http {
+ # include default Kong Nginx config
+ include 'nginx-kong.conf';
+
+ # custom server
+ server {
+ listen 8888;
+ server_name custom_server;
+
+ location / {
+ ... # etc
+ }
+ }
+}
+```
+
+In order to control what is placed in the logs, we will be using the NGINX map module in our template. For more detailed information abut using the map directive, please see [this guide](http://nginx.org/en/docs/http/ngx_http_map_module.html). This will create a new variable whose value depends on values of one or more of the source variables specified in the first parameter. The format is:
+
+```
+
+map $paramater_to_look_at $variable_name {
+ pattern_to_look_for 0;
+ second_pattern_to_look_for 0;
+
+ default 1;
+}
+```
+
+For this example, we will be mapping a new variable called `keeplog` which is dependent on certain values appearing in the `$request_uri`. We will be placing our map directive right at the start of the http block, this must be before `include 'nginx-kong.conf';`. So, for our example, we will add something along the lines of:
+
+```
+map $request_uri $keeplog {
+ ~.+\@.+\..+ 0;
+ ~/servicename/v2/verify 0;
+ ~/v3/verify 0;
+
+ default 1;
+}
+```
+
+You’ll probably notice that each of those lines start with a tilde. This is what tells NGINX to use RegEx when evaluating the line. We have three things to look for in this example:
+- The first line uses regex to look for any email address in the x@y.z format
+- The second line looks for any part of the URI which is /servicename/v2/verify
+- The third line looks at any part of the URI which contains /v3/verify
+
+Because all of those have a value of something other than 0, if a request has one of those elements, it will not be added to the log.
+
+Now, we need to set the log format for what we will keep in the logs. We will use the `log_format` module and assign our new logs a name of show_everything. The contents of the log can be customized for you needs, but for this example, I will simply change everything back to the Kong standards. To see the full list of options you can use, please refer to [this guide](https://nginx.org/en/docs/http/ngx_http_core_module.html#variables).
+
+```
+log_format show_everything '$remote_addr - $remote_user [$time_local] '
+ '$request_uri $status $body_bytes_sent '
+ '"$http_referer" "$http_user_agent"';
+```
+
+Now, our custom NGINX template is all ready to be used. If you have been following along, your file should now be look like this:
+
+```
+# ---------------------
+# custom_nginx.template
+# ---------------------
+
+worker_processes ${{NGINX_WORKER_PROCESSES}}; # can be set by kong.conf
+daemon ${{NGINX_DAEMON}}; # can be set by kong.conf
+
+pid pids/nginx.pid; # this setting is mandatory
+error_log stderr ${{LOG_LEVEL}}; # can be set by kong.conf
+
+
+
+events {
+ use epoll; # custom setting
+ multi_accept on;
+}
+
+http {
+
+
+ map $request_uri $keeplog {
+ ~.+\@.+\..+ 0;
+ ~/v1/invitation/ 0;
+ ~/reset/v1/customer/password/token 0;
+ ~/v2/verify 0;
+
+ default 1;
+ }
+ log_format show_everything '$remote_addr - $remote_user [$time_local] '
+ '$request_uri $status $body_bytes_sent '
+ '"$http_referer" "$http_user_agent"';
+
+ include 'nginx-kong.conf';
+}
+```
+
+The last thing we need to do is tell Kong to use the newly created log, `show_everything`. To do this, we will be altering the Kong variable `prpxy_access_log`. Either by opening and editing `etc/kong/kong.conf` or by using an environmental variable `KONG_PROXY_ACCESS_LOG=` you will want to mend the default location to show
+
+```
+proxy_access_log=logs/access.log show_everything if=$keeplog
+```
+
+The final step in the process to make all the changes take effect is to restart kong. you can use the `kong restart` command to do so.
+
+Now, any requests made with an email address in it will no longer be logged. Of course, we can use this logic to remove anything we want from the logs on a conditional manner.
diff --git a/app/enterprise/0.36-x/network.md b/app/enterprise/0.36-x/network.md
new file mode 100644
index 000000000000..5266093c8ebb
--- /dev/null
+++ b/app/enterprise/0.36-x/network.md
@@ -0,0 +1,70 @@
+---
+title: Network & Firewall
+---
+
+## Introduction
+
+In this section you will find a summary about the recommended network and firewall settings for Kong.
+
+## Ports
+
+Kong uses multiple connections for different purposes.
+
+* proxy
+* admin api
+
+### Proxy
+
+The proxy ports is where Kong receives its incoming traffic. There are two ports with the following defaults:
+
+* `8000` for proxying HTTP traffic, and
+* `8443` for proxying HTTPS traffic
+
+See [proxy_listen] for more details on HTTP/HTTPS proxy listen options. For production environment it is common
+to change HTTP and HTTPS listen ports to `80` and `443`.
+
+Kong can also proxy TCP/TLS streams. The stream proxying is disabled by default. See [stream_listen] for
+additional details on stream proxy listen options, and how to enable it (if you plan to proxy anything other than
+HTTP/HTTPS traffic).
+
+In general the proxy ports are the **only ports** that should be made available to your clients.
+
+### Admin API
+
+This is the port where Kong exposes its management API. Hence in production this port should be firewalled to protect
+it from unauthorized access.
+
+* `8001` provides Kong's **Admin API** that you can use to operate Kong with HTTP. See [admin_listen].
+* `8444` provides the same Kong **Admin API** but using HTTPS. See [admin_listen] and the `ssl` suffix.
+
+## Firewall
+
+Below are the recommended firewall settings:
+
+* The upstream Services behind Kong will be available via the [proxy_listen] interface/port values.
+ Configure these values according to the access level you wish to grant to the upstream Services.
+* If you are binding the Admin API to a public-facing interface (via [admin_listen]), then **protect** it to only
+ allow trusted clients to access the Admin API. See also [Securing the Admin API][secure_admin_api].
+* Your proxy will need have rules added for any HTTP/HTTPS and TCP/TLS stream listeners that you configure.
+ For example, if you want Kong to manage traffic on port `4242`, your firewall will need to allow traffic
+ on said port.
+
+#### Transparent Proxying
+
+It is worth mentioning that the `transparent` listen option may be applied to [proxy_listen]
+and [stream_listen] configuration. With packet filtering such as `iptables` (Linux) or `pf` (macOS/BSDs)
+or with hardware routers/switches, you can specify pre-routing or redirection rules for TCP packets that
+allow you to mangle the original destination address and port. For example a HTTP request with a destination
+address of `10.0.0.1`, and a destination port of `80` can be redirected to `127.0.0.1` at port `8000`.
+To make this work, you need (with Linux) to add the `transparent` listen option to Kong proxy,
+`proxy_listen=8000 transparent`. This allows Kong to see the original destination for the request
+(`10.0.0.1:80`) even when Kong didn't actually listen to it directly. With this information,
+Kong can route the request correctly. The `transparent` listen option should only be used with Linux.
+macOS/BSDs allow transparent proxying without `transparent` listen option. With Linux you may also need
+to start Kong as a `root` user or set the needed capabilities for the executable.
+
+
+[proxy_listen]: /enterprise/{{page.kong_version}}/property-reference/#proxy_listen
+[stream_listen]: /enterprise/{{page.kong_version}}/property-reference/#stream_listen
+[admin_listen]: /enterprise/{{page.kong_version}}/property-reference/#admin_listen
+[secure_admin_api]: /enterprise/{{page.kong_version}}/secure-admin-api
diff --git a/app/enterprise/0.36-x/oasconfig.md b/app/enterprise/0.36-x/oasconfig.md
new file mode 100644
index 000000000000..3999c89ad0b6
--- /dev/null
+++ b/app/enterprise/0.36-x/oasconfig.md
@@ -0,0 +1,353 @@
+---
+title: OpenAPI Spec to Kong Entities
+---
+
+## Introduction
+
+This Admin API endpoint allows you to read an OpenAPI Spec into Kong to create the appropriate Services and Routes in an automated way. For now, the functionality is in the early stages and is limited to creating Services and Routes in Kong. This endpoint is useful for testing or quick-start scenarios. In future releases, it may be expanded.
+
+### Create Routes & Services using OAS
+**Endpoint**
+
+
/oas-config
+
+| Attribute | Description |
+|-------------|---------------------------|
+| `spec` | JSON Body containing a stringified / escaped OAS Specification to generate Kong Routes & Services.|
+
+
+**Response**
+
+Returns the Routes & Services generated by the given OAS file as JSON.
+```
+HTTP 201 Created
+```
+
+```json
+{
+ "routes": [
+ {
+ "created_at": 1568224673,
+ "https_redirect_status_code": 426,
+ "id": "a33f22b8-e81f-44ec-b8a2-a8b117800115",
+ "methods": [
+ "POST"
+ ],
+ "paths": [
+ "/user"
+ ],
+ "preserve_host": false,
+ "protocols": [
+ "http"
+ ],
+ "regex_priority": 0,
+ "service": {
+ "id": "bc64c34e-5c83-49f5-9a8f-65714ceaea65"
+ },
+ "strip_path": false,
+ "updated_at": 1568224673
+ },
+ {
+ "created_at": 1568224673,
+ "https_redirect_status_code": 426,
+ "id": "554bb6d3-ce80-435f-8ad2-41cd7ebca5b6",
+ "methods": [
+ "GET"
+ ],
+ "paths": [
+ "/store/inventory"
+ ],
+ "preserve_host": false,
+ "protocols": [
+ "http"
+ ],
+ "regex_priority": 0,
+ "service": {
+ "id": "bc64c34e-5c83-49f5-9a8f-65714ceaea65"
+ },
+ "strip_path": false,
+ "updated_at": 1568224673
+ },
+ {
+ "created_at": 1568224673,
+ "https_redirect_status_code": 426,
+ "id": "2dea6287-d856-4369-8e1b-b55cbf09386b",
+ "methods": [
+ "POST",
+ "PUT"
+ ],
+ "paths": [
+ "/pet"
+ ],
+ "preserve_host": false,
+ "protocols": [
+ "http"
+ ],
+ "regex_priority": 0,
+ "service": {
+ "id": "bc64c34e-5c83-49f5-9a8f-65714ceaea65"
+ },
+ "strip_path": false,
+ "updated_at": 1568224673
+ }
+ ],
+ "services": [
+ {
+ "connect_timeout": 60000,
+ "created_at": 1568224673,
+ "host": "petstore.swagger.io",
+ "id": "bc64c34e-5c83-49f5-9a8f-65714ceaea65",
+ "name": "swagger-petstore-1",
+ "path": "/v2",
+ "port": 80,
+ "protocol": "http",
+ "read_timeout": 60000,
+ "retries": 5,
+ "updated_at": 1568224673,
+ "write_timeout": 60000
+ }
+ ]
+}
+```
+### Update Routes & Services using OAS
+**Endpoint**
+
+
/oas-config
+
+| Attribute | Description |
+|-------------|---------------------------|
+| `spec` | JSON Body containing a stringified / escaped OAS Specification to generate Kong Routes & Services |
+| `recreate_routes` | `true` to update Service routes|
+
+
+**Response**
+
+Return Updated Routes & Services
+```
+HTTP 201 Created
+```
+```json
+}
+ "services": [
+ {
+ "connect_timeout": 60000,
+ "created_at": 1568224673,
+ "host": "petstore.swagger.io",
+ "id": "bc64c34e-5c83-49f5-9a8f-65714ceaea65",
+ "name": "swagger-petstore-1",
+ "path": "/v1",
+ "port": 80,
+ "protocol": "http",
+ "read_timeout": 60000,
+ "retries": 5,
+ "updated_at": 1568227806,
+ "write_timeout": 60000
+ }
+ ]
+}
+```
+
+## Example of how to use the OAS Config Endpoint
+
+1. Define your OAS File for the services and routes you wish to create. Please validate your OAS file prior to submitting. The below is an abbreviated version of the sample Petstore specification (https://petstore.swagger.io)[https://petstore.swagger.io].
+```json
+{
+ "swagger": "2.0",
+ "info": {
+ "description": "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.",
+ "version": "1.0.0",
+ "title": "Swagger Petstore",
+ "termsOfService": "http://swagger.io/terms/",
+ "contact": {
+ "email": "apiteam@swagger.io"
+ },
+ "license": {
+ "name": "Apache 2.0",
+ "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
+ }
+ },
+ "host": "petstore.swagger.io",
+ "basePath": "/v2",
+ "tags": [
+ {
+ "name": "pet",
+ "description": "Everything about your Pets",
+ "externalDocs": {
+ "description": "Find out more",
+ "url": "http://swagger.io"
+ }
+ },
+ {
+ "name": "store",
+ "description": "Access to Petstore orders"
+ },
+ {
+ "name": "user",
+ "description": "Operations about user",
+ "externalDocs": {
+ "description": "Find out more about our store",
+ "url": "http://swagger.io"
+ }
+ }
+ ],
+ "schemes": [
+ "http"
+ ],
+ "paths": {
+ "/pet": {
+ "post": {
+ "tags": [
+ "pet"
+ ],
+ "summary": "Add a new pet to the store",
+ "description": "",
+ "operationId": "addPet",
+ "consumes": [
+ "application/json",
+ "application/xml"
+ ],
+ "produces": [
+ "application/xml",
+ "application/json"
+ ],
+ "parameters": [
+ {
+ "in": "body",
+ "name": "body",
+ "description": "Pet object that needs to be added to the store",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/Pet"
+ }
+ }
+ ],
+ "responses": {
+ "405": {
+ "description": "Invalid input"
+ }
+ },
+ "security": [
+ {
+ "petstore_auth": [
+ "write:pets",
+ "read:pets"
+ ]
+ }
+ ]
+ },
+ "put": {
+ "tags": [
+ "pet"
+ ],
+ "summary": "Update an existing pet",
+ "description": "",
+ "operationId": "updatePet",
+ "consumes": [
+ "application/json",
+ "application/xml"
+ ],
+ "produces": [
+ "application/xml",
+ "application/json"
+ ],
+ "parameters": [
+ {
+ "in": "body",
+ "name": "body",
+ "description": "Pet object that needs to be added to the store",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/Pet"
+ }
+ }
+ ],
+ "responses": {
+ "400": {
+ "description": "Invalid ID supplied"
+ },
+ "404": {
+ "description": "Pet not found"
+ },
+ "405": {
+ "description": "Validation exception"
+ }
+ },
+ "security": [
+ {
+ "petstore_auth": [
+ "write:pets",
+ "read:pets"
+ ]
+ }
+ ]
+ }
+ },
+ "/store/inventory": {
+ "get": {
+ "tags": [
+ "store"
+ ],
+ "summary": "Returns pet inventories by status",
+ "description": "Returns a map of status codes to quantities",
+ "operationId": "getInventory",
+ "produces": [
+ "application/json"
+ ],
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "successful operation",
+ "schema": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "integer",
+ "format": "int32"
+ }
+ }
+ }
+ },
+ "security": [
+ {
+ "api_key": []
+ }
+ ]
+ }
+ },
+ "/user": {
+ "post": {
+ "tags": [
+ "user"
+ ],
+ "summary": "Create user",
+ "description": "This can only be done by the logged in user.",
+ "operationId": "createUser",
+ "produces": [
+ "application/xml",
+ "application/json"
+ ],
+ "parameters": [
+ {
+ "in": "body",
+ "name": "body",
+ "description": "Created user object",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/User"
+ }
+ }
+ ],
+ "responses": {
+ "default": {
+ "description": "successful operation"
+ }
+ }
+ }
+ }
+ }
+ }
+```
+
+2. Use the OAS config endpoint to create the Kong Routes and Services based on the above file.
+```
+http POST http://kong:8001/oas-config spec=@petstore.json
+```
diff --git a/app/enterprise/0.36-x/pdk/index.md b/app/enterprise/0.36-x/pdk/index.md
new file mode 100644
index 000000000000..2f951970b6c4
--- /dev/null
+++ b/app/enterprise/0.36-x/pdk/index.md
@@ -0,0 +1,176 @@
+---
+title: PDK
+pdk: true
+toc: true
+---
+
+## Plugin Development Kit
+
+The Plugin Development Kit (or "PDK") is set of Lua functions and variables
+ that can be used by plugins to implement their own logic. The PDK is a
+ [Semantically Versioned](https://semver.org/) component, originally
+ released in Kong 0.14.0. The PDK will be guaranteed to be forward-compatible
+ from its 1.0.0 release and on.
+
+ As of this release, the PDK has not yet reached 1.0.0, but plugin authors
+ can already depend on it for a safe and reliable way of interacting with the
+ request, response, or the core components.
+
+ The Plugin Development Kit is accessible from the `kong` global variable,
+ and various functionalities are namespaced under this table, such as
+ `kong.request`, `kong.log`, etc...
+
+
+
+
+### kong.version
+
+A human-readable string containing the version number of the currently
+ running node.
+
+**Usage**
+
+``` lua
+print(kong.version) -- "0.14.0"
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.version_num
+
+An integral number representing the version number of the currently running
+ node, useful for comparison and feature-existence checks.
+
+**Usage**
+
+``` lua
+if kong.version_num < 13000 then -- 000.130.00 -> 0.13.0
+ -- no support for Routes & Services
+end
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.pdk_major_version
+
+A number representing the major version of the current PDK (e.g.
+ `1`). Useful for feature-existence checks or backwards-compatible behavior
+ as users of the PDK.
+
+
+**Usage**
+
+``` lua
+if kong.pdk_version_num < 2 then
+ -- PDK is below version 2
+end
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.pdk_version
+
+A human-readable string containing the version number of the current PDK.
+
+**Usage**
+
+``` lua
+print(kong.pdk_version) -- "1.0.0"
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.configuration
+
+A read-only table containing the configuration of the current Kong node,
+ based on the configuration file and environment variables.
+
+ See [kong.conf.default](https://github.com/Kong/kong/blob/master/kong.conf.default)
+ for details.
+
+ Comma-separated lists in that file get promoted to arrays of strings in this
+ table.
+
+
+**Usage**
+
+``` lua
+print(kong.configuration.prefix) -- "/usr/local/kong"
+-- this table is read-only; the following throws an error:
+kong.configuration.prefix = "foo"
+```
+
+[Back to TOC](#table-of-contents)
+
+
+
+
+### kong.db
+
+Instance of Kong's DAO (the `kong.db` module). Contains accessor objects
+ to various entities.
+
+ A more thorough documentation of this DAO and new schema definitions is to
+ be made available in the future.
+
+
+**Usage**
+
+``` lua
+kong.db.services:insert()
+kong.db.routes:select()
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.dns
+
+Instance of Kong's DNS resolver, a client object from the
+ [lua-resty-dns-client](https://github.com/kong/lua-resty-dns-client) module.
+
+ **Note:** usage of this module is currently reserved to the core or to
+ advanced users.
+
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.worker_events
+
+Instance of Kong's IPC module for inter-workers communication from the
+ [lua-resty-worker-events](https://github.com/Kong/lua-resty-worker-events)
+ module.
+
+ **Note:** usage of this module is currently reserved to the core or to
+ advanced users.
+
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.cluster_events
+
+Instance of Kong's cluster events module for inter-nodes communication.
+
+ **Note:** usage of this module is currently reserved to the core or to
+ advanced users.
+
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.cache
+
+Instance of Kong's database caching object, from the `kong.cache` module.
+
+ **Note:** usage of this module is currently reserved to the core or to
+ advanced users.
+
+
+[Back to TOC](#table-of-contents)
+
diff --git a/app/enterprise/0.36-x/pdk/kong.client.md b/app/enterprise/0.36-x/pdk/kong.client.md
new file mode 100644
index 000000000000..947beb0aedbd
--- /dev/null
+++ b/app/enterprise/0.36-x/pdk/kong.client.md
@@ -0,0 +1,286 @@
+---
+title: kong.client
+pdk: true
+toc: true
+---
+
+## kong.client
+
+Client information module
+ A set of functions to retrieve information about the client connecting to
+ Kong in the context of a given request.
+
+ See also:
+ [nginx.org/en/docs/http/ngx_http_realip_module.html](http://nginx.org/en/docs/http/ngx_http_realip_module.html)
+
+
+
+### kong.client.get_ip()
+
+Returns the remote address of the client making the request. This will
+ **always** return the address of the client directly connecting to Kong.
+ That is, in cases when a load balancer is in front of Kong, this function
+ will return the load balancer's address, and **not** that of the
+ downstream client.
+
+
+**Phases**
+
+* certificate, rewrite, access, header_filter, body_filter, log
+
+**Returns**
+
+* `string` ip The remote address of the client making the request
+
+
+**Usage**
+
+``` lua
+-- Given a client with IP 127.0.0.1 making connection through
+-- a load balancer with IP 10.0.0.1 to Kong answering the request for
+-- https://example.com:1234/v1/movies
+kong.client.get_ip() -- "10.0.0.1"
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.client.get_forwarded_ip()
+
+Returns the remote address of the client making the request. Unlike
+ `kong.client.get_ip`, this function will consider forwarded addresses in
+ cases when a load balancer is in front of Kong. Whether this function
+ returns a forwarded address or not depends on several Kong configuration
+ parameters:
+
+ * [trusted\_ips](/enterprise/{{page.kong_version}}/property-reference/#trusted_ips)
+ * [real\_ip\_header](/enterprise/{{page.kong_version}}/property-reference/#real_ip_header)
+ * [real\_ip\_recursive](/enterprise/{{page.kong_version}}/property-reference/#real_ip_recursive)
+
+
+**Phases**
+
+* certificate, rewrite, access, header_filter, body_filter, log
+
+**Returns**
+
+* `string` ip The remote address of the client making the request,
+ considering forwarded addresses
+
+
+
+**Usage**
+
+``` lua
+-- Given a client with IP 127.0.0.1 making connection through
+-- a load balancer with IP 10.0.0.1 to Kong answering the request for
+-- https://username:password@example.com:1234/v1/movies
+
+kong.request.get_forwarded_ip() -- "127.0.0.1"
+
+-- Note: assuming that 10.0.0.1 is one of the trusted IPs, and that
+-- the load balancer adds the right headers matching with the configuration
+-- of `real_ip_header`, e.g. `proxy_protocol`.
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.client.get_port()
+
+Returns the remote port of the client making the request. This will
+ **always** return the port of the client directly connecting to Kong. That
+ is, in cases when a load balancer is in front of Kong, this function will
+ return load balancer's port, and **not** that of the downstream client.
+
+**Phases**
+
+* certificate, rewrite, access, header_filter, body_filter, log
+
+**Returns**
+
+* `number` The remote client port
+
+
+**Usage**
+
+``` lua
+-- [client]:40000 <-> 80:[balancer]:30000 <-> 80:[kong]:20000 <-> 80:[service]
+kong.client.get_port() -- 30000
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.client.get_forwarded_port()
+
+Returns the remote port of the client making the request. Unlike
+ `kong.client.get_port`, this function will consider forwarded ports in cases
+ when a load balancer is in front of Kong. Whether this function returns a
+ forwarded port or not depends on several Kong configuration parameters:
+
+ * [trusted\_ips](/enterprise/{{page.kong_version}}/property-reference/#trusted_ips)
+ * [real\_ip\_header](/enterprise/{{page.kong_version}}/property-reference/#real_ip_header)
+ * [real\_ip\_recursive](/enterprise/{{page.kong_version}}/property-reference/#real_ip_recursive)
+
+**Phases**
+
+* certificate, rewrite, access, header_filter, body_filter, log
+
+**Returns**
+
+* `number` The remote client port, considering forwarded ports
+
+
+**Usage**
+
+``` lua
+-- [client]:40000 <-> 80:[balancer]:30000 <-> 80:[kong]:20000 <-> 80:[service]
+kong.client.get_forwarded_port() -- 40000
+
+-- Note: assuming that [balancer] is one of the trusted IPs, and that
+-- the load balancer adds the right headers matching with the configuration
+-- of `real_ip_header`, e.g. `proxy_protocol`.
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.client.get_credential()
+
+Returns the credentials of the currently authenticated consumer.
+ If not set yet, it returns `nil`.
+
+**Phases**
+
+* access, header_filter, body_filter, log
+
+**Returns**
+
+* the authenticated credential
+
+
+**Usage**
+
+``` lua
+local credential = kong.client.get_credential()
+if credential then
+ consumer_id = credential.consumer_id
+else
+ -- request not authenticated yet
+end
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.client.get_consumer()
+
+Returns the `consumer` entity of the currently authenticated consumer.
+ If not set yet, it returns `nil`.
+
+**Phases**
+
+* access, header_filter, body_filter, log
+
+**Returns**
+
+* `table` the authenticated consumer entity
+
+
+**Usage**
+
+``` lua
+local consumer = kong.client.get_consumer()
+if consumer then
+ consumer_id = consumer.id
+else
+ -- request not authenticated yet, or a credential
+ -- without a consumer (external auth)
+end
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.client.authenticate(consumer, credential)
+
+Sets the authenticated consumer and/or credential for the current request.
+ While both `consumer` and `credential` can be `nil`, it is required
+ that at least one of them exists. Otherwise this function will throw an
+ error.
+
+**Phases**
+
+* access
+
+**Parameters**
+
+* **consumer** (table|nil): The consumer to set. Note: if no
+ value is provided, then any existing value will be cleared!
+* **credential** (table|nil): The credential to set. Note: if
+ no value is provided, then any existing value will be cleared!
+
+**Usage**
+
+``` lua
+-- assuming `credential` and `consumer` have been set by some authentication code
+kong.client.authenticate(consumer, credentials)
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.client.get_subsystem()
+
+Returns the Nginx subsystem used by the client. It can be
+ "http" or "stream"
+
+
+**Phases**
+
+* access, header_filter, body_filter, log
+
+**Returns**
+
+* `string` a string with either `"http"` or `"stream"`
+
+
+**Usage**
+
+``` lua
+kong.client.get_subsystem() -- "http"
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### _CLIENT.get_protocol(allow_terminated)
+
+Returns the protocol matched by the current route (`"http"`, `"https"`, `"tcp"` or
+ `"tls"`), or `nil`, if no route has been matched, which can happen when dealing with
+ erroneous requests.
+
+**Phases**
+
+* access, header_filter, body_filter, log
+
+**Parameters**
+
+* **allow_terminated** ([opt]): boolean. If set, the `X-Forwarded-Proto` header will be checked when checking for https
+
+**Returns**
+
+1. `string|nil` `"http"`, `"https"`, `"tcp"`, `"tls"` or `nil` in case of failure
+
+1. `nil|err` an error message when a failure happens. `nil` otherwise
+
+
+**Usage**
+
+``` lua
+kong.client.get_protocol() -- "http"
+```
+
+[Back to TOC](#table-of-contents)
+
diff --git a/app/enterprise/0.36-x/pdk/kong.ctx.md b/app/enterprise/0.36-x/pdk/kong.ctx.md
new file mode 100644
index 000000000000..c44dc7e8a776
--- /dev/null
+++ b/app/enterprise/0.36-x/pdk/kong.ctx.md
@@ -0,0 +1,106 @@
+---
+title: kong.ctx
+pdk: true
+toc: true
+---
+
+## kong.ctx
+
+Current request context data
+
+
+
+### kong.ctx.shared
+
+A table that has the lifetime of the current request and is shared between
+ all plugins. It can be used to share data between several plugins in a given
+ request.
+
+ Since only relevant in the context of a request, this table cannot be
+ accessed from the top-level chunk of Lua modules. Instead, it can only be
+ accessed in request phases, which are represented by the `rewrite`,
+ `access`, `header_filter`, `body_filter`, and `log` phases of the plugin
+ interfaces. Accessing this table in those functions (and their callees) is
+ fine.
+
+ Values inserted in this table by a plugin will be visible by all other
+ plugins. One must use caution when interacting with its values, as a naming
+ conflict could result in the overwrite of data.
+
+
+**Phases**
+
+* rewrite, access, header_filter, body_filter, log
+
+**Usage**
+
+``` lua
+-- Two plugins A and B, and if plugin A has a higher priority than B's
+-- (it executes before B):
+
+-- plugin A handler.lua
+function plugin_a_handler:access(conf)
+ kong.ctx.shared.foo = "hello world"
+
+ kong.ctx.shared.tab = {
+ bar = "baz"
+ }
+end
+
+-- plugin B handler.lua
+function plugin_b_handler:access(conf)
+ kong.log(kong.ctx.shared.foo) -- "hello world"
+ kong.log(kong.ctx.shared.tab.bar) -- "baz"
+end
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.ctx.plugin
+
+A table that has the lifetime of the current request - Unlike
+ `kong.ctx.shared`, this table is **not** shared between plugins. Instead,
+ it is only visible for the current plugin _instance_. That is, if several
+ instances of the rate-limiting plugin are configured (e.g. on different
+ Services), each instance has its own table, for every request.
+
+ Because of its namespaced nature, this table is safer for a plugin to use
+ than `kong.ctx.shared` since it avoids potential naming conflicts, which
+ could lead to several plugins unknowingly overwrite each other's data.
+
+ Since only relevant in the context of a request, this table cannot be
+ accessed from the top-level chunk of Lua modules. Instead, it can only be
+ accessed in request phases, which are represented by the `rewrite`,
+ `access`, `header_filter`, `body_filter`, and `log` phases of the plugin
+ interfaces. Accessing this table in those functions (and their callees) is
+ fine.
+
+ Values inserted in this table by a plugin will be visible in successful
+ phases of this plugin's instance only. For example, if a plugin wants to
+ save some value for post-processing during the `log` phase:
+
+
+**Phases**
+
+* rewrite, access, header_filter, body_filter, log
+
+**Usage**
+
+``` lua
+-- plugin handler.lua
+
+function plugin_handler:access(conf)
+ kong.ctx.plugin.val_1 = "hello"
+ kong.ctx.plugin.val_2 = "world"
+end
+
+function plugin_handler:log(conf)
+ local value = kong.ctx.plugin.val_1 .. " " .. kong.ctx.plugin.val_2
+
+ kong.log(value) -- "hello world"
+end
+```
+
+[Back to TOC](#table-of-contents)
+
diff --git a/app/enterprise/0.36-x/pdk/kong.ip.md b/app/enterprise/0.36-x/pdk/kong.ip.md
new file mode 100644
index 000000000000..86c74d21942e
--- /dev/null
+++ b/app/enterprise/0.36-x/pdk/kong.ip.md
@@ -0,0 +1,51 @@
+---
+title: kong.ip
+pdk: true
+toc: true
+---
+
+## kong.ip
+
+Trusted IPs module
+
+ This module can be used to determine whether or not a given IP address is
+ in the range of trusted IP addresses defined by the `trusted_ips` configuration
+ property.
+
+ Trusted IP addresses are those that are known to send correct replacement
+ addresses for clients (as per the chosen header field, e.g. X-Forwarded-*).
+
+ See [docs.konghq.com/latest/configuration/#trusted_ips](https://docs.konghq.com/latest/configuration/#trusted_ips)
+
+
+
+
+### kong.ip.is_trusted(address)
+
+Depending on the `trusted_ips` configuration property,
+ this function will return whether a given ip is trusted or not Both ipv4 and ipv6 are supported.
+
+
+**Phases**
+
+* init_worker, certificate, rewrite, access, header_filter, body_filter, log
+
+**Parameters**
+
+* **address** (string): A string representing an IP address
+
+**Returns**
+
+* `boolean` `true` if the IP is trusted, `false` otherwise
+
+
+**Usage**
+
+``` lua
+if kong.ip.is_trusted("1.1.1.1") then
+ kong.log("The IP is trusted")
+end
+```
+
+[Back to TOC](#table-of-contents)
+
diff --git a/app/enterprise/0.36-x/pdk/kong.log.md b/app/enterprise/0.36-x/pdk/kong.log.md
new file mode 100644
index 000000000000..1914b5d02f3c
--- /dev/null
+++ b/app/enterprise/0.36-x/pdk/kong.log.md
@@ -0,0 +1,261 @@
+---
+title: kong.log
+pdk: true
+toc: true
+---
+
+## kong.log
+
+This namespace contains an instance of a "logging facility", which is a
+ table containing all of the methods described below.
+
+ This instance is namespaced per plugin, and Kong will make sure that before
+ executing a plugin, it will swap this instance with a logging facility
+ dedicated to the plugin. This allows the logs to be prefixed with the
+ plugin's name for debugging purposes.
+
+
+
+
+### kong.log(...)
+
+Write a log line to the location specified by the current Nginx
+ configuration block's `error_log` directive, with the `notice` level (similar
+ to `print()`).
+
+ The Nginx `error_log` directive is set via the `log_level`, `proxy_error_log`
+ and `admin_error_log` Kong configuration properties.
+
+ Arguments given to this function will be concatenated similarly to
+ `ngx.log()`, and the log line will report the Lua file and line number from
+ which it was invoked. Unlike `ngx.log()`, this function will prefix error
+ messages with `[kong]` instead of `[lua]`.
+
+ Arguments given to this function can be of any type, but table arguments
+ will be converted to strings via `tostring` (thus potentially calling a
+ table's `__tostring` metamethod if set). This behavior differs from
+ `ngx.log()` (which only accepts table arguments if they define the
+ `__tostring` metamethod) with the intent to simplify its usage and be more
+ forgiving and intuitive.
+
+ Produced log lines have the following format when logging is invoked from
+ within the core:
+
+ ``` plain
+ [kong] %file_src:%line_src %message
+ ```
+
+ In comparison, log lines produced by plugins have the following format:
+
+ ``` plain
+ [kong] %file_src:%line_src [%namespace] %message
+ ```
+
+ Where:
+
+ * `%namespace`: is the configured namespace (the plugin name in this case).
+ * `%file_src`: is the file name from where the log was called from.
+ * `%line_src`: is the line number from where the log was called from.
+ * `%message`: is the message, made of concatenated arguments given by the caller.
+
+ For example, the following call:
+
+ ``` lua
+ kong.log("hello ", "world")
+ ```
+
+ would, within the core, produce a log line similar to:
+
+ ``` plain
+ 2017/07/09 19:36:25 [notice] 25932#0: *1 [kong] some_file.lua:54 hello world, client: 127.0.0.1, server: localhost, request: "GET /log HTTP/1.1", host: "localhost"
+ ```
+
+ If invoked from within a plugin (e.g. `key-auth`) it would include the
+ namespace prefix, like so:
+
+ ``` plain
+ 2017/07/09 19:36:25 [notice] 25932#0: *1 [kong] some_file.lua:54 [key-auth] hello world, client: 127.0.0.1, server: localhost, request: "GET /log HTTP/1.1", host: "localhost"
+ ```
+
+
+**Phases**
+
+* init_worker, certificate, rewrite, access, header_filter, body_filter, log
+
+**Parameters**
+
+* **...** : all params will be concatenated and stringified before being sent to the log
+
+**Returns**
+
+* Nothing; throws an error on invalid inputs.
+
+
+**Usage**
+
+``` lua
+kong.log("hello ", "world") -- alias to kong.log.notice()
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.log.LEVEL(...)
+
+Similar to `kong.log()`, but the produced log will have the severity given by
+ `
`, instead of `notice`. The supported levels are:
+
+ * `kong.log.alert()`
+ * `kong.log.crit()`
+ * `kong.log.err()`
+ * `kong.log.warn()`
+ * `kong.log.notice()`
+ * `kong.log.info()`
+ * `kong.log.debug()`
+
+ Logs have the same format as that of `kong.log()`. For
+ example, the following call:
+
+ ``` lua
+ kong.log.err("hello ", "world")
+ ```
+
+ would, within the core, produce a log line similar to:
+
+ ``` plain
+ 2017/07/09 19:36:25 [error] 25932#0: *1 [kong] some_file.lua:54 hello world, client: 127.0.0.1, server: localhost, request: "GET /log HTTP/1.1", host: "localhost"
+ ```
+
+ If invoked from within a plugin (e.g. `key-auth`) it would include the
+ namespace prefix, like so:
+
+ ``` plain
+ 2017/07/09 19:36:25 [error] 25932#0: *1 [kong] some_file.lua:54 [key-auth] hello world, client: 127.0.0.1, server: localhost, request: "GET /log HTTP/1.1", host: "localhost"
+ ```
+
+
+**Phases**
+
+* init_worker, certificate, rewrite, access, header_filter, body_filter, log
+
+**Parameters**
+
+* **...** : all params will be concatenated and stringified before being sent to the log
+
+**Returns**
+
+* Nothing; throws an error on invalid inputs.
+
+
+**Usage**
+
+``` lua
+kong.log.warn("something require attention")
+kong.log.err("something failed: ", err)
+kong.log.alert("something requires immediate action")
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.log.inspect(...)
+
+Like `kong.log()`, this function will produce a log with the `notice` level,
+ and accepts any number of arguments as well. If inspect logging is disabled
+ via `kong.log.inspect.off()`, then this function prints nothing, and is
+ aliased to a "NOP" function in order to save CPU cycles.
+
+ ``` lua
+ kong.log.inspect("...")
+ ```
+
+ This function differs from `kong.log()` in the sense that arguments will be
+ concatenated with a space(`" "`), and each argument will be
+ "pretty-printed":
+
+ * numbers will printed (e.g. `5` -> `"5"`)
+ * strings will be quoted (e.g. `"hi"` -> `'"hi"'`)
+ * array-like tables will be rendered (e.g. `{1,2,3}` -> `"{1, 2, 3}"`)
+ * dictionary-like tables will be rendered on multiple lines
+
+ This function is intended for use with debugging purposes in mind, and usage
+ in production code paths should be avoided due to the expensive formatting
+ operations it can perform. Existing statements can be left in production code
+ but nopped by calling `kong.log.inspect.off()`.
+
+ When writing logs, `kong.log.inspect()` always uses its own format, defined
+ as:
+
+ ``` plain
+ %file_src:%func_name:%line_src %message
+ ```
+
+ Where:
+
+ * `%file_src`: is the file name from where the log was called from.
+ * `%func_name`: is the name of the function from where the log was called
+ from.
+ * `%line_src`: is the line number from where the log was called from.
+ * `%message`: is the message, made of concatenated, pretty-printed arguments
+ given by the caller.
+
+ This function uses the [inspect.lua](https://github.com/kikito/inspect.lua)
+ library to pretty-print its arguments.
+
+
+**Phases**
+
+* init_worker, certificate, rewrite, access, header_filter, body_filter, log
+
+**Parameters**
+
+* **...** : Parameters will be concatenated with spaces between them and
+ rendered as described
+
+**Usage**
+
+``` lua
+kong.log.inspect("some value", a_variable)
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.log.inspect.on()
+
+Enables inspect logs for this logging facility. Calls to
+ `kong.log.inspect` will be writing log lines with the appropriate
+ formatting of arguments.
+
+
+**Phases**
+
+* init_worker, certificate, rewrite, access, header_filter, body_filter, log
+
+**Usage**
+
+``` lua
+kong.log.inspect.on()
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.log.inspect.off()
+
+Disables inspect logs for this logging facility. All calls to
+ `kong.log.inspect()` will be nopped.
+
+
+**Phases**
+
+* init_worker, certificate, rewrite, access, header_filter, body_filter, log
+
+**Usage**
+
+``` lua
+kong.log.inspect.off()
+```
+
+[Back to TOC](#table-of-contents)
+
diff --git a/app/enterprise/0.36-x/pdk/kong.node.md b/app/enterprise/0.36-x/pdk/kong.node.md
new file mode 100644
index 000000000000..b712a6340fd1
--- /dev/null
+++ b/app/enterprise/0.36-x/pdk/kong.node.md
@@ -0,0 +1,29 @@
+---
+title: kong.node
+pdk: true
+toc: true
+---
+
+## kong.node
+
+Node-level utilities
+
+
+
+### kong.node.get_id()
+
+Returns the id used by this node to describe itself.
+
+**Returns**
+
+* `string` The v4 UUID used by this node as its id
+
+
+**Usage**
+
+``` lua
+local id = kong.node.get_id()
+```
+
+[Back to TOC](#table-of-contents)
+
diff --git a/app/enterprise/0.36-x/pdk/kong.request.md b/app/enterprise/0.36-x/pdk/kong.request.md
new file mode 100644
index 000000000000..4f86f01fec99
--- /dev/null
+++ b/app/enterprise/0.36-x/pdk/kong.request.md
@@ -0,0 +1,599 @@
+---
+title: kong.request
+pdk: true
+toc: true
+---
+
+## kong.request
+
+Client request module
+ A set of functions to retrieve information about the incoming requests made
+ by clients.
+
+
+
+### kong.request.get_scheme()
+
+Returns the scheme component of the request's URL. The returned value is
+ normalized to lower-case form.
+
+
+**Phases**
+
+* rewrite, access, header_filter, body_filter, log, admin_api
+
+**Returns**
+
+* `string` a string like `"http"` or `"https"`
+
+
+**Usage**
+
+``` lua
+-- Given a request to https://example.com:1234/v1/movies
+
+kong.request.get_scheme() -- "https"
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.request.get_host()
+
+Returns the host component of the request's URL, or the value of the
+ "Host" header. The returned value is normalized to lower-case form.
+
+
+**Phases**
+
+* rewrite, access, header_filter, body_filter, log, admin_api
+
+**Returns**
+
+* `string` the host
+
+
+**Usage**
+
+``` lua
+-- Given a request to https://example.com:1234/v1/movies
+
+kong.request.get_host() -- "example.com"
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.request.get_port()
+
+Returns the port component of the request's URL. The value is returned
+ as a Lua number.
+
+
+**Phases**
+
+* certificate, rewrite, access, header_filter, body_filter, log, admin_api
+
+**Returns**
+
+* `number` the port
+
+
+**Usage**
+
+``` lua
+-- Given a request to https://example.com:1234/v1/movies
+
+kong.request.get_port() -- 1234
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.request.get_forwarded_scheme()
+
+Returns the scheme component of the request's URL, but also considers
+ `X-Forwarded-Proto` if it comes from a trusted source. The returned
+ value is normalized to lower-case.
+
+ Whether this function considers `X-Forwarded-Proto` or not depends on
+ several Kong configuration parameters:
+
+ * [trusted\_ips](/enterprise/{{page.kong_version}}/property-reference/#trusted_ips)
+ * [real\_ip\_header](/enterprise/{{page.kong_version}}/property-reference/#real_ip_header)
+ * [real\_ip\_recursive](/enterprise/{{page.kong_version}}/property-reference/#real_ip_recursive)
+
+ **Note**: support for the Forwarded HTTP Extension (RFC 7239) is not
+ offered yet since it is not supported by ngx\_http\_realip\_module.
+
+
+**Phases**
+
+* rewrite, access, header_filter, body_filter, log, admin_api
+
+**Returns**
+
+* `string` the forwarded scheme
+
+
+**Usage**
+
+``` lua
+kong.request.get_forwarded_scheme() -- "https"
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.request.get_forwarded_host()
+
+Returns the host component of the request's URL or the value of the "host"
+ header. Unlike `kong.request.get_host()`, this function will also consider
+ `X-Forwarded-Host` if it comes from a trusted source. The returned value
+ is normalized to lower-case.
+
+ Whether this function considers `X-Forwarded-Proto` or not depends on
+ several Kong configuration parameters:
+
+ * [trusted\_ips](/enterprise/{{page.kong_version}}/property-reference/#trusted_ips)
+ * [real\_ip\_header](/enterprise/{{page.kong_version}}/property-reference/#real_ip_header)
+ * [real\_ip\_recursive](/enterprise/{{page.kong_version}}/property-reference/#real_ip_recursive)
+
+ **Note**: we do not currently offer support for Forwarded HTTP Extension
+ (RFC 7239) since it is not supported by ngx_http_realip_module.
+
+
+**Phases**
+
+* rewrite, access, header_filter, body_filter, log, admin_api
+
+**Returns**
+
+* `string` the forwarded host
+
+
+**Usage**
+
+``` lua
+kong.request.get_forwarded_host() -- "example.com"
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.request.get_forwareded_port()
+
+Returns the port component of the request's URL, but also considers
+ `X-Forwarded-Host` if it comes from a trusted source. The value
+ is returned as a Lua number.
+
+ Whether this function considers `X-Forwarded-Proto` or not depends on
+ several Kong configuration parameters:
+
+ * [trusted\_ips](/enterprise/{{page.kong_version}}/property-reference/#trusted_ips)
+ * [real\_ip\_header](/enterprise/{{page.kong_version}}/property-reference/#real_ip_header)
+ * [real\_ip\_recursive](/enterprise/{{page.kong_version}}/property-reference/#real_ip_recursive)
+
+ **Note**: we do not currently offer support for Forwarded HTTP Extension
+ (RFC 7239) since it is not supported by ngx_http_realip_module.
+
+
+**Phases**
+
+* rewrite, access, header_filter, body_filter, log, admin_api
+
+**Returns**
+
+* `number` the forwared port
+
+
+**Usage**
+
+``` lua
+kong.request.get_forwarded_port() -- 1234
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.request.get_http_version()
+
+Returns the HTTP version used by the client in the request as a Lua
+ number, returning values such as `1`, `1.1`, `2.0`, or `nil` for
+ unrecognized values.
+
+**Phases**
+
+* rewrite, access, header_filter, body_filter, log, admin_api
+
+**Returns**
+
+* `number|nil` the http version
+
+
+**Usage**
+
+``` lua
+kong.request.get_http_version() -- 1.1
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.request.get_method()
+
+Returns the HTTP method of the request. The value is normalized to
+ upper-case.
+
+
+**Phases**
+
+* rewrite, access, header_filter, body_filter, log, admin_api
+
+**Returns**
+
+* `string` the request method
+
+
+**Usage**
+
+``` lua
+kong.request.get_method() -- "GET"
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.request.get_path()
+
+Returns the path component of the request's URL. It is not normalized in
+ any way and does not include the querystring.
+
+
+**Phases**
+
+* rewrite, access, header_filter, body_filter, log, admin_api
+
+**Returns**
+
+* `string` the path
+
+
+**Usage**
+
+``` lua
+-- Given a request to https://example.com:1234/v1/movies?movie=foo
+
+kong.request.get_path() -- "/v1/movies"
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.request.get_path_with_query()
+
+Returns the path, including the querystring if any. No
+ transformations/normalizations are done.
+
+
+**Phases**
+
+* rewrite, access, header_filter, body_filter, log, admin_api
+
+**Returns**
+
+* `string` the path with the querystring
+
+
+**Usage**
+
+``` lua
+-- Given a request to https://example.com:1234/v1/movies?movie=foo
+
+kong.request.get_path_with_query() -- "/v1/movies?movie=foo"
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.request.get_raw_query()
+
+Returns the query component of the request's URL. It is not normalized in
+ any way (not even URL-decoding of special characters) and does not
+ include the leading `?` character.
+
+
+**Phases**
+
+* rewrite, access, header_filter, body_filter, log, admin_api
+
+**Returns**
+
+* string the query component of the request's URL
+
+
+**Usage**
+
+``` lua
+-- Given a request to https://example.com/foo?msg=hello%20world&bla=&bar
+
+kong.request.get_raw_query() -- "msg=hello%20world&bla=&bar"
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.request.get_query_arg()
+
+Returns the value of the specified argument, obtained from the query
+ arguments of the current request.
+
+ The returned value is either a `string`, a boolean `true` if an
+ argument was not given a value, or `nil` if no argument with `name` was
+ found.
+
+ If an argument with the same name is present multiple times in the
+ querystring, this function will return the value of the first occurrence.
+
+
+**Phases**
+
+* rewrite, access, header_filter, body_filter, log, admin_api
+
+**Returns**
+
+* `string|boolean|nil` the value of the argument
+
+
+**Usage**
+
+``` lua
+-- Given a request GET /test?foo=hello%20world&bar=baz&zzz&blo=&bar=bla&bar
+
+kong.request.get_query_arg("foo") -- "hello world"
+kong.request.get_query_arg("bar") -- "baz"
+kong.request.get_query_arg("zzz") -- true
+kong.request.get_query_arg("blo") -- ""
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.request.get_query([max_args])
+
+Returns the table of query arguments obtained from the querystring. Keys
+ are query argument names. Values are either a string with the argument
+ value, a boolean `true` if an argument was not given a value, or an array
+ if an argument was given in the query string multiple times. Keys and
+ values are unescaped according to URL-encoded escaping rules.
+
+ Note that a query string `?foo&bar` translates to two boolean `true`
+ arguments, and `?foo=&bar=` translates to two string arguments containing
+ empty strings.
+
+ By default, this function returns up to **100** arguments. The optional
+ `max_args` argument can be specified to customize this limit, but must be
+ greater than **1** and not greater than **1000**.
+
+
+**Phases**
+
+* rewrite, access, header_filter, body_filter, log, admin_api
+
+**Parameters**
+
+* **max_args** (number, _optional_): set a limit on the maximum number of parsed
+ arguments
+
+**Returns**
+
+* `table` A table representation of the query string
+
+
+**Usage**
+
+``` lua
+-- Given a request GET /test?foo=hello%20world&bar=baz&zzz&blo=&bar=bla&bar
+
+for k, v in pairs(kong.request.get_query()) do
+ kong.log.inspect(k, v)
+end
+
+-- Will print
+-- "foo" "hello world"
+-- "bar" {"baz", "bla", true}
+-- "zzz" true
+-- "blo" ""
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.request.get_header(name)
+
+Returns the value of the specified request header.
+
+ The returned value is either a `string`, or can be `nil` if a header with
+ `name` was not found in the request. If a header with the same name is
+ present multiple times in the request, this function will return the value
+ of the first occurrence of this header.
+
+ Header names in are case-insensitive and are normalized to lowercase, and
+ dashes (`-`) can be written as underscores (`_`); that is, the header
+ `X-Custom-Header` can also be retrieved as `x_custom_header`.
+
+
+**Phases**
+
+* rewrite, access, header_filter, body_filter, log, admin_api
+
+**Parameters**
+
+* **name** (string): the name of the header to be returned
+
+**Returns**
+
+* `string|nil` the value of the header or nil if not present
+
+
+**Usage**
+
+``` lua
+-- Given a request with the following headers:
+
+-- Host: foo.com
+-- X-Custom-Header: bla
+-- X-Another: foo bar
+-- X-Another: baz
+
+kong.request.get_header("Host") -- "foo.com"
+kong.request.get_header("x-custom-header") -- "bla"
+kong.request.get_header("X-Another") -- "foo bar"
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.request.get_headers([max_headers])
+
+Returns a Lua table holding the request headers. Keys are header names.
+ Values are either a string with the header value, or an array of strings
+ if a header was sent multiple times. Header names in this table are
+ case-insensitive and are normalized to lowercase, and dashes (`-`) can be
+ written as underscores (`_`); that is, the header `X-Custom-Header` can
+ also be retrieved as `x_custom_header`.
+
+ By default, this function returns up to **100** headers. The optional
+ `max_headers` argument can be specified to customize this limit, but must
+ be greater than **1** and not greater than **1000**.
+
+
+**Phases**
+
+* rewrite, access, header_filter, body_filter, log, admin_api
+
+**Parameters**
+
+* **max_headers** (number, _optional_): set a limit on the maximum number of
+ parsed headers
+
+**Returns**
+
+* `table` the request headers in table form
+
+
+**Usage**
+
+``` lua
+-- Given a request with the following headers:
+
+-- Host: foo.com
+-- X-Custom-Header: bla
+-- X-Another: foo bar
+-- X-Another: baz
+local headers = kong.request.get_headers()
+
+headers.host -- "foo.com"
+headers.x_custom_header -- "bla"
+headers.x_another[1] -- "foo bar"
+headers["X-Another"][2] -- "baz"
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.request.get_raw_body()
+
+Returns the plain request body.
+
+ If the body has no size (empty), this function returns an empty string.
+
+ If the size of the body is greater than the Nginx buffer size (set by
+ `client_body_buffer_size`), this function will fail and return an error
+ message explaining this limitation.
+
+
+**Phases**
+
+* rewrite, access, admin_api
+
+**Returns**
+
+* `string` the plain request body
+
+
+**Usage**
+
+``` lua
+-- Given a body with payload "Hello, Earth!":
+
+kong.request.get_raw_body():gsub("Earth", "Mars") -- "Hello, Mars!"
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.request.get_body([mimetype[, max_args]])
+
+Returns the request data as a key/value table.
+ A high-level convenience function.
+ The body is parsed with the most appropriate format:
+
+ * If `mimetype` is specified:
+ * Decodes the body with the requested content type (if supported).
+ * If the request content type is `application/x-www-form-urlencoded`:
+ * Returns the body as form-encoded.
+ * If the request content type is `multipart/form-data`:
+ * Decodes the body as multipart form data
+ (same as `multipart(kong.request.get_raw_body(),
+ kong.request.get_header("Content-Type")):get_all()` ).
+ * If the request content type is `application/json`:
+ * Decodes the body as JSON
+ (same as `json.decode(kong.request.get_raw_body())`).
+ * JSON types are converted to matching Lua types.
+ * If none of the above, returns `nil` and an error message indicating the
+ body could not be parsed.
+
+ The optional argument `mimetype` can be one of the following strings:
+
+ * `application/x-www-form-urlencoded`
+ * `application/json`
+ * `multipart/form-data`
+
+ The optional argument `max_args` can be used to set a limit on the number
+ of form arguments parsed for `application/x-www-form-urlencoded` payloads.
+
+ The third return value is string containing the mimetype used to parsed
+ the body (as per the `mimetype` argument), allowing the caller to identify
+ what MIME type the body was parsed as.
+
+
+**Phases**
+
+* rewrite, access, admin_api
+
+**Parameters**
+
+* **mimetype** (string, _optional_): the MIME type
+* **max_args** (number, _optional_): set a limit on the maximum number of parsed
+ arguments
+
+**Returns**
+
+1. `table|nil` a table representation of the body
+
+1. `string|nil` an error message
+
+1. `string|nil` mimetype the MIME type used
+
+
+**Usage**
+
+``` lua
+local body, err, mimetype = kong.request.get_body()
+body.name -- "John Doe"
+body.age -- "42"
+```
+
+[Back to TOC](#table-of-contents)
+
diff --git a/app/enterprise/0.36-x/pdk/kong.response.md b/app/enterprise/0.36-x/pdk/kong.response.md
new file mode 100644
index 000000000000..34e0288186a0
--- /dev/null
+++ b/app/enterprise/0.36-x/pdk/kong.response.md
@@ -0,0 +1,469 @@
+---
+title: kong.response
+pdk: true
+toc: true
+---
+
+## kong.response
+
+Client response module
+
+ The downstream response module contains a set of functions for producing and
+ manipulating responses sent back to the client ("downstream"). Responses can
+ be produced by Kong (e.g. an authentication plugin rejecting a request), or
+ proxied back from an Service's response body.
+
+ Unlike `kong.service.response`, this module allows mutating the response
+ before sending it back to the client.
+
+
+
+
+### kong.response.get_status()
+
+Returns the HTTP status code currently set for the downstream response (as
+ a Lua number).
+
+ If the request was proxied (as per `kong.response.get_source()`), the
+ return value will be that of the response from the Service (identical to
+ `kong.service.response.get_status()`).
+
+ If the request was _not_ proxied, and the response was produced by Kong
+ itself (i.e. via `kong.response.exit()`), the return value will be
+ returned as-is.
+
+
+**Phases**
+
+* header_filter, body_filter, log, admin_api
+
+**Returns**
+
+* `number` status The HTTP status code currently set for the
+ downstream response
+
+
+**Usage**
+
+``` lua
+kong.response.get_status() -- 200
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.response.get_header(name)
+
+Returns the value of the specified response header, as would be seen by
+ the client once received.
+
+ The list of headers returned by this function can consist of both response
+ headers from the proxied Service _and_ headers added by Kong (e.g. via
+ `kong.response.add_header()`).
+
+ The return value is either a `string`, or can be `nil` if a header with
+ `name` was not found in the response. If a header with the same name is
+ present multiple times in the request, this function will return the value
+ of the first occurrence of this header.
+
+
+**Phases**
+
+* header_filter, body_filter, log, admin_api
+
+**Parameters**
+
+* **name** (string): The name of the header
+
+ Header names are case-insensitive and dashes (`-`) can be written as
+ underscores (`_`); that is, the header `X-Custom-Header` can also be
+ retrieved as `x_custom_header`.
+
+
+**Returns**
+
+* `string|nil` The value of the header
+
+
+**Usage**
+
+``` lua
+-- Given a response with the following headers:
+-- X-Custom-Header: bla
+-- X-Another: foo bar
+-- X-Another: baz
+
+kong.response.get_header("x-custom-header") -- "bla"
+kong.response.get_header("X-Another") -- "foo bar"
+kong.response.get_header("X-None") -- nil
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.response.get_headers([max_headers])
+
+Returns a Lua table holding the response headers. Keys are header names.
+ Values are either a string with the header value, or an array of strings
+ if a header was sent multiple times. Header names in this table are
+ case-insensitive and are normalized to lowercase, and dashes (`-`) can be
+ written as underscores (`_`); that is, the header `X-Custom-Header` can
+ also be retrieved as `x_custom_header`.
+
+ A response initially has no headers until a plugin short-circuits the
+ proxying by producing one (e.g. an authentication plugin rejecting a
+ request), or the request has been proxied, and one of the latter execution
+ phases is currently running.
+
+ Unlike `kong.service.response.get_headers()`, this function returns *all*
+ headers as the client would see them upon reception, including headers
+ added by Kong itself.
+
+ By default, this function returns up to **100** headers. The optional
+ `max_headers` argument can be specified to customize this limit, but must
+ be greater than **1** and not greater than **1000**.
+
+
+**Phases**
+
+* header_filter, body_filter, log, admin_api
+
+**Parameters**
+
+* **max_headers** (number, _optional_): Limits how many headers are parsed
+
+**Returns**
+
+1. `table` headers A table representation of the headers in the
+ response
+
+
+1. `string` err If more headers than `max_headers` were present, a
+ string with the error `"truncated"`.
+
+
+**Usage**
+
+``` lua
+-- Given an response from the Service with the following headers:
+-- X-Custom-Header: bla
+-- X-Another: foo bar
+-- X-Another: baz
+
+local headers = kong.response.get_headers()
+
+headers.x_custom_header -- "bla"
+headers.x_another[1] -- "foo bar"
+headers["X-Another"][2] -- "baz"
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.response.get_source()
+
+This function helps determining where the current response originated
+ from. Kong being a reverse proxy, it can short-circuit a request and
+ produce a response of its own, or the response can come from the proxied
+ Service.
+
+ Returns a string with three possible values:
+
+ * "exit" is returned when, at some point during the processing of the
+ request, there has been a call to `kong.response.exit()`. In other
+ words, when the request was short-circuited by a plugin or by Kong
+ itself (e.g. invalid credentials)
+ * "error" is returned when an error has happened while processing the
+ request - for example, a timeout while connecting to the upstream
+ service.
+ * "service" is returned when the response was originated by successfully
+ contacting the proxied Service.
+
+
+**Phases**
+
+* header_filter, body_filter, log, admin_api
+
+**Returns**
+
+* `string` the source.
+
+
+**Usage**
+
+``` lua
+if kong.response.get_source() == "service" then
+ kong.log("The response comes from the Service")
+elseif kong.response.get_source() == "error" then
+ kong.log("There was an error while processing the request")
+elseif kong.response.get_source() == "exit" then
+ kong.log("There was an early exit while processing the request")
+end
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.response.set_status(status)
+
+Allows changing the downstream response HTTP status code before sending it
+ to the client.
+
+ This function should be used in the `header_filter` phase, as Kong is
+ preparing headers to be sent back to the client.
+
+
+**Phases**
+
+* rewrite, access, header_filter, admin_api
+
+**Parameters**
+
+* **status** (number): The new status
+
+**Returns**
+
+* Nothing; throws an error on invalid input.
+
+
+**Usage**
+
+``` lua
+kong.response.set_status(404)
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.response.set_header(name, value)
+
+Sets a response header with the given value. This function overrides any
+ existing header with the same name.
+
+ This function should be used in the `header_filter` phase, as Kong is
+ preparing headers to be sent back to the client.
+
+**Phases**
+
+* rewrite, access, header_filter, admin_api
+
+**Parameters**
+
+* **name** (string): The name of the header
+* **value** (string|number|boolean): The new value for the header
+
+**Returns**
+
+* Nothing; throws an error on invalid input.
+
+
+**Usage**
+
+``` lua
+kong.response.set_header("X-Foo", "value")
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.response.add_header(name, value)
+
+Adds a response header with the given value. Unlike
+ `kong.response.set_header()`, this function does not remove any existing
+ header with the same name. Instead, another header with the same name will
+ be added to the response. If no header with this name already exists on
+ the response, then it is added with the given value, similarly to
+ `kong.response.set_header().`
+
+ This function should be used in the `header_filter` phase, as Kong is
+ preparing headers to be sent back to the client.
+
+**Phases**
+
+* rewrite, access, header_filter, admin_api
+
+**Parameters**
+
+* **name** (string): The header name
+* **value** (string|number|boolean): The header value
+
+**Returns**
+
+* Nothing; throws an error on invalid input.
+
+
+**Usage**
+
+``` lua
+kong.response.add_header("Cache-Control", "no-cache")
+kong.response.add_header("Cache-Control", "no-store")
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.response.clear_header(name)
+
+Removes all occurrences of the specified header in the response sent to
+ the client.
+
+ This function should be used in the `header_filter` phase, as Kong is
+ preparing headers to be sent back to the client.
+
+
+**Phases**
+
+* rewrite, access, header_filter, admin_api
+
+**Parameters**
+
+* **name** (string): The name of the header to be cleared
+
+**Returns**
+
+* Nothing; throws an error on invalid input.
+
+
+**Usage**
+
+``` lua
+kong.response.set_header("X-Foo", "foo")
+kong.response.add_header("X-Foo", "bar")
+
+kong.response.clear_header("X-Foo")
+-- from here onwards, no X-Foo headers will exist in the response
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.response.set_headers(headers)
+
+Sets the headers for the response. Unlike `kong.response.set_header()`,
+ the `headers` argument must be a table in which each key is a string
+ (corresponding to a header's name), and each value is a string, or an
+ array of strings.
+
+ This function should be used in the `header_filter` phase, as Kong is
+ preparing headers to be sent back to the client.
+
+ The resulting headers are produced in lexicographical order. The order of
+ entries with the same name (when values are given as an array) is
+ retained.
+
+ This function overrides any existing header bearing the same name as those
+ specified in the `headers` argument. Other headers remain unchanged.
+
+
+**Phases**
+
+* rewrite, access, header_filter, admin_api
+
+**Parameters**
+
+* **headers** (table):
+
+**Returns**
+
+* Nothing; throws an error on invalid input.
+
+
+**Usage**
+
+``` lua
+kong.response.set_headers({
+ ["Bla"] = "boo",
+ ["X-Foo"] = "foo3",
+ ["Cache-Control"] = { "no-store", "no-cache" }
+})
+
+-- Will add the following headers to the response, in this order:
+-- X-Bar: bar1
+-- Bla: boo
+-- Cache-Control: no-store
+-- Cache-Control: no-cache
+-- X-Foo: foo3
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.response.exit(status[, body[, headers]])
+
+This function interrupts the current processing and produces a response.
+ It is typical to see plugins using it to produce a response before Kong
+ has a chance to proxy the request (e.g. an authentication plugin rejecting
+ a request, or a caching plugin serving a cached response).
+
+ It is recommended to use this function in conjunction with the `return`
+ operator, to better reflect its meaning:
+
+ ```lua
+ return kong.response.exit(200, "Success")
+ ```
+
+ Calling `kong.response.exit()` will interrupt the execution flow of
+ plugins in the current phase. Subsequent phases will still be invoked.
+ E.g. if a plugin called `kong.response.exit()` in the `access` phase, no
+ other plugin will be executed in that phase, but the `header_filter`,
+ `body_filter`, and `log` phases will still be executed, along with their
+ plugins. Plugins should thus be programmed defensively against cases when
+ a request was **not** proxied to the Service, but instead was produced by
+ Kong itself.
+
+ The first argument `status` will set the status code of the response that
+ will be seen by the client.
+
+ The second, optional, `body` argument will set the response body. If it is
+ a string, no special processing will be done, and the body will be sent
+ as-is. It is the caller's responsibility to set the appropriate
+ Content-Type header via the third argument. As a convenience, `body` can
+ be specified as a table; in which case, it will be JSON-encoded and the
+ `application/json` Content-Type header will be set.
+
+ The third, optional, `headers` argument can be a table specifying response
+ headers to send. If specified, its behavior is similar to
+ `kong.response.set_headers()`.
+
+ Unless manually specified, this method will automatically set the
+ Content-Length header in the produced response for convenience.
+
+**Phases**
+
+* rewrite, access, admin_api, header_filter (only if `body` is nil)
+
+**Parameters**
+
+* **status** (number): The status to be used
+* **body** (table|string, _optional_): The body to be used
+* **headers** (table, _optional_): The headers to be used
+
+**Returns**
+
+* Nothing; throws an error on invalid input.
+
+
+**Usage**
+
+``` lua
+return kong.response.exit(403, "Access Forbidden", {
+ ["Content-Type"] = "text/plain",
+ ["WWW-Authenticate"] = "Basic"
+})
+
+---
+
+return kong.response.exit(403, [[{"message":"Access Forbidden"}]], {
+ ["Content-Type"] = "application/json",
+ ["WWW-Authenticate"] = "Basic"
+})
+
+---
+
+return kong.response.exit(403, { message = "Access Forbidden" }, {
+ ["WWW-Authenticate"] = "Basic"
+})
+```
+
+[Back to TOC](#table-of-contents)
+
diff --git a/app/enterprise/0.36-x/pdk/kong.router.md b/app/enterprise/0.36-x/pdk/kong.router.md
new file mode 100644
index 000000000000..c30ceb5fca48
--- /dev/null
+++ b/app/enterprise/0.36-x/pdk/kong.router.md
@@ -0,0 +1,68 @@
+---
+title: kong.router
+pdk: true
+toc: true
+---
+
+## kong.router
+
+Router module
+ A set of functions to access the routing properties of the request.
+
+
+
+### kong.router.get_route()
+
+Returns the current `route` entity. The request was matched against this
+ route.
+
+
+**Phases**
+
+* access, header_filter, body_filter, log
+
+**Returns**
+
+* `table` the `route` entity.
+
+
+**Usage**
+
+``` lua
+if kong.router.get_route() then
+ -- routed by route & service entities
+else
+ -- routed by a legacy API entity
+end
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.router.get_service()
+
+Returns the current `service` entity. The request will be targetted to this
+ upstream service.
+
+
+**Phases**
+
+* access, header_filter, body_filter, log
+
+**Returns**
+
+* `table` the `service` entity.
+
+
+**Usage**
+
+``` lua
+if kong.router.get_service() then
+ -- routed by route & service entities
+else
+ -- routed by a legacy API entity
+end
+```
+
+[Back to TOC](#table-of-contents)
+
diff --git a/app/enterprise/0.36-x/pdk/kong.service.md b/app/enterprise/0.36-x/pdk/kong.service.md
new file mode 100644
index 000000000000..dce94eb96192
--- /dev/null
+++ b/app/enterprise/0.36-x/pdk/kong.service.md
@@ -0,0 +1,89 @@
+---
+title: kong.service
+pdk: true
+toc: true
+---
+
+## kong.service
+
+The service module contains a set of functions to manipulate the connection
+ aspect of the request to the Service, such as connecting to a given host, IP
+ address/port, or choosing a given Upstream entity for load-balancing and
+ healthchecking.
+
+
+
+### kong.service.set_upstream(host)
+
+Sets the desired Upstream entity to handle the load-balancing step for
+ this request. Using this method is equivalent to creating a Service with a
+ `host` property equal to that of an Upstream entity (in which case, the
+ request would be proxied to one of the Targets associated with that
+ Upstream).
+
+ The `host` argument should receive a string equal to that of one of the
+ Upstream entities currently configured.
+
+
+**Phases**
+
+* access
+
+**Parameters**
+
+* **host** (string):
+
+**Returns**
+
+1. `boolean|nil` `true` on success, or `nil` if no upstream entities
+ where found
+
+1. `string|nil` An error message describing the error if there was
+ one.
+
+
+
+**Usage**
+
+``` lua
+local ok, err = kong.service.set_upstream("service.prod")
+if not ok then
+ kong.log.err(err)
+ return
+end
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.service.set_target(host, port)
+
+Sets the host and port on which to connect to for proxying the request. ]]
+ Using this method is equivalent to ask Kong to not run the load-balancing
+ phase for this request, and consider it manually overridden.
+ Load-balancing components such as retries and health-checks will also be
+ ignored for this request.
+
+ The `host` argument expects a string containing the IP address of the
+ upstream server (IPv4/IPv6), and the `port` argument must contain a number
+ representing the port on which to connect to.
+
+
+**Phases**
+
+* access
+
+**Parameters**
+
+* **host** (string):
+* **port** (number):
+
+**Usage**
+
+``` lua
+kong.service.set_target("service.local", 443)
+kong.service.set_target("192.168.130.1", 80)
+```
+
+[Back to TOC](#table-of-contents)
+
diff --git a/app/enterprise/0.36-x/pdk/kong.service.request.md b/app/enterprise/0.36-x/pdk/kong.service.request.md
new file mode 100644
index 000000000000..c47d45e974b6
--- /dev/null
+++ b/app/enterprise/0.36-x/pdk/kong.service.request.md
@@ -0,0 +1,437 @@
+---
+title: kong.service.request
+pdk: true
+toc: true
+---
+
+## kong.service.request
+
+Manipulation of the request to the Service
+
+
+
+### kong.service.request.set_scheme(scheme)
+
+Sets the protocol to use when proxying the request to the Service.
+
+**Phases**
+
+* `access`
+
+**Parameters**
+
+* **scheme** (string): The scheme to be used. Supported values are `"http"` or `"https"`
+
+**Returns**
+
+* Nothing; throws an error on invalid inputs.
+
+
+**Usage**
+
+``` lua
+kong.service.request.set_scheme("https")
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.service.request.set_path(path)
+
+Sets the path component for the request to the service. It is not
+ normalized in any way and should **not** include the querystring.
+
+**Phases**
+
+* `access`
+
+**Parameters**
+
+* **path** : The path string. Example: "/v2/movies"
+
+**Returns**
+
+* Nothing; throws an error on invalid inputs.
+
+
+**Usage**
+
+``` lua
+kong.service.request.set_path("/v2/movies")
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.service.request.set_raw_query(query)
+
+Sets the querystring of the request to the Service. The `query` argument is a
+ string (without the leading `?` character), and will not be processed in any
+ way.
+
+ For a higher-level function to set the query string from a Lua table of
+ arguments, see `kong.service.request.set_query()`.
+
+**Phases**
+
+* `rewrite`, `access`
+
+**Parameters**
+
+* **query** (string): The raw querystring. Example: "foo=bar&bla&baz=hello%20world"
+
+**Returns**
+
+* Nothing; throws an error on invalid inputs.
+
+
+**Usage**
+
+``` lua
+kong.service.request.set_raw_query("zzz&bar=baz&bar=bla&bar&blo=&foo=hello%20world")
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.service.request.set_method(method)
+
+Sets the HTTP method for the request to the service.
+
+**Phases**
+
+* `rewrite`, `access`
+
+**Parameters**
+
+* **method** : The method string, which should be given in all
+ uppercase. Supported values are: `"GET"`, `"HEAD"`, `"PUT"`, `"POST"`,
+ `"DELETE"`, `"OPTIONS"`, `"MKCOL"`, `"COPY"`, `"MOVE"`, `"PROPFIND"`,
+ `"PROPPATCH"`, `"LOCK"`, `"UNLOCK"`, `"PATCH"`, `"TRACE"`.
+
+**Returns**
+
+* Nothing; throws an error on invalid inputs.
+
+
+**Usage**
+
+``` lua
+kong.service.request.set_method("DELETE")
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.service.request.set_query(args)
+
+Set the querystring of the request to the Service.
+
+ Unlike `kong.service.request.set_raw_query()`, the `query` argument must be a
+ table in which each key is a string (corresponding to an arguments name), and
+ each value is either a boolean, a string or an array of strings or booleans.
+ Additionally, all string values will be URL-encoded.
+
+ The resulting querystring will contain keys in their lexicographical order. The
+ order of entries within the same key (when values are given as an array) is
+ retained.
+
+ If further control of the querystring generation is needed, a raw querystring
+ can be given as a string with `kong.service.request.set_raw_query()`.
+
+
+**Phases**
+
+* `rewrite`, `access`
+
+**Parameters**
+
+* **args** (table): A table where each key is a string (corresponding to an
+ argument name), and each value is either a boolean, a string or an array of
+ strings or booleans. Any string values given are URL-encoded.
+
+**Returns**
+
+* Nothing; throws an error on invalid inputs.
+
+
+**Usage**
+
+``` lua
+kong.service.request.set_query({
+ foo = "hello world",
+ bar = {"baz", "bla", true},
+ zzz = true,
+ blo = ""
+})
+-- Will produce the following query string:
+-- bar=baz&bar=bla&bar&blo=&foo=hello%20world&zzz
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.service.request.set_header(header, value)
+
+Sets a header in the request to the Service with the given value. Any existing header
+ with the same name will be overridden.
+
+ If the `header` argument is `"host"` (case-insensitive), then this is
+ will also set the SNI of the request to the Service.
+
+
+**Phases**
+
+* `rewrite`, `access`
+
+**Parameters**
+
+* **header** (string): The header name. Example: "X-Foo"
+* **value** (string|boolean|number): The header value. Example: "hello world"
+
+**Returns**
+
+* Nothing; throws an error on invalid inputs.
+
+
+**Usage**
+
+``` lua
+kong.service.request.set_header("X-Foo", "value")
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.service.request.add_header(header, value)
+
+Adds a request header with the given value to the request to the Service. Unlike
+ `kong.service.request.set_header()`, this function will not remove any existing
+ headers with the same name. Instead, several occurences of the header will be
+ present in the request. The order in which headers are added is retained.
+
+
+**Phases**
+
+* `rewrite`, `access`
+
+**Parameters**
+
+* **header** (string): The header name. Example: "Cache-Control"
+* **value** (string|number|boolean): The header value. Example: "no-cache"
+
+**Returns**
+
+* Nothing; throws an error on invalid inputs.
+
+
+**Usage**
+
+``` lua
+kong.service.request.add_header("Cache-Control", "no-cache")
+kong.service.request.add_header("Cache-Control", "no-store")
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.service.request.clear_header(header)
+
+Removes all occurrences of the specified header in the request to the Service.
+
+**Phases**
+
+* `rewrite`, `access`
+
+**Parameters**
+
+* **header** (string): The header name. Example: "X-Foo"
+
+**Returns**
+
+* Nothing; throws an error on invalid inputs.
+ The function does not throw an error if no header was removed.
+
+
+**Usage**
+
+``` lua
+kong.service.request.set_header("X-Foo", "foo")
+kong.service.request.add_header("X-Foo", "bar")
+kong.service.request.clear_header("X-Foo")
+-- from here onwards, no X-Foo headers will exist in the request
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.service.request.set_headers(headers)
+
+Sets the headers of the request to the Service. Unlike
+ `kong.service.request.set_header()`, the `headers` argument must be a table in
+ which each key is a string (corresponding to a header's name), and each value
+ is a string, or an array of strings.
+
+ The resulting headers are produced in lexicographical order. The order of
+ entries with the same name (when values are given as an array) is retained.
+
+ This function overrides any existing header bearing the same name as those
+ specified in the `headers` argument. Other headers remain unchanged.
+
+ If the `"Host"` header is set (case-insensitive), then this is
+ will also set the SNI of the request to the Service.
+
+**Phases**
+
+* `rewrite`, `access`
+
+**Parameters**
+
+* **headers** (table): A table where each key is a string containing a header name
+ and each value is either a string or an array of strings.
+
+**Returns**
+
+* Nothing; throws an error on invalid inputs.
+
+
+**Usage**
+
+``` lua
+kong.service.request.set_header("X-Foo", "foo1")
+kong.service.request.add_header("X-Foo", "foo2")
+kong.service.request.set_header("X-Bar", "bar1")
+kong.service.request.set_headers({
+ ["X-Foo"] = "foo3",
+ ["Cache-Control"] = { "no-store", "no-cache" },
+ ["Bla"] = "boo"
+})
+
+-- Will add the following headers to the request, in this order:
+-- X-Bar: bar1
+-- Bla: boo
+-- Cache-Control: no-store
+-- Cache-Control: no-cache
+-- X-Foo: foo3
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.service.request.set_raw_body(body)
+
+Sets the body of the request to the Service.
+
+ The `body` argument must be a string and will not be processed in any way.
+ This function also sets the `Content-Length` header appropriately. To set an
+ empty body, one can give an empty string `""` to this function.
+
+ For a higher-level function to set the body based on the request content type,
+ see `kong.service.request.set_body()`.
+
+**Phases**
+
+* `rewrite`, `access`
+
+**Parameters**
+
+* **body** (string): The raw body
+
+**Returns**
+
+* Nothing; throws an error on invalid inputs.
+
+
+**Usage**
+
+``` lua
+kong.service.request.set_raw_body("Hello, world!")
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.service.request.set_body(args[, mimetype])
+
+Sets the body of the request to the Service. Unlike
+ `kong.service.request.set_raw_body()`, the `args` argument must be a table, and
+ will be encoded with a MIME type. The encoding MIME type can be specified in
+ the optional `mimetype` argument, or if left unspecified, will be chosen based
+ on the `Content-Type` header of the client's request.
+
+ If the MIME type is `application/x-www-form-urlencoded`:
+
+ * Encodes the arguments as form-encoded: keys are produced in lexicographical
+ order. The order of entries within the same key (when values are
+ given as an array) is retained. Any string values given are URL-encoded.
+
+ If the MIME type is `multipart/form-data`:
+
+ * Encodes the arguments as multipart form data.
+
+ If the MIME type is `application/json`:
+
+ * Encodes the arguments as JSON (same as
+ `kong.service.request.set_raw_body(json.encode(args))`)
+ * Lua types are converted to matching JSON types.mej
+
+ If none of the above, returns `nil` and an error message indicating the
+ body could not be encoded.
+
+ The optional argument `mimetype` can be one of:
+
+ * `application/x-www-form-urlencoded`
+ * `application/json`
+ * `multipart/form-data`
+
+ If the `mimetype` argument is specified, the `Content-Type` header will be
+ set accordingly in the request to the Service.
+
+ If further control of the body generation is needed, a raw body can be given as
+ a string with `kong.service.request.set_raw_body()`.
+
+
+**Phases**
+
+* `rewrite`, `access`
+
+**Parameters**
+
+* **args** (table): A table with data to be converted to the appropriate format
+ and stored in the body.
+* **mimetype** (string, _optional_): can be one of:
+
+**Returns**
+
+1. `boolean|nil` `true` on success, `nil` otherwise
+
+1. `string|nil` `nil` on success, an error message in case of error.
+ Throws an error on invalid inputs.
+
+
+**Usage**
+
+``` lua
+kong.service.set_header("application/json")
+local ok, err = kong.service.request.set_body({
+ name = "John Doe",
+ age = 42,
+ numbers = {1, 2, 3}
+})
+
+-- Produces the following JSON body:
+-- { "name": "John Doe", "age": 42, "numbers":[1, 2, 3] }
+
+local ok, err = kong.service.request.set_body({
+ foo = "hello world",
+ bar = {"baz", "bla", true},
+ zzz = true,
+ blo = ""
+}, "application/x-www-form-urlencoded")
+
+-- Produces the following body:
+-- bar=baz&bar=bla&bar&blo=&foo=hello%20world&zzz
+```
+
+[Back to TOC](#table-of-contents)
+
diff --git a/app/enterprise/0.36-x/pdk/kong.service.response.md b/app/enterprise/0.36-x/pdk/kong.service.response.md
new file mode 100644
index 000000000000..feede11b266e
--- /dev/null
+++ b/app/enterprise/0.36-x/pdk/kong.service.response.md
@@ -0,0 +1,132 @@
+---
+title: kong.service.response
+pdk: true
+toc: true
+---
+
+## kong.service.response
+
+Manipulation of the response from the Service
+
+
+
+### kong.service.response.get_status()
+
+Returns the HTTP status code of the response from the Service as a Lua number.
+
+**Phases**
+
+* `header_filter`, `body_filter`, `log`
+
+**Returns**
+
+* `number|nil` the status code from the response from the Service, or `nil`
+ if the request was not proxied (i.e. `kong.response.get_source()` returned
+ anything other than `"service"`.
+
+
+**Usage**
+
+``` lua
+kong.log.inspect(kong.service.response.get_status()) -- 418
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.service.response.get_headers([max_headers])
+
+Returns a Lua table holding the headers from the response from the Service. Keys are
+ header names. Values are either a string with the header value, or an array of
+ strings if a header was sent multiple times. Header names in this table are
+ case-insensitive and dashes (`-`) can be written as underscores (`_`); that is,
+ the header `X-Custom-Header` can also be retrieved as `x_custom_header`.
+
+ Unlike `kong.response.get_headers()`, this function will only return headers that
+ were present in the response from the Service (ignoring headers added by Kong itself).
+ If the request was not proxied to a Service (e.g. an authentication plugin rejected
+ a request and produced an HTTP 401 response), then the returned `headers` value
+ might be `nil`, since no response from the Service has been received.
+
+ By default, this function returns up to **100** headers. The optional
+ `max_headers` argument can be specified to customize this limit, but must be
+ greater than **1** and not greater than **1000**.
+
+**Phases**
+
+* `header_filter`, `body_filter`, `log`
+
+**Parameters**
+
+* **max_headers** (number, _optional_): customize the headers to parse
+
+**Returns**
+
+1. `table` the response headers in table form
+
+1. `string` err If more headers than `max_headers` were present, a
+ string with the error `"truncated"`.
+
+
+**Usage**
+
+``` lua
+-- Given a response with the following headers:
+-- X-Custom-Header: bla
+-- X-Another: foo bar
+-- X-Another: baz
+local headers = kong.service.response.get_headers()
+if headers then
+ kong.log.inspect(headers.x_custom_header) -- "bla"
+ kong.log.inspect(headers.x_another[1]) -- "foo bar"
+ kong.log.inspect(headers["X-Another"][2]) -- "baz"
+end
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.service.response.get_header(name)
+
+Returns the value of the specified response header.
+
+ Unlike `kong.response.get_header()`, this function will only return a header
+ if it was present in the response from the Service (ignoring headers added by Kong
+ itself).
+
+
+**Phases**
+
+* `header_filter`, `body_filter`, `log`
+
+**Parameters**
+
+* **name** (string): The name of the header.
+
+ Header names in are case-insensitive and are normalized to lowercase, and
+ dashes (`-`) can be written as underscores (`_`); that is, the header
+ `X-Custom-Header` can also be retrieved as `x_custom_header`.
+
+
+**Returns**
+
+* `string|nil` The value of the header, or `nil` if a header with
+ `name` was not found in the response. If a header with the same name is present
+ multiple times in the response, this function will return the value of the
+ first occurrence of this header.
+
+
+**Usage**
+
+``` lua
+-- Given a response with the following headers:
+-- X-Custom-Header: bla
+-- X-Another: foo bar
+-- X-Another: baz
+
+kong.log.inspect(kong.service.response.get_header("x-custom-header")) -- "bla"
+kong.log.inspect(kong.service.response.get_header("X-Another")) -- "foo bar"
+```
+
+[Back to TOC](#table-of-contents)
+
diff --git a/app/enterprise/0.36-x/pdk/kong.table.md b/app/enterprise/0.36-x/pdk/kong.table.md
new file mode 100644
index 000000000000..7e62db9eed94
--- /dev/null
+++ b/app/enterprise/0.36-x/pdk/kong.table.md
@@ -0,0 +1,67 @@
+---
+title: kong.table
+pdk: true
+toc: true
+---
+
+## kong.table
+
+Utilities for Lua tables
+
+
+
+### kong.table.new([narr[, nrec]])
+
+Returns a table with pre-allocated number of slots in its array and hash
+ parts.
+
+**Parameters**
+
+* **narr** (number, _optional_): specifies the number of slots to pre-allocate
+ in the array part.
+* **nrec** (number, _optional_): specifies the number of slots to pre-allocate in
+ the hash part.
+
+**Returns**
+
+* `table` the newly created table
+
+
+**Usage**
+
+``` lua
+local tab = kong.table.new(4, 4)
+```
+
+[Back to TOC](#table-of-contents)
+
+
+### kong.table.clear(tab)
+
+Clears a table from all of its array and hash parts entries.
+
+**Parameters**
+
+* **tab** (table): the table which will be cleared
+
+**Returns**
+
+* Nothing
+
+
+**Usage**
+
+``` lua
+local tab = {
+ "hello",
+ foo = "bar"
+}
+
+kong.table.clear(tab)
+
+kong.log(tab[1]) -- nil
+kong.log(tab.foo) -- nil
+```
+
+[Back to TOC](#table-of-contents)
+
diff --git a/app/enterprise/0.36-x/plugin-development/access-the-datastore.md b/app/enterprise/0.36-x/plugin-development/access-the-datastore.md
new file mode 100644
index 000000000000..f783a00d90a5
--- /dev/null
+++ b/app/enterprise/0.36-x/plugin-development/access-the-datastore.md
@@ -0,0 +1,75 @@
+---
+title: Plugin Development - Accessing the Datastore
+book: plugin_dev
+chapter: 5
+---
+
+## Introduction
+
+Kong interacts with the model layer through classes we refer to as "DAOs". This
+chapter will detail the available API to interact with the datastore.
+
+Kong supports two primary datastores: [Cassandra
+{{site.data.kong_latest.dependencies.cassandra}}](http://cassandra.apache.org/)
+and [PostgreSQL
+{{site.data.kong_latest.dependencies.postgres}}](http://www.postgresql.org/).
+
+## kong.db
+
+All entities in Kong are represented by:
+
+- A schema that describes which table the entity relates to in the datastore,
+ constraints on its fields such as foreign keys, non-null constraints etc.
+ This schema is a table described in the [plugin configuration]({{page.book.chapters.plugin-configuration}})
+ chapter.
+- An instance of the `DAO` class mapping to the database currently in use
+ (Cassandra or Postgres). This class' methods consume the schema and expose
+ methods to insert, update, select and delete entities of that type.
+
+The core entities in Kong are: Services, Routes, Consumers and Plugins.
+All of them are accessible as Data Access Objects (DAOs),
+through the `kong.db` global singleton:
+
+
+```lua
+-- Core DAOs
+local services = kong.db.services
+local routes = kong.db.routes
+local consumers = kong.db.consumers
+local plugins = kong.db.plugins
+```
+
+Both core entities from Kong and custom entities from plugins are
+available through `kong.db.*`.
+
+---
+
+## The DAO Lua API
+
+The DAO class is responsible for the operations executed on a given table in
+the datastore, generally mapping to an entity in Kong. All the underlying
+supported databases (currently Cassandra and Postgres) comply to the same
+interface, thus making the DAO compatible with all of them.
+
+For example, inserting a Service and a Plugin is as easy as:
+
+```lua
+local inserted_service, err = kong.db.services:insert({
+ name = "mockbin",
+ url = "http://mockbin.org",
+})
+
+local inserted_plugin, err = kong.db.plugins:insert({
+ name = "key-auth",
+ service = inserted_service,
+})
+```
+
+For a real-life example of the DAO being used in a plugin, see the
+[Key-Auth plugin source code](https://github.com/Kong/kong/blob/master/kong/plugins/key-auth/handler.lua).
+
+---
+
+Next: [Storing Custom Entities ›]({{page.book.next}})
+
+[Plugin Development Kit]: /enterprise/{{page.kong_version}}/pdk
diff --git a/app/enterprise/0.36-x/plugin-development/admin-api.md b/app/enterprise/0.36-x/plugin-development/admin-api.md
new file mode 100644
index 000000000000..f5a1211f6d9c
--- /dev/null
+++ b/app/enterprise/0.36-x/plugin-development/admin-api.md
@@ -0,0 +1,174 @@
+---
+title: Plugin Development - Extending the Admin API
+book: plugin_dev
+chapter: 8
+---
+
+
+
Note: This chapter assumes that you have a relative
+ knowledge of
Lapis.
+
+
+## Introduction
+
+Kong can be configured using a REST interface referred to as the [Admin API].
+Plugins can extend it by adding their own endpoints to accommodate custom
+entities or other personalized management needs. A typical example of this is
+the creation, retrieval, and deletion (commonly referred to as "CRUD
+operations") of API keys.
+
+The Admin API is a [Lapis](http://leafo.net/lapis/) application, and Kong's
+level of abstraction makes it easy for you to add endpoints.
+
+## Module
+
+```
+kong.plugins..api
+```
+
+## Adding endpoints to the Admin API
+
+Kong will detect and load your endpoints if they are defined in a module named:
+
+```
+"kong.plugins..api"
+```
+
+This module is bound to return a table with one or more entries with the following structure:
+
+``` lua
+{
+ [""] = {
+ schema = ,
+ methods = {
+ before = function(self) ... end,
+ on_error = function(self) ... end,
+ GET = function(self) ... end,
+ PUT = function(self) ... end,
+ ...
+ }
+ },
+ ...
+}
+```
+
+Where:
+
+- `` should be a string representing a route like `/users` (See [Lapis routes & URL
+ Patterns](http://leafo.net/lapis/reference/actions.html#routes--url-patterns)) for details.
+ Notice that the path can contain interpolation parameters, like `/users/:users/new`.
+- `` is a schema definition. Schemas for core and custom plugin entities are available
+ via `kong.db..schema`. The schema is used to parse certain fields according to their
+ types; for example if a field is marked as an integer, it will be parsed as such when it is
+ passed to a function (by default form fields are all strings).
+- The `methods` subtable contains functions, indexed by a string.
+ - The `before` key is optional and can hold a function. If present, the function will be executed
+ on every request that hits `path`, before any other function is invoked.
+ - One or more functions can be indexed with HTTP method names, like `GET` or `PUT`. These functions
+ will be executed when the appropriate HTTP method and `path` is matched. If a `before` function is
+ present on the `path`, it will be executed first. Keep in mind that `before` functions can
+ use `kong.response.exit` to finish early, effectively cancelling the "regular" http method function.
+ - The `on_error` key is optional and can hold a function. If present, the function will be executed
+ when the code from other functions (either from a `before` or a "http method") throws an error. If
+ not present, then Kong will use a default error handler to return the errors.
+
+For example:
+
+``` lua
+local endpoints = require "kong.api.endpoints"
+
+local credentials_schema = kong.db.keyauth_credentials.schema
+local consumers_schema = kong.db.consumers.schema
+
+return {
+ ["/consumers/:consumers/key-auth"] = {
+ schema = credentials_schema,
+ methods = {
+ GET = endpoints.get_collection_endpoint(
+ credentials_schema, consumers_schema, "consumer"),
+
+ POST = endpoints.post_collection_endpoint(
+ credentials_schema, consumers_schema, "consumer"),
+ },
+ },
+}
+```
+
+This code will create two Admin API endpoints in `/consumers/:consumers/key-auth`, to
+obtain (`GET`) and create (`POST`) credentials associated to a given consumer. On this example
+the functions are provided by the `kong.api.endpoints` library. If you want to see a more
+complete example, with custom code in functions, see
+[the `api.lua` file from the key-auth plugin](https://github.com/Kong/kong/blob/master/kong/plugins/key-auth/api.lua).
+
+The `endpoints` module currently contains the default implementation for the most usual CRUD
+operations used in Kong. This module provides you with helpers for any insert, retrieve,
+update or delete operations and performs the necessary DAO operations and replies with
+the appropriate HTTP status codes. It also provides you with functions to retrieve parameters from
+the path, such as an Service's name or id, or a Consumer's username or id.
+
+If `endpoints`-provided are functions not enough, a regular Lua function can be used instead. From there you can use:
+
+- Several functions provided by the `endpoints` module.
+- All the functionality provided by the [PDK](../../pdk)
+- The `self` parameter, which is the [Lapis request object](http://leafo.net/lapis/reference/actions.html#request-object).
+- And of course you can `require` any Lua modules if needed. Make sure they are compatible with OpenResty if you choose this route.
+
+``` lua
+local endpoints = require "kong.api.endpoints"
+
+local credentials_schema = kong.db.keyauth_credentials.schema
+local consumers_schema = kong.db.consumers.schema
+
+return {
+ ["/consumers/:consumers/key-auth/:keyauth_credentials"] = {
+ schema = credentials_schema,
+ methods = {
+ before = function(self, db, helpers)
+ local consumer, _, err_t = endpoints.select_entity(self, db, consumers_schema)
+ if err_t then
+ return endpoints.handle_error(err_t)
+ end
+ if not consumer then
+ return kong.response.exit(404, { message = "Not found" })
+ end
+
+ self.consumer = consumer
+
+ if self.req.method ~= "PUT" then
+ local cred, _, err_t = endpoints.select_entity(self, db, credentials_schema)
+ if err_t then
+ return endpoints.handle_error(err_t)
+ end
+
+ if not cred or cred.consumer.id ~= consumer.id then
+ return kong.response.exit(404, { message = "Not found" })
+ end
+ self.keyauth_credential = cred
+ self.params.keyauth_credentials = cred.id
+ end
+ end,
+ GET = endpoints.get_entity_endpoint(credentials_schema),
+ PUT = function(self, db, helpers)
+ self.args.post.consumer = { id = self.consumer.id }
+ return endpoints.put_entity_endpoint(credentials_schema)(self, db, helpers)
+ end,
+ },
+ },
+}
+```
+
+On the previous example, the `/consumers/:consumers/key-auth/:keyauth_credentials` path gets
+three functions:
+- The `before` function is a custom Lua function which uses several `endpoints`-provided utilities
+ (`endpoints.handle_error`) as well as PDK functions (`kong.response.exit`). It also populates
+ `self.consumer` for the subsequent functions to use.
+- The `GET` function is built entirely using `endpoints`. This is possible because the `before` has
+ "prepared" things in advance, like `self.consumer`.
+- The `PUT` function populates `self.args.post.consumer` before calling the `endpoints`-provided
+ `put_entity_endpoint` function.
+
+---
+
+Next: [Write tests for your plugin]({{page.book.next}})
+
+[Admin API]: /enterprise/{{page.kong_version}}/admin-api/
diff --git a/app/enterprise/0.36-x/plugin-development/custom-entities.md b/app/enterprise/0.36-x/plugin-development/custom-entities.md
new file mode 100644
index 000000000000..c8272133ce83
--- /dev/null
+++ b/app/enterprise/0.36-x/plugin-development/custom-entities.md
@@ -0,0 +1,645 @@
+---
+title: Plugin Development - Storing Custom Entities
+book: plugin_dev
+chapter: 6
+---
+
+## Introduction
+
+While not all plugins need it, your plugin might need to store more than
+its configuration in the database. In that case, Kong provides you with
+an abstraction on top of its primary datastores which allows you to store
+custom entities.
+
+As explained in the [previous chapter]({{page.book.previous}}), Kong interacts
+with the model layer through classes we refer to as "DAOs", and available on a
+singleton often referred to as the "DAO Factory". This chapter will explain how
+to to provide an abstraction for your own entities.
+
+## Modules
+
+```
+kong.plugins..daos
+kong.plugins..migrations.init
+kong.plugins..migrations.000_base_
+kong.plugins..migrations.001__to_
+kong.plugins..migrations.002__to_
+```
+
+## Create the migrations folder
+
+Once you have defined your model, you must create your migration modules which
+will be executed by Kong to create the table in which your records of your
+entity will be stored.
+
+If your plugin is intended to support both Cassandra and Postgres, then both
+migrations must be written.
+
+If your plugin doesn't have it already, you should add a `/migrations`
+folder to it. If there is no `init.lua` file inside already, you should create one.
+This is where all the migrations for your plugin will be referenced.
+
+The initial version of your `migrations/init.lua` file will point to a single migration.
+
+In this case we have called it `000_base_my_plugin`.
+
+``` lua
+-- `migrations/init.lua`
+return {
+ "000_base_my_plugin",
+}
+```
+
+This means that there will be a file in `/migrations/000_base_my_plugin.lua`
+containing the initial migrations. We'll see how this is done in a minute.
+
+## Adding a new migration to an existing plugin
+
+Sometimes it is necessary to introduce changes after a version of a plugin has already been
+released. A new functionality might be needed. A database table row might need changing.
+
+When this happens, *you must* create a new migrations file. You *must not* of modify the
+existing migration files once they are published (you can still make them more robust and
+bulletproof if you want, e.g. always try to write the migrations reentrant).
+
+While there is no strict rule for naming your migration files, there is a convention that the
+initial one is prefixed by `000`, the next one by `001`, and so on.
+
+Following with our previous example, if we wanted to release a new version of the plugin with
+changes in the database (for example, a table was needed called `foo`) we would insert it by
+adding a file called `/migrations/001_100_to_110.lua`, and referencing it on the
+migrations init file like so (where `100` is the previous version of the plugin `1.0.0` and
+`110` is the version to which plugin is migrated to `1.1.0`:
+
+
+``` lua
+-- `/migrations/init.lua`
+return {
+ "000_base_my_plugin",
+ "001_100_to_110",
+}
+```
+
+## Migration File syntax
+
+While Kong's core migrations support both Postgres and Cassandra, custom plugins
+can choose to support either both of them or just one.
+
+A migration file is a Lua file which returns a table with the following structure:
+
+``` lua
+-- `