diff --git a/app/.jekyll-metadata b/app/.jekyll-metadata new file mode 100644 index 000000000000..110c6c1b84a2 Binary files /dev/null and b/app/.jekyll-metadata differ diff --git a/app/_assets/images/icons/hub/kong-inc_degraphql.png b/app/_assets/images/icons/hub/kong-inc_degraphql.png new file mode 100644 index 000000000000..255bcbed045a Binary files /dev/null and b/app/_assets/images/icons/hub/kong-inc_degraphql.png differ diff --git a/app/_assets/images/icons/hub/kong-inc_exit-transformer.png b/app/_assets/images/icons/hub/kong-inc_exit-transformer.png new file mode 100644 index 000000000000..255bcbed045a Binary files /dev/null and b/app/_assets/images/icons/hub/kong-inc_exit-transformer.png differ diff --git a/app/_assets/images/icons/hub/kong-inc_graphql-proxy-cache-advanced.png b/app/_assets/images/icons/hub/kong-inc_graphql-proxy-cache-advanced.png new file mode 100644 index 000000000000..255bcbed045a Binary files /dev/null and b/app/_assets/images/icons/hub/kong-inc_graphql-proxy-cache-advanced.png differ diff --git a/app/_assets/images/icons/hub/kong-inc_proxy-cache-advanced.png b/app/_assets/images/icons/hub/kong-inc_proxy-cache-advanced.png new file mode 100644 index 000000000000..a9cc478dfe98 Binary files /dev/null and b/app/_assets/images/icons/hub/kong-inc_proxy-cache-advanced.png differ diff --git a/app/_data/docs_nav_ee_0.36-x.yml b/app/_data/docs_nav_ee_0.36-x.yml index b383e016ccb9..c4047d5e1698 100644 --- a/app/_data/docs_nav_ee_0.36-x.yml +++ b/app/_data/docs_nav_ee_0.36-x.yml @@ -58,8 +58,6 @@ - text: Rate Limiting Library url: /enterprise/references/rate-limiting absolute_url: true - - text: CLI reference - url: /cli - text: Proxy reference url: /proxy - text: Authentication reference diff --git a/app/_data/docs_nav_ee_1.3-x.yml b/app/_data/docs_nav_ee_1.3-x.yml new file mode 100644 index 000000000000..a36b5c0b9f61 --- /dev/null +++ b/app/_data/docs_nav_ee_1.3-x.yml @@ -0,0 +1,315 @@ +- title: Deployment + items: + - text: Licensing + url: /deployment/licensing + items: + - text: Overview + url: /deployment/licensing + - text: How to Access Your License + url: /deployment/access-license + - text: Installation + url: /deployment/installation/docker + items: + - text: Docker + url: /deployment/installation/docker + - text: Ubuntu + url: /deployment/installation/ubuntu + - text: CentOS + url: /deployment/installation/centos + - text: Amazon Linux + url: /deployment/installation/amazon-linux + - text: Changelog + url: /enterprise/changelog + absolute_url: true + - text: Migrating to 1.3 + url: /deployment/migrations + + +- title: Getting Started + url: /getting-started/ + items: + - text: Overview + url: /getting-started/ + - text: How to Start Kong Enterprise + url: /getting-started/start-kong + - text: How to Add a Workspace + url: /getting-started/add-workspace + - text: How to Add a Role and Permissions + url: /getting-started/add-role + - text: How to Add an Admin + url: /getting-started/add-admin + - text: How to Add a Service and Route + url: /getting-started/add-service + - text: How to Enable a Plugin + url: /getting-started/enable-plugin + - text: How to Add a Consumer + url: /getting-started/add-consumer + - text: How to Enable the Dev Portal + url: /getting-started/enable-dev-portal + +- title: Guides & References + url: /property-reference + items: + - text: Configuration Property Reference + url: /property-reference + - text: CLI Reference + url: /cli + - text: Rate Limiting Library + url: /enterprise/references/rate-limiting + absolute_url: true + - text: Proxy reference + url: /proxy + - text: Authentication reference + url: /auth + - text: Load balancing reference + url: /loadbalancing + - text: Health checks and circuit breakers reference + url: /health-checks-circuit-breakers + - text: Clustering reference + url: /clustering + - text: Logging reference + url: /logging + - text: Network & Firewall + url: /network + - text: Securing the Admin API + url: /secure-admin-api + - text: Plugin Development Guide + url: /plugin-development + - text: Plugin Development Kit + url: /pdk + - text : OpenAPI Spec to Kong Entities + url: /oasconfig + +- title: Admin API + url: /admin-api + items: + - text: Overview + url: /admin-api + - text: Supported Content Types + url: /admin-api/#supported-content-types + - text: Information Routes + url: /admin-api/#information-routes + - text: Tags + url: /admin-api/#tags + - text: Service Object + url: /admin-api/#service-object + - text: Route Object + url: /admin-api/#route-object + - text: Consumer Object + url: /admin-api/#consumer-object + - text: Plugin Object + url: /admin-api/#plugin-object + - text: Certificate Object + url: /admin-api/#certificate-object + - text: SNI Object + url: /admin-api/#sni-object + - text: Upstream Object + url: /admin-api/#upstream-object + - text: Target Object + url: /admin-api/#target-object + - text: Workspace Object routes + url: /admin-api/workspaces/reference + - text: RBAC Object routes + url: /admin-api/rbac/reference + - text: Workspaces + url: /admin-api/workspaces/reference + - text: RBAC + url: /admin-api/rbac/reference + - text: Admins + url: /admin-api/admins/reference + items: + - text: API Reference + url: /admin-api/admins/reference + - text: Examples + url: /admin-api/admins/examples + - text: Vitals + url: /admin-api/vitals + items: + - text: Vitals Overview + url: /admin-api/vitals + - text: Kong Vitals with InfluxDB + url: /admin-api/vitals/vitals-influx-strategy + - text: Kong Vitals with Prometheus + url: /admin-api/vitals/vitals-prometheus-strategy + - text: Audit Logging + url: /admin-api/audit-log + +- title: Kong Manager + url: /kong-manager/overview + items: + - text: Overview + url: /kong-manager/overview + - text: Service Directory Mapping + url: /kong-manager/service-directory-mapping + - text: Networking + url: /kong-manager/networking/configuration + items: + - text: Default and Custom Configuration + url: /kong-manager/networking/configuration + - text: Configuring to Send Email + url: /kong-manager/networking/email + - text: Securing Kong Manager + url: /kong-manager/security + - text: Authentication + url: /kong-manager/authentication/super-admin + items: + - text: How to Create a Super Admin + url: /kong-manager/authentication/super-admin + - text: Basic Auth + url: /kong-manager/authentication/basic + - text: LDAP + url: /kong-manager/authentication/ldap + - text: OIDC + url: /kong-manager/authentication/oidc + - text: Sessions + url: /kong-manager/authentication/sessions + - text: How to Reset Passwords and RBAC Tokens + url: /kong-manager/reset-password + - text: Administration + url: /kong-manager/administration/workspaces/workspaces + items: + - text: Workspaces + url: /kong-manager/administration/workspaces/workspaces + - items: + - text: Workspaces in Kong Manager + url: /kong-manager/administration/workspaces/workspaces + - text: How to Create a Workspace + url: /kong-manager/administration/workspaces/create-workspace + - text: How to Update a Workspace + url: /kong-manager/administration/workspaces/update-workspace + - text: RBAC + url: /kong-manager/administration/rbac/rbac + - items: + - text: RBAC in Kong Manager + url: /kong-manager/administration/rbac/rbac + - text: How to Create a New Role + url: /kong-manager/administration/rbac/new-role + - text: How to Create an RBAC User + url: /kong-manager/administration/rbac/add-user + - text: Admins + url: /kong-manager/administration/admins/invite + - items: + - text: How to Invite an Admin + url: /kong-manager/administration/admins/invite + - text: Vitals + url: /kong-manager/vitals + + +- title: Kong Dev Portal + url: /developer-portal + items: + - text: Introduction + url: /developer-portal/ + - text: Overview + url: /developer-portal/overview + - text: Migrating from Legacy + url: /developer-portal/legacy-migration + - text: Structure and File Types + url: /developer-portal/structure-and-file-types + - text: Working with Templates + url: /developer-portal/working-with-templates + - text: Using the Editor + url: /developer-portal/using-the-editor + - text: Networking + url: /developer-portal/networking + - text: Configuration + url: /developer-portal/configuration + items: + - text: Authentication + url: /developer-portal/configuration/authentication + items: + - text: Basic Auth + url: /developer-portal/configuration/authentication/basic-auth + - text: Key Auth + url: /developer-portal/configuration/authentication/key-auth + - text: OIDC + url: /developer-portal/configuration/authentication/oidc + - text: Sessions + url: /developer-portal/configuration/authentication/sessions + - text: Adding Custom Registration Fields + url: /developer-portal/configuration/authentication/adding-registration-fields + - text: SMTP + url: /developer-portal/configuration/smtp + - text: Workspaces + url: /developer-portal/configuration/workspaces + - text: Administration + url: /developer-portal/administration/ + items: + - text: Managing Developers + url: /developer-portal/administration/managing-developers + - text: Developer Roles and Content Permissions + url: /developer-portal/administration/developer-permissions + - text: Theme Customization + url: /developer-portal/theme-customization/easy-theme-editing + items: + - text: Easy Theme Editing + url: /developer-portal/theme-customization/easy-theme-editing + - text: Helpers + url: /developer-portal/helpers/cli + items: + - text: CLI + url: /developer-portal/helpers/cli + + +- title: Kong Brain & Kong Immunity + url: /brain-immunity/install-configure + items: + - text: Installation and Configuration + url: /brain-immunity/install-configure + - text: Service Map + url: /brain-immunity/service-map + + +- title: APIs and Plugins + url: https://konghq.com/hub + items: + - text: Plugin Reference + items: + - text: Canary Release Plugin + url: /plugins/canary-release + - text: Rate Limiting Plugin + url: /plugins/rate-limiting-advanced + - text: Request Transformer Plugin + url: /plugins/request-transformer + - text: OAuth2 Introspection Plugin + url: /plugins/oauth2-introspection + - text: OpenID Connect Plugin + url: /plugins/openid-connect + - text: HTTP Proxy Caching + url: /plugins/http-proxy-caching + - text: Forward Proxy + url: /plugins/forward-proxy + - text: StatsD Advanced Plugin + url: /plugins/statsd-advanced + - text: LDAP Auth Advanced Plugin + url: /plugins/ldap-authentication-advanced + - text: Session Plugin + url: /plugins/session + - text: Route By Header + url: /plugins/route-by-header + - text: JWT Signer + url: /plugins/jwt-signer + - text: Upstream TLS + url: /plugins/upstream-tls + - text: Vault Auth + url: /plugins/vault-auth + - text: Request Validator + url: /plugins/request-validator + - text: DegraphQL + url: /plugins/degraphql + - text: GraphQL Proxy Cache Advanced + url: /plugins/graphql-proxy-cache-advanced + - text: GraphQL Rate Limiting Advanced + url: /plugins/graphql-rate-limiting-advanced + - text: Implementation + items: + - text: Multiple Authentication Methods + url: /plugins/allowing-multiple-authentication-methods + - text: OpenID Connect with Azure AD + url: /plugins/oidc-azuread + - text: OpenID Connect with Google + url: /plugins/oidc-google + - text: OpenID Connect with Okta + url: /plugins/oidc-okta + - text: OpenID Connect with Auth0 + url: /plugins/oidc-auth0 diff --git a/app/_data/kong_versions.yml b/app/_data/kong_versions.yml index e85b36ee410c..6059010511df 100644 --- a/app/_data/kong_versions.yml +++ b/app/_data/kong_versions.yml @@ -255,3 +255,15 @@ postgres: "9.5+" openresty: "1.13.6.2" lua_doc: true +- + release: "1.3-x" + version: "1.3" + edition: "enterprise" + luarocks_version: "0.34.x" + dependencies: + luajit: "2.1.0-beta2" + luarocks: "2.4.3" + cassandra: "3.x.x" + postgres: "9.5+" + openresty: "1.13.6.2" + lua_doc: true diff --git a/app/_hub/kong-inc/degraphql/index.md b/app/_hub/kong-inc/degraphql/index.md new file mode 100644 index 000000000000..f9fcd573d7d4 --- /dev/null +++ b/app/_hub/kong-inc/degraphql/index.md @@ -0,0 +1,149 @@ +--- + +name: DeGraphQL +publisher: Kong Inc. +version: 1.3.x + +desc: Transform a GraphQL upstream into a REST API +description: | + This plugin transforms a GraphQL upstream into a traditional endpoint by mapping uris into GraphQL queries. + +type: plugin +enterprise: true +categories: + - transformations + +kong_version_compatibility: + enterprise_edition: + compatible: + - 1.3.x + +params: + name: degraphql + service_id: true + config: + +--- +## Usage + +DeGraphQL needs a graphql endpoint to query. As an example, we are going to +build a REST API around https://api.github.com GraphQL service. For that reason +examples are going to include the header `Authorization: Bearer some-token`. + +Note this plugin differs from other plugins as far as configuration goes. It +needs to be activated on a service that points to a GraphQL endpoint +(sans `/graphql`). + +### 1. Create a Service and a Route in Kong: + + ```bash + $ http :8001/services name=github url=https://api.github.com + $ http -f :8001/services/github/routes paths=/api + ``` + +### 2. Configure the Plugin on the Service + +The plugin takes over the service. From this point on, the service represents +our REST api and not the graphql endpoint itself. It will return a 404 Not Found +if no DeGraphQL routes have been configured. + + ```bash + $ http :8001/services/github/plugins name=degraphql + ``` + +### 3. Configure DeGraphQL Routes on the Service + +Once the Plugin is activated on a Service, we can add our own routes to build +our service, by defining uris and associating them to GraphQL queries. + + ```bash + $ http :8001/services/github/degraphql/routes uri='/me' \ + query='query { viewer { login } }' + + $ http :8000/api/me "Authorization: Bearer some-token" + { + "data": { + "viewer": { + "login": "you" + } + } + } + ``` + +GraphQL Query Variables can be defined on uris + + ```bash + $ http :8001/services/github/degraphql/routes uri='/:owner/:name' \ + query='query ($owner:String! $name:String!){ + repository(owner:$owner, name:$name) { + name + forkCount + description + } + }' + + $ http :8000/api/kong/kong "Authorization: Bearer some-token" + { + "data": { + "repository": { + "description": "🦍 The Cloud-Native API Gateway ", + "forkCount": 2997, + "name": "kong" + } + } + } + ``` + +The same Variables can also be provided as GET arguments + + ```bash + $ http :8001/services/github/degraphql/routes uri='/repo' \ + query='query ($owner:String! $name:String!){ + repository(owner:$owner, name:$name) { + name + forkCount + description + } + }' + + $ http GET :8000/api/repo "Authorization: Bearer some-token" \ + owner=kong name=kuma + { + "data": { + "repository": { + "description": "🐻 The Universal Service Mesh", + "forkCount": 48, + "name": "kuma" + } + } + } + ``` + +### Available endpoints + +**List defined DeGraphQL Routes for a service** + +
/services/:service_name/degraphql/routes
+ +**Create a DeGraphQL Route for a Service** + +
/services/:service_name/degraphql/routes
+ +| Attributes | Description +| -------------- | ------- +|`uri` | path to map to a GraphQL query +|`query` | GraphQL query to map to uri + +**Edit a DeGraphQL Route for a Service** + +
/services/:service_name/degraphql/routes/:id
+ +| Attributes | Description +| -------------- | ------- +|`uri` | path to map to a GraphQL query +|`query` | GraphQL query to map to uri + + +**Delete a DeGraphQL Route for a Service** + +
/services/:service_name/degraphql/routes/:id
diff --git a/app/_hub/kong-inc/exit-transformer/index.md b/app/_hub/kong-inc/exit-transformer/index.md new file mode 100644 index 000000000000..485db8aae52a --- /dev/null +++ b/app/_hub/kong-inc/exit-transformer/index.md @@ -0,0 +1,181 @@ +--- +name: Exit Transformer +publisher: Kong Inc. +version: 1.3-x + +desc: Customize Kong exit responses sent downstream +description: | + Transform and customize Kong response exit messages using Lua functions. + The capabilities range from changing messages, status codes, and headers, to completely transforming + the structure of Kong responses. + +type: plugin +enterprise: true +categories: + - transformations + +kong_version_compatibility: + enterprise_edition: + compatible: + - 1.3-x + +params: + name: exit-transformer + service_id: true + route_id: true + consumer_id: false + protocols: ["http", "https"] + config: + - name: functions + required: true + value_in_examples: "[]" + description: Array of functions used to transform any Kong proxy exit response. + +--- + +## Function syntax + +The exit transformer expects a configuration function to be Lua code that returns +a function accepting three arguments: status, body, and headers. + +Any Kong exit call exposed on the proxy side gets reduced through these +functions. + +``` +Kong -> f(status, body, headers) -> ... -> exit(status, body, headers) +``` + + +### Examples + +* Identity function: does not transform the exit responses + +```lua +return function(status, body, headers) + return status, body, headers +end +``` + +* Always return a 200 status code, bundling the status within the message + +```lua +return function(status, body, headers) + -- identity + if not body or not body.message then + return status, body, headers + end + + body.status = status + + return 200, body, headers +end +``` + +* Customize particular Kong messages + +```lua +local responses = { + ["No API key found in request"] = { + message = "Please provide an API key", + status = 418, + headers = { ["x-some-header"] = "some value" }, + }, + ["Invalid authentication credentials"] = { + message = "Invalid API key", + }, + -- ... +} + +return function(status, body, headers) + if not body or not body.message then + return status, body, headers + end + + local response = responses[body.message] + + body.message = response.message or body.message + status = response.status or status + headers = response.headers or headers + + return status, body, headers +end +``` + +## Demonstration + +1. Create a Service and a Route in Kong: + + ```bash + $ http :8001/services name=example.com host=mockbin.org + $ http -f :8001/services/example.com/routes hosts=example.com + ``` + +2. Create a file named `transform.lua` with the transformation code. The + following example adds a header, appends "arr!" to any message, and adds + an `error` and `status` field on the response. + + ```lua + -- transform.lua + return function(status, body, headers) + if not body or not body.message then + return status, body, headers + end + + headers = { ["x-some-header"] = "some value" } + local new_body = { + error = true, + status = status, + message = body.message .. ", arr!", + } + + return status, body, headers + end + ``` + +3. Configure the `exit-transformer` plugin with `transform.lua` + + ```bash + $ http :8001/services/example.com/plugins \ + name=exit-transformer \ + config.functions=@transform.lua + ``` + +4. (example) Add key-auth plugin to force generation of an exit response + + ```bash + $ http :8001/services/example.com/plugins name=key-auth + ``` + +5. Attempt a request to the Service to get the custom error + + ```bash + $ http :8000 Host:example.com + HTTP/1.1 200 OK + ... + X-Some-Header: some value + + { + "error": true, + "status": 401, + "kong_message": "No API key found in request, arr!" + } + ``` + +6. Note the plugin can also be applied globally + + ```bash + $ http :8001/plugins \ + name=exit-transformer \ + config.functions=@transform.lua + + $ http :8000 Host:non-existent.com + HTTP/1.1 200 OK + ... + X-Some-Header: some value + + { + "error": true, + "status": 404, + "kong_message": "no Route matched with those values, arr!" + } + ``` diff --git a/app/_hub/kong-inc/graphql-proxy-cache-advanced/index.md b/app/_hub/kong-inc/graphql-proxy-cache-advanced/index.md new file mode 100644 index 000000000000..530d874b0b31 --- /dev/null +++ b/app/_hub/kong-inc/graphql-proxy-cache-advanced/index.md @@ -0,0 +1,187 @@ +--- + +name: GraphQL Proxy Caching Advanced +publisher: Kong Inc. +version: 1.3-x + +desc: Cache and serve commonly requested responses in Kong +description: | + This plugin provides a reverse GraphQL proxy cache implementation for Kong. It caches response entities based on + configuration. It can cache by GraphQL query or vary headers. Cache entities are stored for a configurable period of + time, after which subsequent requests to the same resource will re-fetch and re-store the resource. Cache entities + can also be forcefully purged via the Admin API prior to their expiration time. + +type: plugin +enterprise: true +categories: + - traffic-control + +kong_version_compatibility: + community_edition: + compatible: + - 1.3.x + enterprise_edition: + compatible: + - 1.3-x + +params: + name: graphql-proxy-cache-advanced + service_id: true + route_id: true + config: + - name: vary_headers + required: false + default: + value_in_examples: + description: | + Relevant headers considered for the cache key. If undefined, none of the headers are taken into consideration. + - name: cache_ttl + required: + default: 300 + value_in_examples: + description: | + TTL, in seconds, of cache entities + - name: strategy + required: + default: + value_in_examples: memory + description: | + The backing data store in which to hold cache entities. Accepted values are; `memory` at the moment. + - name: memory.dictionary_name + required: + default: kong_cache + value_in_examples: + description: | + The name of the shared dictionary in which to hold cache entities when the memory strategy is selected. Note + that this dictionary currently must be defined manually in the Kong Nginx template. + +--- +### Strategies + +GraphQL Proxy Caching Advanced Plugin is designed to support storing GraphQL proxy cache data in different backend formats. +Currently the following strategies are provided: +- `memory`: A `lua_shared_dict`. Note that the default dictionary, `kong_cache`, is also used by other plugins and +elements of Kong to store unrelated database cache entities. Using this dictionary is an easy way to bootstrap the +graphql-proxy-cache-advanced plugin, but it is not recommended for large-scale installations as significant usage will put pressure +on other facets of Kong's database caching operations. It is recommended to define a separate `lua_shared_dict` via a +custom Nginx template at this time. + +### Cache Key + +Kong keys each cache elements based on the GraphQL query that is being send +in the HTTP request body. Internally, cache keys are represented as a +hexadecimal-encoded MD5 sum of the concatenation of the constituent parts. + +``` +key = md5(UUID | headers | body) +``` + +Where `headers` contains the headers defined in vary_headers. `vary_headers` defaults to NONE. + +Kong will return the cache key associated with a given request as the +`X-Cache-Key` response header. + + +### Cache Status + +Kong identifies the status of the request's proxy cache behavior via the `X-Cache-Status` header. There are several +possible values for this header: + +* `Miss`: The request could be satisfied in cache, but an entry for the resource was not found in cache, and the request +was proxied upstream. +* `Hit`: The request was satisfied and served from cache. +* `Refresh`: The resource was found in cache, but could not satisfy the request, due to `Cache-Control` behaviors or +reaching its hard-coded `cache_ttl` threshold. +* `Bypass`: The request could not be satisfied from cache based on plugin configuration. + +### Admin API + +This plugin provides several endpoints to managed cache entities. These endpoints are assigned to the `graphql-proxy-cache-advanced` +resource. + +The following endpoints are provided on the Admin API to examine and purge cache entities: + +### Retrieve a Cache Entity + +Two separate endpoints are available: one to look up a known plugin instance, and another that searches all +graphql-proxy-cache-advanced plugins data stores for the given cache key. Both endpoints have the same return value. + +**Endpoint** + +
/graphql-proxy-cache-advanced/:plugin_id/caches/:cache_id
+ +| Attributes | Description +| -------------- | ------- +|`plugin_id` | The UUID of the graphql-proxy-cache-advanced plugin +| `cache_id` | The cache entity key as reported by the X-Cache-Key response header + +**Endpoint** + +
/graphql-proxy-cache-advanced/:cache_id
+ +| Attributes | Description +| -------------- | ------- +|`cache_id` | The cache entity key as reported by the X-Cache-Key response header + +**Response** + +If the cache entity exists + +``` +HTTP 200 OK +``` + +If the entity with the given key does not exist + +``` +HTTP 400 Not Found +``` + +### Delete Cache Entity + +Two separate endpoints are available: one to look up a known plugin instance, and another that searches all graphql-proxy-cache-advanced +plugins data stores for the given cache key. Both endpoints have the same return value. + +**Endpoint** + +
/graphql-proxy-cache-advanced/:plugin_id/caches/:cache_id
+ +| Attributes | Description +| -------------- | ------- +|`plugin_id` | The UUID of the graphql-proxy-cache-advanced plugin +|`cache_id` | The cache entity key as reported by the `X-Cache-Key` response header + +**Endpoint** + +
/graphql-proxy-cache-advanced/:cache_id
+ +| Attributes | Description +| -------------- | ------- +|`cache_id` | he cache entity key as reported by the `X-Cache-Key` response header + +**Response** + +If the cache entity exists + +``` +HTTP 204 No Content +``` + +If the entity with the given key does not exist + +``` +HTTP 400 Not Found +``` + +### Purge All Cache Entities +**Endpoint** + +
/graphql-proxy-cache-advanced/
+ +**Response** + +``` +HTTP 204 No Content +``` + +Note that this endpoint purges all cache entities across all `graphql-proxy-cache-advanced` plugins. diff --git a/app/_hub/kong-inc/kafka-log/index.md b/app/_hub/kong-inc/kafka-log/index.md new file mode 100644 index 000000000000..082eaac0626a --- /dev/null +++ b/app/_hub/kong-inc/kafka-log/index.md @@ -0,0 +1,209 @@ +--- +name: Kafka Log +publisher: Kong Inc. + +desc: Publish logs to a Kafka topic. +description: | + Publish request and response logs to a [Kafka](https://kafka.apache.org/) topic. + +type: plugin +categories: + - multi-protocol + +kong_version_compatibility: + community_edition: + compatible: + enterprise_edition: + compatible: + - 1.3-x + +params: + + name: kafka-log + config: + - name: bootstrap_servers + required: true + value_in_examples: BOOTSTRAP_SERVERS + urlencode_in_examples: true + default: + description: | + List of bootstrap brokers in a `{host: host, port: port}` format. + - name: topic + required: true + value_in_examples: TOPIC + urlencode_in_examples: true + default: + description: The Kafka topic to publish to + - name: timeout + required: false + default: "`10000`" + value_in_examples: TIMEOUT + description: Socket timeout in milliseconds. + - name: keepalive + required: false + default: "`60000`" + value_in_examples: KEEPALIVE + description: Keepalive timeout in milliseconds. + - name: producer_request_acks + required: false + default: "`1`" + value_in_examples: PRODUCER_REQUEST_ACKS + description: | + The number of acknowledgments the producer requires the leader to have received before considering a request complete. Allowed values: 0 for no acknowledgments, 1 for only the leader, and -1 for the full ISR + - name: producer_request_timeout + required: false + default: "`2000`" + value_in_examples: PRODUCER_REQUEST_TIMEOUT + description: | + Time to wait for a Produce response in milliseconds + - name: producer_request_limits_messages_per_request + required: false + default: "`200`" + value_in_examples: PRODUCER_REQUEST_LIMITS_MESSAGES_PER_REQUEST + description: Maximum number of messages to include into a single Produce request + - name: producer_request_limits_bytes_per_request + required: false + default: "`1048576`" + value_in_examples: PRODUCER_REQUEST_LIMITS_BYTES_PER_REQUEST + description: Maximum size of a Produce request in bytes + - name: producer_request_retries_max_attempts + required: false + default: "`10`" + value_in_examples: PRODUCER_REQUEST_RETRIES_MAX_ATTEMPTS + description: Maximum number of retry attempts per single Produce request + - name: producer_request_retries_backoff_timeout + required: false + default: "`100`" + description: Backoff interval between retry attempts in milliseconds. + - name: producer_async + required: false + default: "`true`" + description: | + The response status code to use (instead of the default `200`, `202`, or `204`) in the case of an [`Unhandled` Function Error](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_ResponseSyntax) + - name: producer_async_flush_timeout + required: false + default: "`1000`" + description: | + Maximum time interval in milliseconds between buffer flushes in asynchronous mode. + - name: producer_async_buffering_limits_messages_in_memory + required: false + default: "`50000`" + description: | + Maximum number of messages that can be buffered in memory in asynchronous mode. + +--- + +## Installation + +Manually download and install: +``` +$ git clone https://github.com/kong/kong-plugin-kafka-log.git /path/to/kong/plugins/kong-plugin-kafka-log +$ cd /path/to/kong/plugins/kong-plugin-kafka-log +$ luarocks make *.rockspec +``` + +In both cases, you need to change your Kong [`plugins` configuration option](https://docs.konghq.com/1.3.x/configuration/#plugins) +to include this plugin: + +``` +plugins = bundled,kong-plugin-kafka-log +``` + +Or, if you don't want to activate any of the bundled plugins: + +``` +plugins = kong-plugin-kafka-log +``` + +Then reload kong: + +``` +kong reload +``` + +## Configuration + +### Enabling globally + +```bash +$ curl -X POST http://kong:8001/plugins \ + --data "name=kafka-log" \ + --data "config.bootstrap_servers[1].host=localhost" \ + --data "config.bootstrap_servers[1].port=9092" \ + --data "config.topic=kong-log" \ + --data "config.timeout=10000" \ + --data "config.keepalive=60000" \ + --data "config.producer_request_acks=1" \ + --data "config.producer_request_timeout=2000" \ + --data "config.producer_request_limits_messages_per_request=200" \ + --data "config.producer_request_limits_bytes_per_request=1048576" \ + --data "config.producer_request_retries_max_attempts=10" \ + --data "config.producer_request_retries_backoff_timeout=100" \ + --data "config.producer_async=true" \ + --data "config.producer_async_flush_timeout=1000" \ + --data "config.producer_async_buffering_limits_messages_in_memory=50000" +``` + +## Log Format + +Similar to [HTTP Log Plugin](https://docs.konghq.com/hub/kong-inc/http-log#log-format). + +## Implementation details + +This plugin makes use of [lua-resty-kafka](https://github.com/doujiang24/lua-resty-kafka) client under the hood. + +## Known issues and limitations + +Known limitations: + +1. There is no support for TLS +2. There is no support for Authentication +3. There is no support for message compression + +## Quickstart + +The following guidelines assume that both `Kong` and `Kafka` have been installed on your local machine: + +1. Install `kong-plugin-kafka-log` as specified in the "Installation" section above. + +2. Create `kong-log` topic in your `Kafka` cluster: + + ``` + ${KAFKA_HOME}/bin/kafka-topics.sh --create \ + --zookeeper localhost:2181 \ + --replication-factor 1 \ + --partitions 10 \ + --topic kong-log + ``` + +3. Add `kong-plugin-kafka-log` plugin globally: + + ``` + curl -X POST http://localhost:8001/plugins \ + --data "name=kafka-log" \ + --data "config.bootstrap_servers[1].host=localhost \ + --data "config.bootstrap_servers[1].port=9092 \ + --data "config.topic=kong-log" + ``` + + Alternatively, create a Service with a Route, and attach the plugin to that Service. + +4. Make sample requests: + + ``` + for i in {1..50} ; do curl http://localhost:8000/request/$i ; done + ``` + +5. Verify the contents of `Kafka` topic: + + ``` + ${KAFKA_HOME}/bin/kafka-console-consumer.sh \ + --bootstrap-server localhost:9092 \ + --topic kong-log \ + --partition 0 \ + --from-beginning \ + --timeout-ms 1000 + ``` + +[badge-travis-url]: https://travis-ci.com/Kong/kong-plugin-kafka-log/branches +[badge-travis-image]: https://travis-ci.com/Kong/kong-plugin-kafka-log.svg?token=BfzyBZDa3icGPsKGmBHb&branch=master diff --git a/app/_hub/kong-inc/mtls-auth/0.36-x.md b/app/_hub/kong-inc/mtls-auth/0.36-x.md new file mode 100644 index 000000000000..0c826339f78a --- /dev/null +++ b/app/_hub/kong-inc/mtls-auth/0.36-x.md @@ -0,0 +1,136 @@ +--- + +name: Mutual TLS Authentication +publisher: Kong Inc. +version: 0.36-x + +desc: Secure routes and services with client certificate and mutual TLS authentication +description: | + Add mutual TLS authentication based on client-supplied certificate and configured trusted CA list. Automatically maps certificates to **Consumers** based on the common name field. + +enterprise: true +type: plugin +categories: + - authentication + +kong_version_compatibility: + community_edition: + compatible: + enterprise_edition: + compatible: + - 0.36-x + +params: + name: mtls-auth + service_id: true + route_id: true + config: + - name: anonymous + required: false + description: | + An optional string (consumer UUID) value to use as an "anonymous" **Consumer** if authentication fails. If the request is left empty (which it is by default), it will fail with an authentication failure of either `HTTP 495` if the client presented a certificate that is not acceptable, or `HTTP 496` if the client failed to present certificate as requested. Please note that this value must refer to the **Consumer** `id` attribute, which is internal to Kong, and **not** its `custom_id`. + - name: consumer_by + required: false + default: '`[ "username", "custom_id" ]`' + description: | + Whether to match the subject name of the client-supplied certificate against consumer's `username` and/or `custom_id` attribute. If set to `[]` (the empty array) then auto-matching is disabled. + - name: ca_certificates + required: true + value_in_examples: '`[ { "id": "fdac360e-7b19-4ade-a553-6dd22937c82f" }, { "id": "aabc360e-7b19-5aab-1231-6da229a7b82f"} ]`' + description: | + List of "CA Certificates" object to use as Certificate Authorities (CA) when validating client certificate. At least one is required but can specify as many as needed. The value of this array comprises of primary keys for the "Certificate Authority" object. + - name: cache_ttl + default: "`60`" + description: | + Cache expiry time in seconds. +--- + +### Usage + +In order to authenticate the **Consumer**, it must provide a valid certificate and +complete mutual TLS handshake with Kong. + +The plugin will validate the certificate provided against the configured CA list based on the requested **Route** or **Service**. +If the certificate is not trusted or has expired, the response will be `HTTP 401` "TLS certificate failed verification." +If **Consumer** did not present a valid certificate (this includes requests not sent to the HTTPS port), +then the response will be `HTTP 401` "No required TLS certificate was sent". That exception is if the `config.anonymous` +option was configured on the plugin, in which case the anonymous **Consumer** will be used +and the request will be allowed to proceed. + +### Adding certificate authorities + +In order to use this plugin, you must add certificate authority certificates. These are stored in a separate ca-certificates store rather than the main certificates store, as they do not require private keys. To add one, obtain a PEM-encoded copy of your CA certificate and POST it to `/ca_certificates`: + +```bash +$ curl -sX POST https://kong:8001/ca_certificates -F cert=@cert.pem +{ + "tags": null, + "created_at": 1566597621, + "cert": "-----BEGIN CERTIFICATE-----\FullPEMOmittedForBrevity==\n-----END CERTIFICATE-----\n", + "id": "322dce96-d434-4e0d-9038-311b3520f0a3" +} +``` + +The `id` value returned can now be used for mTLS plugin configurations or consumer mappings. + +### Create manual mappings between certificate and Consumer object + +Sometimes you may not wish to use automatic Consumer lookup or you have certificates +that contain a field value not associated with **Consumer** objects directly. In those +situations, you may manually assign one or more subject names to the **Consumer** object for +identifying the correct Consumer. + +**Note:** "Subject names" refers to the certificate's Subject Alternative Names (SAN) or +"Common Name" (CN). CN will only be used if the SAN extension does not exist. + +```bash +$ curl -X POST http://kong:8001/consumers/{consumer}/mtls-auth \ + -d 'subject_name=test@example.com' +HTTP/1.1 201 Created + +{ + "consumer": { "id": "876bf719-8f18-4ce5-cc9f-5b5af6c36007" }, + "created_at": 1443371053000, + "subject_name": "test@example.com" +} +``` + +* `consumer`: The `id` or `username` property of the [Consumer][consumer-object] entity to associate the credentials to. + +form parameter | default | description +--- | --- | --- +`subject_name`
*required* | | The Subject Alternative Name (SAN) or Common Name (CN) that should be mapped to `consumer` (in that order of lookup). +`ca_certificate`
*optional* | | UUID of the Certificate Authority (CA) that the certificate has to be verifiable by for the mapping to success. This is to help distinguish multiple certificates with the same subject name but are issued under different CAs. If empty, the subject name will match certificates issued by any CA under the corresponding `config.ca_certificates`. + +### Matching behaviors + +Once a client certificate has been verified as valid, the **Consumer** object will be determined in the following order: + +1. Manual mappings with `subject_name` matching the certificate's SAN or CN (in that order) and `ca_certificate = ` +2. Manual mappings with `subject_name` matching the certificate's SAN or CN (in that order) and `ca_certificate = NULL` +3. If `config.consumer_by` is not null, Consumer with `username` and/or `id` matching the certificate's SAN or CN (in that order) +4. The `config.anonymous` consumer (if set) + +**Note**: matching will stop as soon as the first successful match is found. + +When a client has been authenticated, the plugin will append headers to the request before proxying it to the upstream service so that you can identify the **Consumer** in your code: + +* `X-Consumer-ID`, the ID of the Consumer on Kong +* `X-Consumer-Custom-ID`, the `custom_id` of the Consumer (if set) +* `X-Consumer-Username`, the `username` of the Consumer (if set) +* `X-Credential-Username`, the `username` of the Credential (only if the consumer is not the 'anonymous' consumer) +* `X-Anonymous-Consumer` will be set to `true` if authentication failed and the 'anonymous' **Consumer** was set instead. + + +### Troubleshooting + +When authentication fails, the client does not have access to any details explaining the +failure. The security reason for this omission is to prevent malicious reconnaissance. +Instead, the details are recorded inside Kong's error logs under the `[mtls-auth]` +filter. + + +[configuration]: /latest/configuration +[consumer-object]: /latest/admin-api/#consumer-object +[acl-associating]: /plugins/acl/#associating-consumers +[faq-authentication]: /about/faq/#how-can-i-add-an-authentication-layer-on-a-microservice/api? diff --git a/app/_hub/kong-inc/mtls-auth/index.md b/app/_hub/kong-inc/mtls-auth/index.md index 0c826339f78a..0e4eff2c256a 100644 --- a/app/_hub/kong-inc/mtls-auth/index.md +++ b/app/_hub/kong-inc/mtls-auth/index.md @@ -2,7 +2,7 @@ name: Mutual TLS Authentication publisher: Kong Inc. -version: 0.36-x +version: 0.37-x desc: Secure routes and services with client certificate and mutual TLS authentication description: | @@ -19,6 +19,7 @@ kong_version_compatibility: enterprise_edition: compatible: - 0.36-x + - 0.37-x params: name: mtls-auth @@ -39,10 +40,15 @@ params: value_in_examples: '`[ { "id": "fdac360e-7b19-4ade-a553-6dd22937c82f" }, { "id": "aabc360e-7b19-5aab-1231-6da229a7b82f"} ]`' description: | List of "CA Certificates" object to use as Certificate Authorities (CA) when validating client certificate. At least one is required but can specify as many as needed. The value of this array comprises of primary keys for the "Certificate Authority" object. - - name: cache_ttl - default: "`60`" + - name: skip_consumer_lookup + default: "`true`" description: | - Cache expiry time in seconds. + Skip consumer look once certificate is trusted against the configured CA list. + - name: authenticated_group_by + default: "`CN`" + required: true + description: | + Certificate property which will be used as authenticated group. Once `skip_consumer_lookup` is applied, any client with a valid certificate can access the Service/API. To restrict usage to only some of the authenticated users, also add the ACL plugin (not covered here) and create whitelist or blacklist groups of users. --- ### Usage @@ -57,6 +63,21 @@ then the response will be `HTTP 401` "No required TLS certificate was sent". Tha option was configured on the plugin, in which case the anonymous **Consumer** will be used and the request will be allowed to proceed. + +### Client Certificate request +Client certificates are requested in `ssl_certifica_by_lua` phase where Kong does not have access to `route` and `workspace` information. Due to this information gap, Kong will ask for the client certificate on every handshake if the mtls-auth plugin is configured on any Route or Service. In most cases, the failure of the client to present a client certificate is not going to affect subsequent proxying if that Route or Service does not have the mtls-auth plugin applied. The exception is where the client is a desktop browser which will prompt the end user to choose the client cert to send and lead to User Experience issues rather than proxy behavior problems. +To improve this situation, Kong builds an in-memory map of SNIs from the configured Kong Routes that should present a client certificate. To limit client certificate requests during handshake while ensuring the client certificat is requested when needed, the in memory map is dependent on all the Routes in Kong having the SNIs attriubute set. When any routes do not have SNIs set, Kong must request the client certificate during every TLS handhshake. + +- On every request irrespective of Workspace when plugin enabled in global Workspace scope. +- On every request irrespective of Workspace when plugin applied at Service level + and one or more of the Routes *do not* have SNIs set. +- On every request irrespective of Workspace when plugin applied at Route level + and one or more Routes *do not* have SNIs set. +- On specific request only when plugin applied at route level and all Routes have SNIs set. + +The result is all Routes must have SNIs if you wish to restrict the handshake request for client certificates to specific requests. + + ### Adding certificate authorities In order to use this plugin, you must add certificate authority certificates. These are stored in a separate ca-certificates store rather than the main certificates store, as they do not require private keys. To add one, obtain a PEM-encoded copy of your CA certificate and POST it to `/ca_certificates`: @@ -104,7 +125,7 @@ form parameter | default | description ### Matching behaviors -Once a client certificate has been verified as valid, the **Consumer** object will be determined in the following order: +Once a client certificate has been verified as valid, the **Consumer** object will be determined in the following order unless `skip_consumer_lookup` is set to `true`: 1. Manual mappings with `subject_name` matching the certificate's SAN or CN (in that order) and `ca_certificate = ` 2. Manual mappings with `subject_name` matching the certificate's SAN or CN (in that order) and `ca_certificate = NULL` @@ -121,6 +142,14 @@ When a client has been authenticated, the plugin will append headers to the requ * `X-Credential-Username`, the `username` of the Credential (only if the consumer is not the 'anonymous' consumer) * `X-Anonymous-Consumer` will be set to `true` if authentication failed and the 'anonymous' **Consumer** was set instead. +When `skip_consumer_lookup` is set to `true`, consumer lookup will be skipped and instead of appending afromentioned headers, plugin will append following two headers + +* `X-Client-Cert-Dn`, distinguished name of the client certificate +* `X-Client-Cert-San`, SAN of the client certificate + +Once `skip_consumer_lookup` is applied, any client with a valid certificate can access the Service/API. +To restrict usage to only some of the authenticated users, also add the ACL plugin (not covered here) and create whitelist or blacklist groups of users using same +certificate property being set in `authenticated_group_by`. ### Troubleshooting diff --git a/app/_hub/kong-inc/proxy-cache-advanced/index.md b/app/_hub/kong-inc/proxy-cache-advanced/index.md new file mode 100644 index 000000000000..b9953608f71a --- /dev/null +++ b/app/_hub/kong-inc/proxy-cache-advanced/index.md @@ -0,0 +1,283 @@ +--- + +name: Proxy Caching Advanced +publisher: Kong Inc. +version: 1.3-x + +desc: Cache and serve commonly requested responses in Kong +description: | + This plugin provides a reverse proxy cache implementation for Kong. It caches response entities based on configurable response code and content type, as well as request method. It can cache per-Consumer or per-API. Cache entities are stored for a configurable period of time, after which subsequent requests to the same resource will re-fetch and re-store the resource. Cache entities can also be forcefully purged via the Admin API prior to their expiration time. + +type: plugin +enterprise: true +categories: + - traffic-control + +kong_version_compatibility: + community_edition: + compatible: + enterprise_edition: + compatible: + - 1.3-x + - 0.36-x + - 0.35-x + - 0.34-x + +params: + name: proxy-cache-advanced + api_id: true + service_id: true + route_id: true + consumer_id: true + config: + - name: response_code + required: + default: 200, 301, 404 + value_in_examples: + description: | + Upstream response status code considered cacheable + - name: request_method + required: + default: GET, HEAD + value_in_examples: + description: | + Downstream request methods considered cacheable + - name: content_type + required: + default: text/plain, application/json + value_in_examples: + description: | + Upstream response content types considered cacheable. The plugin performs an exact match against each specified value; for example, if the upstream is expected to respond with a `application/json; charset=utf-8` content-type, the plugin configuration must contain said value or a `Bypass` cache status will be returned + - name: vary_headers + required: false + default: + value_in_examples: + description: | + Relevant headers considered for the cache key. If undefined, none of the headers are taken into consideration. + - name: vary_query_params + required: false + default: + value_in_examples: + description: | + Relevant query parameters considered for the cache key. If undefined, all params are taken into consideration. + - name: cache_ttl + required: + default: 300 + value_in_examples: + description: | + TTL, in seconds, of cache entities + - name: cache_control + required: + default: false + value_in_examples: + description: | + When enabled, respect the Cache-Control behaviors defined in [RFC7234](https://tools.ietf.org/html/rfc7234#section-5.2) + - name: storage_ttl + required: false + default: + value_in_examples: + description: | + Number of seconds to keep resources in the storage backend. This value is independent of `cache_ttl` or resource TTLs defined by Cache-Control behaviors. + - name: strategy + required: + default: + value_in_examples: memory + description: | + The backing data store in which to hold cache entities. Accepted values are; `memory`, and `redis`. + - name: memory.dictionary_name + required: + default: kong_cache + value_in_examples: + description: | + The name of the shared dictionary in which to hold cache entities when the memory strategy is selected. Note that this dictionary currently must be defined manually in the Kong Nginx template. + - name: redis.host + required: semi + default: + value_in_examples: + description: | + Host to use for Redis connection when the redis strategy is defined + - name: redis.port + required: semi + default: + value_in_examples: + description: | + Port to use for Redis connection when the redis strategy is defined + - name: redis.timeout + required: semi + default: 2000 + value_in_examples: + description: | + Connection timeout to use for Redis connection when the redis strategy is defined + - name: redis.password + required: semi + default: + value_in_examples: + description: | + Password to use for Redis connection when the redis strategy is defined. If undefined, no AUTH commands are sent to Redis. + - name: redis.database + required: semi + default: 0 + value_in_examples: + description: | + Database to use for Redis connection when the redis strategy is defined + - name: redis.sentinel_master + required: semi + default: + value_in_examples: + description: | + Sentinel master to use for Redis connection when the redis strategy is defined. Defining this value implies using Redis Sentinel. + - name: redis.sentinel_role + required: semi + default: + value_in_examples: + description: | + Sentinel role to use for Redis connection when the redis strategy is defined. Defining this value implies using Redis Sentinel. + - name: redis.sentinel_addresses + required: semi + default: + value_in_examples: + description: | + Sentinel addresses to use for Redis connection when the redis strategy is defined. Defining this value implies using Redis Sentinel. + - name: redis.cluster_addresses + required: semi + default: + value_in_examples: + description: | + Cluster addresses to use for Redis connection when the `redis` strategy is defined. Defining this value implies using Redis cluster. + - name: bypass_on_err + required: false + default: false + value_in_examples: + description: | + Unhandled errors while trying to retrieve a cache entry (such as redis down) are resolved with `Bypass`, with the request going upstream. + +--- +### Strategies + +`kong-plugin-enterprise-proxy-cache` is designed to support storing proxy cache data in different backend formats. Currently the following strategies are provided: +- `memory`: A `lua_shared_dict`. Note that the default dictionary, `kong_cache`, is also used by other plugins and elements of Kong to store unrelated database cache entities. Using this dictionary is an easy way to bootstrap the proxy-cache-advanced plugin, but it is not recommended for large-scale installations as significant usage will put pressure on other facets of Kong's database caching operations. It is recommended to define a separate `lua_shared_dict` via a custom Nginx template at this time. +- `redis`: Supports Redis and Redis Sentinel deployments. + +### Cache Key + +Kong keys each cache elements based on the request method, the full client request (e.g., the request path and query parameters), and the UUID of either the API or Consumer associated with the request. This also implies that caches are distinct between APIs and/or Consumers. Currently the cache key format is hard-coded and cannot be adjusted. Internally, cache keys are represented as a hexadecimal-encoded MD5 sum of the concatenation of the constituent parts. This is calculated as follows: + +``` +key = md5(UUID | method | request) +``` + +Where `method` is defined via the OpenResty `ngx.req.get_method()` call, and `request` is defined via the Nginx `$request` variable. Kong will return the cache key associated with a given request as the `X-Cache-Key` response header. It is also possible to precalculate the cache key for a given request as noted above. + +### Cache Control + +When the `cache_control` configuration option is enabled, Kong will respect request and response Cache-Control headers as defined by [RFC7234](https://tools.ietf.org/html/rfc7234#section-5.2), with a few exceptions: + +- Cache revalidation is not yet supported, and so directives such as `proxy-revalidate` are ignored. +- Similarly, the behavior of `no-cache` is simplified to exclude the entity from being cached entirely. +- Secondary key calculation via `Vary` is not yet supported. + +### Cache Status + +Kong identifies the status of the request's proxy cache behavior via the `X-Cache-Status` header. There are several possible values for this header: + +- `Miss`: The request could be satisfied in cache, but an entry for the resource was not found in cache, and the request was proxied upstream. +- `Hit`: The request was satisfied and served from cache. +- `Refresh`: The resource was found in cache, but could not satisfy the request, due to Cache-Control behaviors or reaching its hard-coded cache_ttl threshold. +- `Bypass`: The request could not be satisfied from cache based on plugin configuration. + +### Storage TTL + +Kong can store resource entities in the storage engine longer than the prescribed `cache_ttl` or `Cache-Control` values indicate. This allows Kong to maintain a cached copy of a resource past its expiration. This allows clients capable of using `max-age` and `max-stale` headers to request stale copies of data if necessary. + +### Upstream Outages + +Due to an implementation in Kong's core request processing model, at this point the proxy-cache-advanced plugin cannot be used to serve stale cache data when an upstream is unreachable. To equip Kong to serve cache data in place of returning an error when an upstream is unreachable, we recommend defining a very large `storage_ttl` (on the order of hours or days) in order to keep stale data in the cache. In the event of an upstream outage, stale data can be considered "fresh" by increasing the `cache_ttl` plugin configuration value. By doing so, data that would have been previously considered stale is now served to the client, before Kong attempts to connect to a failed upstream service. + +### Admin API + +This plugin provides several endpoints to managed cache entities. These endpoints are assigned to the `proxy-cache-advanced` RBAC resource. + +The following endpoints are provided on the Admin API to examine and purge cache entities: + +### Retrieve a Cache Entity + +Two separate endpoints are available: one to look up a known plugin instance, and another that searches all proxy-cache-advanced plugins data stores for the given cache key. Both endpoints have the same return value. + +**Endpoint** + +
/proxy-cache-advanced/:plugin_id/caches/:cache_id
+ +| Attributes | Description +| -------------- | ------- +|`plugin_id` | The UUID of the proxy-cache-advanced plugin +| `cache_id` | The cache entity key as reported by the X-Cache-Key response header + +**Endpoint** + +
/proxy-cache-advanced/:cache_id
+ +| Attributes | Description +| -------------- | ------- +|`cache_id` | The cache entity key as reported by the X-Cache-Key response header + +**Response** + +If the cache entity exists + +``` +HTTP 200 OK +``` + +If the entity with the given key does not exist + +``` +HTTP 400 Not Found +``` + +### Delete Cache Entity + +Two separate endpoints are available: one to look up a known plugin instance, and another that searches all proxy-cache-advanced plugins data stores for the given cache key. Both endpoints have the same return value. + +**Endpoint** + +
/proxy-cache-advanced/:plugin_id/caches/:cache_id
+ +| Attributes | Description +| -------------- | ------- +|`plugin_id` | The UUID of the proxy-cache-advanced plugin +|`cache_id` | The cache entity key as reported by the `X-Cache-Key` response header + +**Endpoint** + +
/proxy-cache-advanced/:cache_id
+ +| Attributes | Description +| -------------- | ------- +|`cache_id` | he cache entity key as reported by the `X-Cache-Key` response header + +**Response** + +If the cache entity exists + +``` +HTTP 204 No Content +``` + +If the entity with the given key does not exist + +``` +HTTP 400 Not Found +``` + +### Purge All Cache Entities +**Endpoint** + +
/proxy-cache-advanced/
+ +**Response** + +``` +HTTP 204 No Content +``` + +Note that this endpoint purges all cache entities across all `proxy-cache-advanced` plugins. diff --git a/app/_hub/kong-inc/proxy-cache/index.md b/app/_hub/kong-inc/proxy-cache/index.md index 60ddbb55ddba..004d1ff4b248 100644 --- a/app/_hub/kong-inc/proxy-cache/index.md +++ b/app/_hub/kong-inc/proxy-cache/index.md @@ -1,8 +1,8 @@ --- -name: Proxy Caching +name: Proxy Cache publisher: Kong Inc. -version: 0.35-x +version: 1.3-x desc: Cache and serve commonly requested responses in Kong description: | @@ -20,6 +20,7 @@ kong_version_compatibility: - 1.2.x enterprise_edition: compatible: + - 1.3-x - 0.36-x - 0.35-x - 0.34-x @@ -84,74 +85,19 @@ params: default: value_in_examples: memory description: | - The backing data store in which to hold cache entities. Accepted values are; `memory`, and `redis`. + The backing data store in which to hold cache entities. Accepted values are; `memory`. - name: memory.dictionary_name required: default: kong_cache value_in_examples: description: | The name of the shared dictionary in which to hold cache entities when the memory strategy is selected. Note that this dictionary currently must be defined manually in the Kong Nginx template. - - name: redis.host - required: semi - default: - value_in_examples: - description: | - Host to use for Redis connection when the redis strategy is defined - - name: redis.port - required: semi - default: - value_in_examples: - description: | - Port to use for Redis connection when the redis strategy is defined - - name: redis.timeout - required: semi - default: 2000 - value_in_examples: - description: | - Connection timeout to use for Redis connection when the redis strategy is defined - - name: redis.password - required: semi - default: - value_in_examples: - description: | - Password to use for Redis connection when the redis strategy is defined. If undefined, no AUTH commands are sent to Redis. - - name: redis.database - required: semi - default: 0 - value_in_examples: - description: | - Database to use for Redis connection when the redis strategy is defined - - name: redis.sentinel_master - required: semi - default: - value_in_examples: - description: | - Sentinel master to use for Redis connection when the redis strategy is defined. Defining this value implies using Redis Sentinel. - - name: redis.sentinel_role - required: semi - default: - value_in_examples: - description: | - Sentinel role to use for Redis connection when the redis strategy is defined. Defining this value implies using Redis Sentinel. - - name: redis.sentinel_addresses - required: semi - default: - value_in_examples: - description: | - Sentinel addresses to use for Redis connection when the redis strategy is defined. Defining this value implies using Redis Sentinel. - - name: redis.cluster_addresses - required: semi - default: - value_in_examples: - description: | - Cluster addresses to use for Redis connection when the `redis` strategy is defined. Defining this value implies using Redis cluster. --- ### Strategies -`kong-plugin-enterprise-proxy-cache` is designed to support storing proxy cache data in different backend formats. Currently the following strategies are provided: +`kong-plugin-proxy-cache` is designed to support storing proxy cache data in different backend formats. Currently the following strategies are provided: - `memory`: A `lua_shared_dict`. Note that the default dictionary, `kong_cache`, is also used by other plugins and elements of Kong to store unrelated database cache entities. Using this dictionary is an easy way to bootstrap the proxy-cache plugin, but it is not recommended for large-scale installations as significant usage will put pressure on other facets of Kong's database caching operations. It is recommended to define a separate `lua_shared_dict` via a custom Nginx template at this time. -- `redis`: Supports Redis and Redis Sentinel deployments. ### Cache Key diff --git a/app/_hub/kong-inc/request-size-limiting/index.md b/app/_hub/kong-inc/request-size-limiting/index.md index e01a4656ce08..e5c941447366 100644 --- a/app/_hub/kong-inc/request-size-limiting/index.md +++ b/app/_hub/kong-inc/request-size-limiting/index.md @@ -45,6 +45,7 @@ kong_version_compatibility: - 0.3.x enterprise_edition: compatible: + - 1.3-x - 0.36-x - 0.35-x - 0.34-x @@ -65,5 +66,10 @@ params: default: "`128`" value_in_examples: 128 description: Allowed request payload size in megabytes, default is `128` (128000000 Bytes) + - name: size_unit + required: true + default: "`megabytes`" + description: Size unit can be set either in `bytes`, `kilobytes`, or `megabytes`. + Note- this configuration is only supported in Kong Enterprise 1.3 and above, and may eventually extend to Kong Gateway --- diff --git a/app/_hub/kong-inc/request-transformer-advanced/0.36-x.md b/app/_hub/kong-inc/request-transformer-advanced/0.36-x.md new file mode 100644 index 000000000000..416f3472296f --- /dev/null +++ b/app/_hub/kong-inc/request-transformer-advanced/0.36-x.md @@ -0,0 +1,296 @@ +--- + +name: Request Transformer Advanced +publisher: Kong Inc. +version: 0.36-x + +desc: Use powerful regular expressions, variables and templates to transform API requests +description: | + The Request Transformer plugin for Kong Enterprise builds on the Kong version of this plugin with enhanced capabilities to match portions of incoming requests using regular expressions, save those matched strings into variables, and substitute those strings into transformed requests via flexible templates. + +enterprise: true +type: plugin +categories: + - transformations + +kong_version_compatibility: + community_edition: + compatible: + enterprise_edition: + compatible: + - 0.36-x + - 0.35-x + - 0.34-x + +params: + name: request-transformer-advanced + api_id: true + service_id: true + route_id: true + consumer_id: true + config: + - name: http_method + required: false + default: + value_in_examples: + description: | + Changes the HTTP method for the upstream request + - name: remove.headers + required: false + default: + value_in_examples: + description: | + List of header names. Unset the headers with the given name. + - name: remove.querystring + required: false + default: + value_in_examples: + description: | + List of querystring names. Remove the querystring if it is present. + - name: remove.body + required: false + default: + value_in_examples: + description: | + List of parameter names. Remove the parameter if and only if content-type is one the following [`application/json`, `multipart/form-data`, `application/x-www-form-urlencoded`] and parameter is present. + - name: replace.headers + required: false + default: + value_in_examples: + description: | + List of headername:value pairs. If and only if the header is already set, replace its old value with the new one. Ignored if the header is not already set. + - name: replace.querystring + required: false + default: + value_in_examples: + description: | + List of queryname:value pairs. If and only if the querystring name is already set, replace its old value with the new one. Ignored if the header is not already set. + - name: replace.uri + required: false + default: + value_in_examples: + description: | + Updates the upstream request URI with given value. This value can only be used to update the path part of the URI, not the scheme, nor the hostname. + - name: replace.body + required: false + default: + value_in_examples: + description: | + List of paramname:value pairs. If and only if content-type is one the following [`application/json`, `multipart/form-data`, `application/x-www-form-urlencoded`] and the parameter is already present, replace its old value with the new one. Ignored if the parameter is not already present. + - name: rename.headers + required: false + default: + value_in_examples: + description: | + List of headername:value pairs. If and only if the header is already set, rename the header. The value is unchanged. Ignored if the header is not already set. + - name: rename.querystring + required: false + default: + value_in_examples: + description: | + List of queryname:value pairs. If and only if the field name is already set, rename the field name. The value is unchanged. Ignored if the field name is not already set. + - name: rename.body + required: false + default: + value_in_examples: + description: | + List of parameter name:value pairs. Rename the parameter name if and only if content-type is one the following [`application/json`, `multipart/form-data`, `application/x-www-form-urlencoded`] and parameter is present. + - name: add.headers + required: false + default: + value_in_examples: + description: | + List of headername:value pairs. If and only if the header is not already set, set a new header with the given value. Ignored if the header is already set. + - name: add.querystring + required: false + default: + value_in_examples: + description: | + List of queryname:value pairs. If and only if the querystring name is not already set, set a new querystring with the given value. Ignored if the querystring name is already set. + - name: add.body + required: false + default: + value_in_examples: + description: | + List of paramname:value pairs. If and only if content-type is one the following [`application/json, multipart/form-data`, `application/x-www-form-urlencoded`] and the parameter is not present, add a new parameter with the given value to form-encoded body. Ignored if the parameter is already present. + - name: append.headers + required: false + default: + value_in_examples: + description: | + List of headername:value pairs. If the header is not set, set it with the given value. If it is already set, a new header with the same name and the new value will be set. + - name: append.querystring + required: false + default: + value_in_examples: + description: | + List of queryname:value pairs. If the querystring is not set, set it with the given value. If it is already set, a new querystring with the same name and the new value will be set. + - name: append.body + required: false + default: + value_in_examples: + description: | + List of paramname:value pairs. If the content-type is one the following [`application/json`, `application/x-www-form-urlencoded`], add a new parameter with the given value if the parameter is not present, otherwise if it is already present, the two values (old and new) will be aggregated in an array. + extra: | + Note: if the value contains a `,` then the comma separated format cannot be used. The array notation must be used instead. + +--- + +### Template as Value + +User can use any of the the current request headers, query params, and captured URI named groups as template to populate above supported config fields. + +| Request Param | Template +| --------- | ----------- +| header | $(headers. or $(headers['']) or 'optional_default') +| querystring | $(query_params. or $(query_params['query-param-name']) or 'optional_default') +| captured URIs | $(uri_captures. or $(uri_captures['group-name']) or 'optional_default') + +To escape a template, wrap it inside quotes and pass inside another template.
+Ex. $('$(some_needs_to_escaped)') + +Note: Plugin creates a non mutable table of request headers, querystrings, and captured URIs before transformation. So any update or removal of params used in template does not affect the rendered value of template. + +#### Examples Using Template as Value + +Add an API `test` with `uris` configured with a named capture group `user_id` + +```bash +$ curl -X POST http://localhost:8001/apis \ + --data 'name=test' \ + --data 'upstream_url=http://mockbin.com' \ + --data-urlencode 'uris=/requests/user/(?\w+)' \ + --data "strip_uri=false" +``` + +Enable the ‘request-transformer-advanced’ plugin to add a new header `x-consumer-id` +and its value is being set with the value sent with header `x-user-id` or +with the default value alice is `header` is missing. + +```bash +$ curl -X POST http://localhost:8001/apis/test/plugins \ + --data "name=request-transformer-advanced" \ + --data-urlencode "config.add.headers=x-consumer-id:\$(headers['x-user-id'] or 'alice')" \ + --data "config.remove.headers=x-user-id" +``` + +Now send a request without setting header `x-user-id` + +```bash +$ curl -i -X GET localhost:8000/requests/user/foo +``` + +Plugin will add a new header `x-consumer-id` with value alice before proxying +request upstream. Now try sending request with header `x-user-id` set + +```bash +$ curl -i -X GET localhost:8000/requests/user/foo \ + -H "X-User-Id:bob" +``` + +This time plugin will add a new header `x-consumer-id` with value sent along +with header `x-user-id`, i.e.`bob` + +### Order of Execution + +Plugin performs the response transformation in following order + +remove –> replace –> add –> append + +### Configuration Examples + +Add multiple headers by passing each header:value pair separately: + +```bash +$ curl -X POST http://localhost:8001/apis/mockbin/plugins \ + --data "name=request-transformer-advanced" \ + --data "config.add.headers[1]=h1:v1" \ + --data "config.add.headers[2]=h2:v1" +``` + +| Incoming Request Headers | Upstream Proxied Headers +| --------- | ----------- +| h1: v1 | h1: v1, h2: v1 + +Add multiple headers by passing comma separated header:value pair: + +```bash +$ curl -X POST http://localhost:8001/apis/mockbin/plugins \ + --data "name=request-transformer-advanced" \ + --data "config.add.headers=h1:v1,h2:v2" +``` + +| Incoming Request Headers | Upstream Proxied Headers +| --------- | ----------- +| h1: v1 | h1: v1, h2: v1 + +Add multiple headers passing config as JSON body: + +```bash +$ curl -X POST http://localhost:8001/apis/mockbin/plugins \ + --header 'content-type: application/json' \ + --data '{"name": "request-transformer-advanced", "config": {"add": {"headers": ["h1:v2", "h2:v1"]}}}' +``` + +| Incoming Request Headers | Upstream Proxied Headers +| --------- | ----------- +| h1: v1 | h1: v1, h2: v1 + +Add a querystring and a header: + +```bash +$ curl -X POST http://localhost:8001/apis/mockbin/plugins \ + --data "name=request-transformer-advanced" \ + --data "config.add.querystring=q1:v2,q2=v1" \ + --data "config.add.headers=h1:v1" + +``` + +| Incoming Request Headers | Upstream Proxied Headers +| --------- | ----------- +| h1: v1 | h1: v1, h2: v1 +| h3: v1 | h1: v1, h2: v1, h3: v1 + +| Incoming Request Querystring | Upstream Proxied Querystring +| --------- | ----------- +| ?q1=v1 | ?q1=v1&q2=v1 +| | ?q1=v2&q2=v1 + +Append multiple headers and remove a body parameter: + +```bash +$ curl -X POST http://localhost:8001/apis/mockbin/plugins \ + --data "name=request-transformer-advanced" \ + --data "config.add.headers=h1:v2,h2:v1" \ + --data "config.remove.body=p1" \ + +``` + +| Incoming Request Headers | Upstream Proxied Headers +| --------- | ----------- +| h1: v1 | h1: v1, h1: v2, h2: v1 + +| Incoming URL Encoded Body | Upstream Proxied URL Encoded Body +| --------- | ----------- +| p1=v1&p2=v1 | p2=v1 +| p2=v1 | p2=v1 + +Add multiple headers and querystring parameters if not already set: + +```bash +$ curl -X POST http://localhost:8001/apis/mockbin/plugins \ + --data "name=request-transformer-advanced" \ + --data "config.add.headers=h1:v1,h2:v1" \ + --data "config.add.querystring=q1:v2,q2:v1" \ + +``` + +| Incoming Request Headers | Upstream Proxied Headers +| --------- | ----------- +| h1: v1 | h1: v1, h2: v1 +| h3: v1 | h1: v1, h2: v1, h3: v1 + +| Incoming Request Querystring | Upstream Proxied Querystring +| --------- | ----------- +| ?q1=v1 | ?q1=v1&q2=v1 +| | ?q1=v2&q2=v1 diff --git a/app/_hub/kong-inc/request-transformer-advanced/index.md b/app/_hub/kong-inc/request-transformer-advanced/index.md index 416f3472296f..cc1501319a37 100644 --- a/app/_hub/kong-inc/request-transformer-advanced/index.md +++ b/app/_hub/kong-inc/request-transformer-advanced/index.md @@ -2,7 +2,7 @@ name: Request Transformer Advanced publisher: Kong Inc. -version: 0.36-x +version: 1.3-x desc: Use powerful regular expressions, variables and templates to transform API requests description: | @@ -18,6 +18,7 @@ kong_version_compatibility: compatible: enterprise_edition: compatible: + - 1.3-x - 0.36-x - 0.35-x - 0.34-x @@ -131,6 +132,12 @@ params: value_in_examples: description: | List of paramname:value pairs. If the content-type is one the following [`application/json`, `application/x-www-form-urlencoded`], add a new parameter with the given value if the parameter is not present, otherwise if it is already present, the two values (old and new) will be aggregated in an array. + - name: whitelist.body + required: false + default: + value_in_examples: + description: | + Set of parameter name. If and only if content-type is one the following [`application/json`, `multipart/form-data`, `application/x-www-form-urlencoded`], allow only whitelisted parameters in the body. extra: | Note: if the value contains a `,` then the comma separated format cannot be used. The array notation must be used instead. diff --git a/app/_hub/kong-inc/response-transformer-advanced/0.36-x.md b/app/_hub/kong-inc/response-transformer-advanced/0.36-x.md new file mode 100755 index 000000000000..ae2c0b605492 --- /dev/null +++ b/app/_hub/kong-inc/response-transformer-advanced/0.36-x.md @@ -0,0 +1,231 @@ +--- +name: Response Transformer Advanced +publisher: Kong Inc. +version: 0.36-x + +desc: Modify the upstream response before returning it to the client +description: | + Transform the response sent by the upstream server on the fly on Kong, before returning the response to the client. + +
+ Note on transforming bodies: Be aware of the performance of transformations on the response body. In order to parse and modify a JSON body, the plugin needs to retain it in memory, which might cause pressure on the worker's Lua VM when dealing with large bodies (several MBs). Because of Nginx's internals, the `Content-Length` header will not be set when transforming a response body. +
+ +type: plugin +categories: + - transformations + +enterprise: true +kong_version_compatibility: + enterprise_edition: + compatible: + - 0.36-x + - 0.35-x + +params: + name: response-transformer-advanced + service_id: true + route_id: true + consumer_id: true + config: + - name: remove.headers + required: false + value_in_examples: "x-toremove, x-another-one" + description: List of header names. Unset the header(s) with the given name. + - name: remove.json + required: false + value_in_examples: "json-key-toremove, another-json-key" + description: List of property names. Remove the property from the JSON body if it is present. + - name: remove.if_status + required: false + description: List of response status codes or status code ranges to which the transformation will apply. Empty means all response codes. + - name: replace.headers + required: false + description: List of headername:value pairs. If and only if the header is already set, replace its old value with the new one. Ignored if the header is not already set. + - name: replace.json + required: false + description: List of property:value pairs. If and only if the parameter is already present, replace its old value with the new one. Ignored if the parameter is not already present. + - name: replace.body + required: false + description: String with which to replace the entire response body + - name: replace.if_status + required: false + description: List of response status codes or status code ranges to which the transformation will apply. Empty means all response codes + - name: add.headers + required: false + value_in_examples: "x-new-header:value,x-another-header:something" + description: List of headername:value pairs. If and only if the header is not already set, set a new header with the given value. Ignored if the header is already set. + - name: add.json + required: false + value_in_examples: "new-json-key:some_value, another-json-key:some_value" + description: List of property:value pairs. If and only if the property is not present, add a new property with the given value to the JSON body. Ignored if the property is already present. + - name: add.if_status + required: false + description: List of response status codes or status code ranges to which the transformation will apply. Empty means all response codes + - name: append.headers + required: false + value_in_examples: "x-existing-header:some_value, x-another-header:some_value" + description: List of headername:value pairs. If the header is not set, set it with the given value. If it is already set, a new header with the same name and the new value will be set. + - name: append.json + required: false + description: List of property:value pairs. If the property is not present in the JSON body, add it with the given value. If it is already present, the two values (old and new) will be aggregated in an array. + - name: append.if_status + required: false + description: List of response status codes or status code ranges to which the transformation will apply. Empty means all response codes + +--- + +Note: if the value contains a `,` then the comma separated format for lists cannot be used. The array notation must be used instead. + +## Order of execution + +Plugin performs the response transformation in following order + +remove --> replace --> add --> append + +## Examples + +In these examples we have the plugin enabled on a Route. This would work +similar for Services. + +- Add multiple headers by passing each header:value pair separately: + +```bash +$ curl -X POST http://localhost:8001/routes/{route id}/plugins \ + --data "name=response-transformer-advanced" \ + --data "config.add.headers[1]=h1:v1" \ + --data "config.add.headers[2]=h2:v1" +``` + + + + + + + + + + +
upstream response headersproxied response headers
h1: v1 +
  • h1: v1
  • h2: v1
+
+ +- Add multiple headers by passing comma separated header:value pair: + +```bash +$ curl -X POST http://localhost:8001/routes/{route id}/plugins \ + --data "name=response-transformer-advanced" \ + --data "config.add.headers=h1:v1,h2:v2" +``` + + + + + + + + + + +
upstream response headersproxied response headers
h1: v1 +
  • h1: v1
  • h2: v1
+
+ + +- Add multiple headers passing config as JSON body: + +```bash +$ curl -X POST http://localhost:8001/routes/{route id}/plugins \ + --header 'content-type: application/json' \ + --data '{"name": "response-transformer-advanced", "config": {"add": {"headers": ["h1:v2", "h2:v1"]}}}' +``` + + + + + + + + + + +
upstream response headersproxied response headers
h1: v1 +
  • h1: v1
  • h2: v1
+
+ +- Add a body property and a header: + +```bash +$ curl -X POST http://localhost:8001/routes/{route id}/plugins \ + --data "name=response-transformer-advanced" \ + --data "config.add.json=p1:v1,p2=v2" \ + --data "config.add.headers=h1:v1" +``` + + + + + + + + + + + + + + +
upstream response headersproxied response headers
h1: v2 +
  • h1: v2
  • h2: v1
+
h3: v1 +
  • h1: v1
  • h2: v1
  • h3: v1
+
+ + +| upstream response JSON body | proxied response body | +| --- | --- | +| {} | {"p1" : "v1", "p2": "v2"} | +| {"p1" : "v2"} | {"p1" : "v2", "p2": "v2"} | + +- Append multiple headers and remove a body property: + +```bash +$ curl -X POST http://localhost:8001/routes/{route id}/plugins \ + --header 'content-type: application/json' \ + --data '{"name": "response-transformer-advanced", "config": {"append": {"headers": ["h1:v2", "h2:v1"]}, "remove": {"json": ["p1"]}}}' +``` + + + + + + + + + + +
upstream response headersproxied response headers
h1: v1 +
  • h1: v1
  • h1: v2
  • h2: v1
+
+ +|upstream response JSON body | proxied response body | +|--- | --- | +|{"p2": "v2"} | {"p2": "v2"} | +|{"p1" : "v1", "p2" : "v1"} | {"p2": "v2"} | + +- Replace entire response body if response code is 500 + +``` +$ curl -X POST http://localhost:8001/routes/{route id}/plugins \ + --data "name=response-transformer-advanced" \ + --data "config.replace.body='{\"error\": \"internal server error\"}'" \ + --data "config.replace.if_status=500" +``` + +**Note**: the plugin doesn't validate the value in `config.replace.body` against +the content type as defined in the `Content-Type` response header. + +[api-object]: /latest/admin-api/#api-object +[consumer-object]: /latest/admin-api/#consumer-object +[configuration]: /latest/configuration +[faq-authentication]: /about/faq/#how-can-i-add-an-authentication-layer-on-a-microservice/api? diff --git a/app/_hub/kong-inc/response-transformer-advanced/index.md b/app/_hub/kong-inc/response-transformer-advanced/index.md index ae2c0b605492..9844829294a1 100755 --- a/app/_hub/kong-inc/response-transformer-advanced/index.md +++ b/app/_hub/kong-inc/response-transformer-advanced/index.md @@ -19,6 +19,7 @@ enterprise: true kong_version_compatibility: enterprise_edition: compatible: + - 1.3-x - 0.36-x - 0.35-x @@ -72,6 +73,18 @@ params: - name: append.if_status required: false description: List of response status codes or status code ranges to which the transformation will apply. Empty means all response codes + - name: whitelist.json + required: false + default: + value_in_examples: + description: | + Set of parameter names. Only allows whitelisted parameters in the JSON response body. + - name: transform.functions + required: false + description: Set of Lua functions to perform arbitrary transforms in a response JSON body. + - name: transform.if_status + required: false + description: List of response status codes or ranges to which the arbitrary transformation applies. Leaving empty implies that the transformations apply to all response codes. --- @@ -225,6 +238,39 @@ $ curl -X POST http://localhost:8001/routes/{route id}/plugins \ **Note**: the plugin doesn't validate the value in `config.replace.body` against the content type as defined in the `Content-Type` response header. +- Perform arbitrary transforms to a JSON body + +Use the power of embedding Lua to perform arbitrary transformations on JSON bodies. Transformation functions +receive an argument with the JSON body, and must return the transformed response body: + +```lua +-- transform.lua +-- this function transforms +-- { "foo": "something", "something": "else" } +-- into +-- { "foobar": "hello world", "something": "else" } +return function (data) + if type(data) ~= "table" then + return data + end + + -- remove foo key + data["foo"] = nil + + -- add a new key + data["foobar"] = "hello world" + + return data +end +``` + +```bash +$ curl -X POST http://localhost:8001/routes/{route id}/plugins \ + -F "name=response-transformer-advanced" \ + -F "config.transform.functions=@transform.lua" + -F "config.transform.if_status=200" +``` + [api-object]: /latest/admin-api/#api-object [consumer-object]: /latest/admin-api/#consumer-object [configuration]: /latest/configuration diff --git a/app/_hub/kong-inc/serverless-functions/index.md b/app/_hub/kong-inc/serverless-functions/index.md index 65efe77db31e..48909cbe8242 100644 --- a/app/_hub/kong-inc/serverless-functions/index.md +++ b/app/_hub/kong-inc/serverless-functions/index.md @@ -86,6 +86,7 @@ different priority in the plugin chain. 1. Create a file named `custom-auth.lua` with the following content: ```lua + return function() -- Get list of request headers local custom_auth = kong.request.get_header("x-custom-auth") @@ -97,6 +98,7 @@ different priority in the plugin chain. -- Remove custom authentication header from request kong.service.request.clear_header('x-custom-auth') + end ``` 4. Ensure the file contents: @@ -153,17 +155,19 @@ different priority in the plugin chain. - name: pre-function config: functions: | - -- Get list of request headers - local custom_auth = kong.request.get_header("x-custom-auth") - - -- Terminate request early if our custom authentication header - -- does not exist - if not custom_auth then - return kong.response.exit(401, "Invalid Credentials") + return function() + -- Get list of request headers + local custom_auth = kong.request.get_header("x-custom-auth") + + -- Terminate request early if our custom authentication header + -- does not exist + if not custom_auth then + return kong.response.exit(401, "Invalid Credentials") + end + + -- Remove custom authentication header from request + kong.service.request.clear_header('x-custom-auth') end - - -- Remove custom authentication header from request - kong.service.request.clear_header('x-custom-auth') ``` 2. Test that our Lua code will terminate the request when no header is passed: diff --git a/app/_hub/kong-inc/session/1.2-x.md b/app/_hub/kong-inc/session/1.2-x.md new file mode 100644 index 000000000000..6097e34b959a --- /dev/null +++ b/app/_hub/kong-inc/session/1.2-x.md @@ -0,0 +1,379 @@ +--- +name: Session +publisher: Kong Inc. +version: 2.0.0-x +redirect_from: + - /hub/kong-in/sessions + - /hub/kong-inc/sessions + +desc: Support sessions for Kong Authentication Plugins. +description: | + The Kong Session Plugin can be used to manage browser sessions for APIs proxied + through the Kong API Gateway. It provides configuration and management for + session data storage, encryption, renewal, expiry, and sending browser cookies. + It is built using + lua-resty-session + +type: plugin +categories: + - authentication + +source_url: https://github.com/Kong/kong-plugin-session + +kong_version_compatibility: + community_edition: + compatible: + - 1.2.x + +params: + name: session + service_id: true + route_id: true + consumer_id: false + config: + - name: secret + required: false + default: random number generated from `kong.utils.random_string` + value_in_examples: opensesame + description: The secret that is used in keyed HMAC generation.​ + - name: cookie_name + required: false + default: '`session`' + description: The name of the cookie + - name: cookie_lifetime + required: false + default: 3600 + description: The duration (in seconds) that the session will remain open + - name: cookie_renew + required: false + default: 600 + description: The duration (in seconds) of a session remaining at which point the Plugin renews the session + - name: cookie_path + required: false + default: '/' + description: The resource in the host where the cookie is available + - name: cookie_domain + required: false + default: Set using Nginx variable host, but may be overridden + description: The domain with which the cookie is intended to be exchanged + - name: cookie_samesite + required: false + default: 'Strict' + description: 'Determines whether and how a cookie may be sent with cross-site requests. "Strict": the browser will send cookies only if the request originated from the website that set the cookie. "Lax": same-site cookies are withheld on cross-domain subrequests, but will be sent when a user navigates to the URL from an external site, for example, by following a link. "off": disables the same-site attribute so that a cookie may be sent with cross-site requests. https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#SameSite_cookies' + - name: cookie_httponly + required: false + default: true + description: Applies the `HttpOnly` tag so that the cookie is sent only to a server https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Secure_and_HttpOnly_cookies + - name: cookie_secure + required: false + default: true + description: Applies the Secure directive so that the cookie may be sent to the server only with an encrypted request over the HTTPS protocol https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Secure_and_HttpOnly_cookies + - name: cookie_discard + required: false + default: 10 + description: The duration (in seconds) after which an old session’s TTL is updated that an old cookie is discarded. + - name: storage + required: false + default: 'cookie' + description: "Determines where the session data is stored. `kong`: stores encrypted session data into Kong's current database strategy (e.g. Postgres, Cassandra); the cookie will not contain any session data. `cookie`: stores encrypted session data within the cookie itself." + - name: logout_methods + required: false + default: '[`"POST"`, `"DELETE"`]' + description: 'The methods that may be used to end sessions: POST, DELETE, GET.' + - name: logout_query_arg + required: false + default: session_logout + description: The query argument passed to logout requests. + - name: logout_post_arg + required: false + default: session_logout + description: The post argument passed to logout requests. Do not change this property. +--- + +## Usage + +The Kong Session **Plugin** can be configured globally or per entity (e.g., Service, Route) +and is always used in conjunction with another Kong Authentication **[Plugin]**. This +**Plugin** is intended to work similarly to the [multiple authentication] setup. + +Once the Kong Session **Plugin** is enabled in conjunction with an Authentication **Plugin**, +it will run prior to credential verification. If no session is found, then the +authentication **Plugin** will run and credentials will be checked as normal. If the +credential verification is successful, then the session **Plugin** will create a new +session for usage with subsequent requests. + +When a new request comes in, and a session is present, then the Kong Session +**Plugin** will attach the `ngx.ctx` variables to let the authentication +**Plugin** know that authentication has already occured via session validation. +Since this configuration is a logical OR scenario, it is desired that anonymous +access be forbidden, then the [Request Termination] **Plugin** should be +configured on an anonymous consumer. Failure to do so will allow unauthorized +requests. For more information please see section on [multiple authentication]. + +### Setup With a Database + +For usage with [Key Auth] **Plugin** + +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[]=/sessions-test' + ``` + + The url `http://localhost:8000/sessions-test` will now echo whatever is being + requested. + +1. Configure the key-auth **Plugin** for the Service + + Issue the following cURL request to add the key-auth **Plugin** to the 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` - it will be needed later. + +1. 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/sessions-test + ``` + + Since the required header or parameter `apikey` was not specified, and + anonymous access was not yet enabled, the response should be `401 Unauthorized`: + +1. Create a Consumer and an anonymous Consumer + + Every request proxied and authenticated by Kong must be associated with a + Consumer. You'll now create a Consumer named `anonymous_users` by issuing + the following request: + + ```bash + $ curl -i -X POST \ + --url http://localhost:8001/consumers/ \ + --data "username=anonymous_users" + ``` + + Be sure to note the Consumer `id` - you'll need it in a later step. + + Now create a consumer that will authenticate via sessions + + ```bash + $ curl -i -X POST \ + --url http://localhost:8001/consumers/ \ + --data "username=fiona" + ``` + +1. Provision key-auth credentials for your Consumer + + ```bash + $ curl -i -X POST \ + --url http://localhost:8001/consumers/fiona/key-auth/ \ + --data 'key=open_sesame' + ``` + +1. Enable anonymous access + + You'll now re-configure the key-auth **Plugin** to permit anonymous access by + issuing the following request (**replace the uuids below by the `id` value + from previous steps**): + + ```bash + $ curl -i -X PATCH \ + --url http://localhost:8001/plugins/ \ + --data "config.anonymous=" + ``` + +1. Add the Kong Session **Plugin** to the service + + ```bash + $ curl -X POST http://localhost:8001/services/example-service/plugins \ + --data "name=session" \ + --data "config.storage=kong" \ + --data "config.cookie_secure=false" + ``` + + > Note: cookie_secure is true by default, and should always be true, but is set to + > false for the sake of this demo in order to avoid using HTTPS. + +1. Add the Request Termination **Plugin** + + To disable anonymous access to only allow users access via sessions or via + authentication credentials, enable the Request Termination **Plugin**. + + ```bash + $ curl -X POST http://localhost:8001/services/example-service/plugins \ + --data "name=request-termination" \ + --data "config.status_code=403" \ + --data "config.message=So long and thanks for all the fish!" \ + --data "consumer.id=" + ``` + +### Setup Without a Database + +Add all these to the declarative config file: + +```yaml +services: + - name: example-service + url: http://mockbin.org/request + +routes: + - service: example-service + paths: ['/sessions-test'] + +consumers: + - username: anonymous_users + # manually set to fixed uuid in order to use it in key-auth plugin + id: 81823632-10c0-4098-a4f7-31062520c1e6 + - username: fiona + +keyauth_credentials: + - consumer: fiona + key: open_sesame + +plugins: + - name: key-auth + service: example-service + config: + # using the anonymous consumer fixed uuid (can't use the username) + anonymous: 81823632-10c0-4098-a4f7-31062520c1e6 + # cookie_secure is true by default, and should always be true, + # but is set to false for the sake of this demo in order to avoid using HTTPS. + cookie_secure: false + - name: session + config: + storage: kong + cookie_secure: false + - name: request-termination + service: example-service + consumer: anonymous_users + config: + status_code: 403 + message: 'So long and thanks for all the fish!' +``` + +### Verification + +1. Check that Anonymous requests are disabled + + ```bash + $ curl -i -X GET \ + --url http://localhost:8000/sessions-test + ``` + + Should return `403`. + +2. Verify that a user can authenticate via sessions + + ```bash + $ curl -i -X GET \ + --url http://localhost:8000/sessions-test?apikey=open_sesame + ``` + + The response should now have the `Set-Cookie` header. Make sure that this + cookie works. + + If cookie looks like this: + + ``` + Set-Cookie: session=emjbJ3MdyDsoDUkqmemFqw..|1544654411|4QMKAE3I-jFSgmvjWApDRmZHMB8.; Path=/; SameSite=Strict; HttpOnly + ``` + + Use it like this: + + ```bash + $ curl -i -X GET \ + --url http://localhost:8000/sessions-test \ + -H "cookie:session=emjbJ3MdyDsoDUkqmemFqw..|1544654411|4QMKAE3I-jFSgmvjWApDRmZHMB8." + ``` + + This request should succeed, and `Set-Cookie` response header will not appear + until renewal period. + +3. You can also now verify cookie is attached to browser session: Navigate to + http://localhost:8000/sessions-test which should return `403` + and see the message "So long and thanks for all the fish!" +4. In same browser session, navigate to http://localhost:8000/sessions-test?apikey=open_sesame + which should return `200`, authenticated via key-auth key query param. +5. In same browser session, navigate to http://localhost:8000/sessions-test, + which will now use the session cookie that was granted by the Kong Session + **Plugin**. + +### Defaults + +By default, the Kong Session **Plugin** favors security using a `Secure`, `HTTPOnly`, +`Samesite=Strict` cookie. `cookie_domain` is automatically set using Nginx +variable host, but can be overridden. + +### Session Data Storage + +The session data can be stored in the cookie itself (encrypted) `storage=cookie`, +or inside [Kong](#-kong-storage-adapter). The session data stores two context +variables: + +``` +ngx.ctx.authenticated_consumer.id +ngx.ctx.authenticated_credential.id +``` + +## Kong Storage Adapter + +the Kong Session **Plugin** extends the functionality of [lua-resty-session] with its own +session data storage adapter when `storage=kong`. This will store encrypted +session data into the current database strategy (e.g. postgres, cassandra etc.) +and the cookie will not contain any session data. Data stored in the database is +encrypted and the cookie will contain only the session id, expiration time and +HMAC signature. Sessions will use the built-in Kong DAO `ttl` mechanism which destroys +sessions after specified `cookie_lifetime` unless renewal occurs during normal +browser activity. It is recommended that the application logout via XHR request +(or something similar) to manually handle redirects. + +## Logging Out + +It is typical to provide users the ability to log out (i.e. to manually destroy) their +current session. Logging out is possible with either query params or `POST` params in +the request URL. The config's `logout_methods` allows the **Plugin** to limit logging +out based on the HTTP verb. When `logout_query_arg` is set, it will check the +presence of the URL query param specified, and likewise when `logout_post_arg` +is set it will check the presence of the specified variable in the request body. +Allowed HTTP verbs are `GET`, `DELETE`, and `POST`. When there is a session +present and the incoming request is a logout request, the Kong Session **Plugin** will +return a 200 before continuing in the **Plugin** run loop, and the request will not +continue to the upstream. + +## Known Limitations + +Due to limitations of OpenResty, the `header_filter` phase cannot connect to the +database, which poses a problem for initial retrieval of cookie (fresh session). +There is a small window of time where cookie is sent to client, but database +insert has not yet been committed, as database call is in `ngx.timer` thread. +Current workaround is to wait some interval of time (~100-500ms) after +`Set-Cookie` header is sent to client before making subsequent requests. This is +_not_ a problem during session renewal period as renew happens in `access` phase. + +[plugin]: https://docs.konghq.com/hub/ +[lua-resty-session]: https://github.com/bungle/lua-resty-session +[multiple authentication]: https://docs.konghq.com/0.14.x/auth/#multiple-authentication +[key auth]: https://docs.konghq.com/hub/kong-inc/key-auth/ +[request termination]: https://docs.konghq.com/hub/kong-inc/request-termination/ diff --git a/app/_hub/kong-inc/session/index.md b/app/_hub/kong-inc/session/index.md index 6097e34b959a..7c73e2ee8cda 100644 --- a/app/_hub/kong-inc/session/index.md +++ b/app/_hub/kong-inc/session/index.md @@ -1,7 +1,7 @@ --- name: Session publisher: Kong Inc. -version: 2.0.0-x +version: 2.2.0-x redirect_from: - /hub/kong-in/sessions - /hub/kong-inc/sessions @@ -23,7 +23,14 @@ source_url: https://github.com/Kong/kong-plugin-session kong_version_compatibility: community_edition: compatible: + - 1.4.x + - 1.3.x - 1.2.x + enterprise_edition: + compatible: + - 1.3.x + - 0.36-x + - 0.35-x params: name: session @@ -329,14 +336,25 @@ variable host, but can be overridden. ### Session Data Storage The session data can be stored in the cookie itself (encrypted) `storage=cookie`, -or inside [Kong](#-kong-storage-adapter). The session data stores two context +or inside [Kong](#-kong-storage-adapter). The session data stores these context variables: ``` ngx.ctx.authenticated_consumer.id ngx.ctx.authenticated_credential.id +ngx.ctx.authenticated_groups ``` +The plugin also sets a `ngx.ctx.authenticated_session` for communication between +the `access` and `header_filter` phases in the plugin. + +### Groups + +Authenticated groups are stored on `ngx.ctx.authenticated_groups` from other +authentication plugins and the session plugin will store them in the data of +the current session. Since the session plugin runs before authentication +plugins, it will also set `authenticated_groups` associated headers. + ## Kong Storage Adapter the Kong Session **Plugin** extends the functionality of [lua-resty-session] with its own diff --git a/app/_hub/kong-inc/vault-auth/0.35-x.md b/app/_hub/kong-inc/vault-auth/0.35-x.md index 2b33edbe9a5a..202707235a13 100644 --- a/app/_hub/kong-inc/vault-auth/0.35-x.md +++ b/app/_hub/kong-inc/vault-auth/0.35-x.md @@ -250,3 +250,6 @@ $ vault write kong-auth/foo - <*note*: the key names may only contain [a-z], [A-Z], [0-9], [_] and [-]. + - name: vault + required: true + default: + description: | + A reference to an existing `vault` objection within the database. `vault` entities define the connection and authentication parameters used to connection to a Vault HTTP(S) API. + - name: secret_token_name + required: true + default: "`access_token`" + description: | + Describes an array of comma separated parameter names where the plugin will look for a secret token. The client must send the secret in one of those key names, and the plugin will try to read the credential from a header or the querystring parameter with the same name.
*note*: the key names may only contain [a-z], [A-Z], [0-9], [_] and [-]. + - name: key_in_body + required: false + default: "`false`" + description: | + If enabled, the plugin will read the request body (if said request has one and its MIME type is supported) and try to find the key in it. Supported MIME types are `application/www-form-urlencoded`, `application/json`, and `multipart/form-data`. + - name: hide_credentials + required: false + default: "`false`" + description: | + An optional boolean value telling the plugin to show or hide the credential from the upstream service. If `true`, the plugin will strip the credential from the request (i.e. the header or querystring containing the key) before proxying it. + - name: anonymous + required: false + default: + description: | + An optional string (consumer uuid) value to use as an "anonymous" consumer if authentication fails. If empty (default), the request will fail with an authentication failure `4xx`. Please note that this value must refer to the Consumer `id` attribute which is internal to Kong, and **not** its `custom_id`. + - name: run_on_preflight + required: false + default: "`true`" + description: | + A boolean value that indicates whether the plugin should run (and try to authenticate) on `OPTIONS` preflight requests, if set to `false` then `OPTIONS` requests will always be allowed. + +--- + +## Usage + +In order to use the plugin, you first need to create a Consumer to associate one or more credentials to. The Consumer represents a developer using the upstream service. Additionally, a Vault object must be created to represent the connection Kong will use to communicate with a Vault server, where access and secret tokens will be stored. + +### Create a Consumer + +You need to associate a credential to an existing [Consumer][consumer-object] object. To create a Consumer, you can execute the following request: + +```bash +$ curl -X POST http://kong:8001/consumers/ \ + --data "username=" \ + --data "custom_id=" +HTTP/1.1 201 Created + +{ + "username":"", + "custom_id": "", + "created_at": 1472604384000, + "id": "7f853474-7b70-439d-ad59-2481a0a9a904" +} +``` + +parameter | default | description +--- | --- | --- +`username`
*semi-optional* | | The username of the Consumer. Either this field or `custom_id` must be specified. +`custom_id`
*semi-optional* | | A custom identifier used to map the Consumer to another database. Either this field or `username` must be specified. + +A [Consumer][consumer-object] can have many credentials. + +If you are also using the [ACL](/plugins/acl/) plugin and whitelists with this +service, you must add the new consumer to a whitelisted group. See +[ACL: Associating Consumers][acl-associating] for details. + +### Create a Vault + +A Vault object represents the connection between Kong and a Vault server. It defines the connection and authentication information used to communicate with the Vault API. This allows different instances of the `vault-auth` plugin to communicate with different Vault servers, providing a flexible deployment and consumption model. + +Vault objects can be created via the following HTTP request: + +```bash +$ curl -X POST http://kong:8001/vaults \ + --data name=kong-auth \ + --data mount=kong-auth \ + --data protocol=http \ + --data host=127.0.0.1 \ + --data port=8200 + --data token=s.m3w9gdV0uMDYFpMgEWSB2mtM +HTTP/1.1 201 Created + +{ + "created_at": 1550538643, + "host": "127.0.0.1", + "id": "d3da058d-0acb-49c2-b7fe-72b3e9fd4b0a", + "mount": "kong-auth", + "name": "kong-auth", + "port": 8200, + "protocol": "http", + "token": "s.m3w9gdV0uMDYFpMgEWSB2mtM", + "updated_at": 1550538643 +} +``` + +This assumes a Vault server is accessible via `127.0.0.1:8200`, and that a version 1 KV secrets engine has been enabled at `kong-auth`. Vault KV secrets engine documentation is available via the [Vault documentation](https://www.vaultproject.io/docs/secrets/kv/kv-v1.html). + +### Create an Access/Secret Token Pair + +`vault-auth` credentials are defined as a pair of tokens: an `access` token that identifies the owner of the credential, and a `secret` token that is used to authenticate ownership of the `access` token. + +Token pairs can be managed either via the Kong Admin API, or independantly via direct access with Vault. Token pairs must be associated with an existing Kong Consumer. Creating a token pair with the Kong Admin API can be done via the following request: + +```bash +$ curl -X POST http://kong:8001/vaults/{vault}/credentials/{consumer} +HTTP/1.1 201 Created + +{ + "data": { + "access_token": "v3cOV1jWglS0PFOrTcdr85bs1GP0e2yM", + "consumer": { + "id": "64063284-e3b5-48e7-9bca-802251c32138" + }, + "created_at": 1550538920, + "secret_token": "11XYyybbu3Ty0Qt4ImIshPGQ0WsvjLzl", + "ttl": null + } +} +``` + +When the `access_token` or `secret_token` values are not provided, token values will be automatically generated via a cryptographically-secure random number generator (CSPRNG). + +### Integrating Vault objects with Vault-Auth plugins + +Vault objects are treated as foreign references in plugin configs, creating a seamless lifecycle relationship between Vault instances and plugins with which they're associated. `vault-auth` plugins require an association with a Vault object, which can be defined with the following HTTP request during plugin creation: + +```bash +$ curl -X POST http://kong:8001/plugins \ + --data name=vault-auth \ + --data config.vault.id= +HTTP/1.1 201 Created + +{ + "created_at": 1550539002, + "config": { + "tokens_in_body": false, + "secret_token_name": "secret_token", + "run_on_preflight": true, + "vault": { + "id": "d3da058d-0acb-49c2-b7fe-72b3e9fd4b0a" + }, + "anonymous": null, + "hide_credentials": false, + "access_token_name": "access_token" + }, + "id": "b4d0cbb7-bff2-4599-ba19-67c705c15b9a", + "service": null, + "enabled": true, + "run_on": "first", + "consumer": null, + "route": null, + "name": "vault-auth" +} + +``` + +Where `` is the `id` of an existing Vault object. + +### Using Vault credentials + +Simply make a request with the `access_token` and `secret_token` as querystring parameters: + +```bash +$ curl http://kong:8000/{proxy path}?access_token=&secret_token= +``` + +Or in a header: + +```bash +$ curl http://kong:8000/{proxy path} \ + -H 'access_token: ' \ + -H 'secret_token: ' +``` + +### Deleting an Access/Secret Token Pair + +Existing Vault credentials can be removed from the Vault server via the following API: + +```bash +$ curl -X DELETE http://kong:8001/vaults/{vault}/credentials/token/{access token} + +HTTP/1.1 204 No Content +``` + +### Token TTL + +When reading a token from Vault, Kong will search the responding KV value for the presence of a `ttl` field. When this is present, Kong will respect the advisory value of the `ttl`field and store the value of the credential in cache for only as long as the `ttl` field defines. This allows tokens created directly in Vault, outside of the Kong Admin API, to be periodically refreshed by Kong. + +### Extra-Kong Token Pairs + +Kong can read access/token secret pairs that have been created directly in Vault, outside of the Kong Admin API. Currently `vault-auth` supports creating and reading credentials based on the Vault v1 KV engine. Create Vault KV secret values must contain the following fields: + +``` +{ + access_token: + secret_token: + created_at: + updated_at: + ttl: (optional) + consumer: { + id: + } +} +``` + +Additional fields within the secret are ignored. The key must be the `access_token` value; this is the identifier by which Kong queries the Vault API to fetch the credential data. See the [Vault documentation](https://www.vaultproject.io/docs/secrets/kv/kv-v1.html) for further information on the KV v1 secrets engine. + +`vault-auth` token pairs can be created with the Vault HTTP API or the `vault write` command: + +```bash +$ vault write kong-auth/foo - <*note*: the key names may only contain [a-z], [A-Z], [0-9], [_] and [-]. + - name: vault + required: true + default: + description: | + A reference to an existing `vault` objection within the database. `vault` entities define the connection and authentication parameters used to connection to a Vault HTTP(S) API. + - name: secret_token_name + required: true + default: "`access_token`" + description: | + Describes an array of comma separated parameter names where the plugin will look for a secret token. The client must send the secret in one of those key names, and the plugin will try to read the credential from a header or the querystring parameter with the same name.
*note*: the key names may only contain [a-z], [A-Z], [0-9], [_] and [-]. + - name: key_in_body + required: false + default: "`false`" + description: | + If enabled, the plugin will read the request body (if said request has one and its MIME type is supported) and try to find the key in it. Supported MIME types are `application/www-form-urlencoded`, `application/json`, and `multipart/form-data`. + - name: hide_credentials + required: false + default: "`false`" + description: | + An optional boolean value telling the plugin to show or hide the credential from the upstream service. If `true`, the plugin will strip the credential from the request (i.e. the header or querystring containing the key) before proxying it. + - name: anonymous + required: false + default: + description: | + An optional string (consumer uuid) value to use as an "anonymous" consumer if authentication fails. If empty (default), the request will fail with an authentication failure `4xx`. Please note that this value must refer to the Consumer `id` attribute which is internal to Kong, and **not** its `custom_id`. + - name: run_on_preflight + required: false + default: "`true`" + description: | + A boolean value that indicates whether the plugin should run (and try to authenticate) on `OPTIONS` preflight requests, if set to `false` then `OPTIONS` requests will always be allowed. + +--- + +## Usage + +In order to use the plugin, you first need to create a Consumer to associate one or more credentials to. The Consumer represents a developer using the upstream service. Additionally, a Vault object must be created to represent the connection Kong will use to communicate with a Vault server, where access and secret tokens will be stored. + +### Create a Consumer + +You need to associate a credential to an existing [Consumer][consumer-object] object. To create a Consumer, you can execute the following request: + +```bash +$ curl -X POST http://kong:8001/consumers/ \ + --data "username=" \ + --data "custom_id=" +HTTP/1.1 201 Created + +{ + "username":"", + "custom_id": "", + "created_at": 1472604384000, + "id": "7f853474-7b70-439d-ad59-2481a0a9a904" +} +``` + +parameter | default | description +--- | --- | --- +`username`
*semi-optional* | | The username of the Consumer. Either this field or `custom_id` must be specified. +`custom_id`
*semi-optional* | | A custom identifier used to map the Consumer to another database. Either this field or `username` must be specified. + +A [Consumer][consumer-object] can have many credentials. + +If you are also using the [ACL](/plugins/acl/) plugin and whitelists with this +service, you must add the new consumer to a whitelisted group. See +[ACL: Associating Consumers][acl-associating] for details. + +### Create a Vault + +A Vault object represents the connection between Kong and a Vault server. It defines the connection and authentication information used to communicate with the Vault API. This allows different instances of the `vault-auth` plugin to communicate with different Vault servers, providing a flexible deployment and consumption model. + +Vault objects can be created via the following HTTP request: + +```bash +$ curl -X POST http://kong:8001/vaults \ + --data name=kong-auth \ + --data mount=kong-auth \ + --data protocol=http \ + --data host=127.0.0.1 \ + --data port=8200 + --data token=s.m3w9gdV0uMDYFpMgEWSB2mtM +HTTP/1.1 201 Created + +{ + "created_at": 1550538643, + "host": "127.0.0.1", + "id": "d3da058d-0acb-49c2-b7fe-72b3e9fd4b0a", + "mount": "kong-auth", + "name": "kong-auth", + "port": 8200, + "protocol": "http", + "token": "s.m3w9gdV0uMDYFpMgEWSB2mtM", + "updated_at": 1550538643 +} +``` + +This assumes a Vault server is accessible via `127.0.0.1:8200`, and that a version 1 KV secrets engine has been enabled at `kong-auth`. Vault KV secrets engine documentation is available via the [Vault documentation](https://www.vaultproject.io/docs/secrets/kv/kv-v1.html). + +### Create an Access/Secret Token Pair + +`vault-auth` credentials are defined as a pair of tokens: an `access` token that identifies the owner of the credential, and a `secret` token that is used to authenticate ownership of the `access` token. + +Token pairs can be managed either via the Kong Admin API, or independantly via direct access with Vault. Token pairs must be associated with an existing Kong Consumer. Creating a token pair with the Kong Admin API can be done via the following request: + +```bash +$ curl -X POST http://kong:8001/vaults/{vault}/credentials/{consumer} +HTTP/1.1 201 Created + +{ + "data": { + "access_token": "v3cOV1jWglS0PFOrTcdr85bs1GP0e2yM", + "consumer": { + "id": "64063284-e3b5-48e7-9bca-802251c32138" + }, + "created_at": 1550538920, + "secret_token": "11XYyybbu3Ty0Qt4ImIshPGQ0WsvjLzl", + "ttl": null + } +} +``` + +When the `access_token` or `secret_token` values are not provided, token values will be automatically generated via a cryptographically-secure random number generator (CSPRNG). + +### Integrating Vault objects with Vault-Auth plugins + +Vault objects are treated as foreign references in plugin configs, creating a seamless lifecycle relationship between Vault instances and plugins with which they're associated. `vault-auth` plugins require an association with a Vault object, which can be defined with the following HTTP request during plugin creation: + +```bash +$ curl -X POST http://kong:8001/plugins \ + --data name=vault-auth \ + --data config.vault.id= +HTTP/1.1 201 Created + +{ + "created_at": 1550539002, + "config": { + "tokens_in_body": false, + "secret_token_name": "secret_token", + "run_on_preflight": true, + "vault": { + "id": "d3da058d-0acb-49c2-b7fe-72b3e9fd4b0a" + }, + "anonymous": null, + "hide_credentials": false, + "access_token_name": "access_token" + }, + "id": "b4d0cbb7-bff2-4599-ba19-67c705c15b9a", + "service": null, + "enabled": true, + "run_on": "first", + "consumer": null, + "route": null, + "name": "vault-auth" +} + +``` + +Where `` is the `id` of an existing Vault object. + +### Using Vault credentials + +Simply make a request with the `access_token` and `secret_token` as querystring parameters: + +```bash +$ curl http://kong:8000/{proxy path}?access_token=&secret_token= +``` + +Or in a header: + +```bash +$ curl http://kong:8000/{proxy path} \ + -H 'access_token: ' \ + -H 'secret_token: ' +``` + +### Deleting an Access/Secret Token Pair + +Existing Vault credentials can be removed from the Vault server via the following API: + +```bash +$ curl -X DELETE http://kong:8001/vaults/{vault}/credentials/token/{access token} + +HTTP/1.1 204 No Content +``` + +### Token TTL + +When reading a token from Vault, Kong will search the responding KV value for the presence of a `ttl` field. When this is present, Kong will respect the advisory value of the `ttl`field and store the value of the credential in cache for only as long as the `ttl` field defines. This allows tokens created directly in Vault, outside of the Kong Admin API, to be periodically refreshed by Kong. + +### Extra-Kong Token Pairs + +Kong can read access/token secret pairs that have been created directly in Vault, outside of the Kong Admin API. Currently `vault-auth` supports creating and reading credentials based on the Vault v1 KV engine. Create Vault KV secret values must contain the following fields: + +``` +{ + access_token: + secret_token: + created_at: + updated_at: + ttl: (optional) + consumer: { + id: + } +} +``` + +Additional fields within the secret are ignored. The key must be the `access_token` value; this is the identifier by which Kong queries the Vault API to fetch the credential data. See the [Vault documentation](https://www.vaultproject.io/docs/secrets/kv/kv-v1.html) for further information on the KV v1 secrets engine. + +`vault-auth` token pairs can be created with the Vault HTTP API or the `vault write` command: + +```bash +$ vault write kong-auth/foo - <{{nav.title}} {% if page.toc == true or page.toc != false and filename != "index.md" %}

Table of Contents

- {% include toc.html html=content anchor_class="scroll-to" h_max=4 %} + {% include toc.html html=content anchor_class="scroll-to" h_max=3 %} + {% endif %} {{ content }} @@ -170,7 +171,7 @@

Table of Contents

docsearch({ appId: 'T5JKD83LWT', apiKey: '1390283021f26e36117242934deb8d9d', - indexName: 'prod_EE', + indexName: 'private_RC', inputSelector: '#getkong-algolia-search-input', algoliaOptions: { hitsPerPage: 5, diff --git a/app/enterprise/0.35-x/cli.md b/app/enterprise/0.35-x/cli.md index 25b77821ea32..8af20c6f3e08 100644 --- a/app/enterprise/0.35-x/cli.md +++ b/app/enterprise/0.35-x/cli.md @@ -240,7 +240,6 @@ Options: --- - ### kong start ``` diff --git a/app/enterprise/0.36-x/developer-portal/configuration/smtp.md b/app/enterprise/0.36-x/developer-portal/configuration/smtp.md index 10f90338522c..846e9c1fe871 100644 --- a/app/enterprise/0.36-x/developer-portal/configuration/smtp.md +++ b/app/enterprise/0.36-x/developer-portal/configuration/smtp.md @@ -33,6 +33,15 @@ You have been invited to create a Developer Portal account at %s. Please visit `` to create your account. ``` + +### portal_email_verification + +**Default:** `off` + +**Description:** +When enabled Developers will receive an email upon registration to verify their account. Developers will not be able to use the Dev Portal until their account is verified, even if auto-approve is enabled. + + ### portal_access_request_email **Default:** `on` diff --git a/app/enterprise/1.3-x/README.md b/app/enterprise/1.3-x/README.md new file mode 100644 index 000000000000..50f4f885b2e4 --- /dev/null +++ b/app/enterprise/1.3-x/README.md @@ -0,0 +1,3 @@ +# Enterprise 1.3 Release + +## Add your 1.3 documents to this folder diff --git a/app/enterprise/1.3-x/admin-api/admins/examples.md b/app/enterprise/1.3-x/admin-api/admins/examples.md new file mode 100644 index 000000000000..d0c575fa582e --- /dev/null +++ b/app/enterprise/1.3-x/admin-api/admins/examples.md @@ -0,0 +1,57 @@ +--- +title: Admins Examples +book: admins +--- + +## How to Invite and Register an Admin + +### Introduction + +Can be used for automation + +### Prerequisites + +```bash +export USERNAME= +export EMAIL= +export WORKSPACE= +export HOST= +export TOKEN=Kong-Admin-Token: +``` + +for example: +```bash +export USERNAME=drogon +export EMAIL=test@test.com +export WORKSPACE=default +export HOST=127.0.0.1:8001 +export ADMIN_TOKEN=Kong-Admin-Token:hunter2 +``` + +May benefit from HTTPie and jq. + +## Step 1 +Extract and store the token from the registration URL, either by manually creating an environment variable or by echoing and piping with `jq`: + +#### Manual method example: + +1. Send a request to the registration URL +```bash +http $HOST/$WORKSPACE/admins/$USERNAME?generate_register_url=true $TOKEN +``` + +2. Copy the response and export as an environment variable, for example: +```bash +export REGISTER_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NDUwNjc0NjUsImlkIjoiM2IyNzY3MzEtNjIxZC00ZjA3LTk3YTQtZjU1NTg0NmJkZjJjIn0.gujRDi2pX_E7u2zuhYBWD4MoPFKe3axMAq-AUcORg2g +``` + +#### Programmatic method (requires `jq`): +```bash +REGISTER_TOKEN=$(http $HOST/$WORKSPACE/admins/$USERNAME?generate_register_url=true $TOKEN | jq .token -r) +``` + +## Step 2 + +```bash +http $HOST/$WORKSPACE/admins/register token=$REGISTER_TOKEN username=$USERNAME email=$EMAIL password="" +``` diff --git a/app/enterprise/1.3-x/admin-api/admins/reference.md b/app/enterprise/1.3-x/admin-api/admins/reference.md new file mode 100644 index 000000000000..450d1786846a --- /dev/null +++ b/app/enterprise/1.3-x/admin-api/admins/reference.md @@ -0,0 +1,321 @@ +--- +title: Admins Reference +book: admins +--- + +## List Admins +**Endpoint** + +
/admins
+ +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "data": [{ + "created_at": 1556638385, + "id": "665b4070-541f-48bf-82c1-53030babaa81", + "updated_at": 1556638385, + "status": 4, + "username": "test-admin", + "email": "test@test.com" + }, { + "created_at": 1556563122, + "id": "a93ff120-9e6c-4198-b47e-f779104c7eac", + "updated_at": 1556563122, + "status": 0, + "username": "kong_admin" + }], + "next": null +} +``` + +## Invite an Admin +**Endpoint** + +
/admins
+ +| Attribute | Description | +|-------------|------------------------------------------------------------| +| `email` | The **Admin**'s email address | +| `username` | The **Admin**'s username | +| `custom_id`
optional | The **Admin**'s custom ID | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "admin": { + "created_at": 1556638641, + "id": "8f0a742f-07f3-49e0-90d7-4fc7eea7e6a4", + "updated_at": 1556638641, + "status": 4, + "username": "test-case-3", + "email": "test3@test.com" + } +} +``` + +## Register an Admin's Credentials +**Endpoint** + +
/admins/register
+ +| Attribute | Description | +|-------------|---------------------------| +| `token` | The authentication token | +| `username` | The **Admin**'s username | +| `email` | The **Admin**'s email address | +| `password` | The **Admin**'s new password | + +**Response** + +``` +HTTP 201 Created +``` + +## Send a Password-Reset Email to an Admin +**Endpoint** + +
/admins/password_resets
+ +| Attribute | Description | +|-------------|------------------------------------------------------------| +| `email` | The **Admin**'s email address | + +**Response** + +``` +HTTP 201 Created +``` + +## Reset an Admin's Password +**Endpoint** + +
/admins/password_resets
+ +| Attribute | Description | +|-------------|------------------------------------------------------------| +| `email` | The **Admin**'s email address | +| `password` | The **Admin**'s new password | +| `token` | The authentication token | + +**Response** + +``` +HTTP 200 OK +``` + +## Retrieve an Admin +**Endpoint** + +
/admins/{name_or_id}
+ +| Attribute | Description | +|------------|-----------------------------------| +| `name_or_id` | The **Admin**'s username or ID | +| `generate_register_url`
optional | `true` returns a unique registration URL for the **Admin** | + +**Notes:** +* `generate_register_url` will only generate a URL if the **Admin**'s +invitation status is 4 ("invited"). +* `generate_register_url` will override the preĂĽvious registration URL +for the particular **Admin** each time it is requested. + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "created_at": 1556638385, + "id": "665b4070-541f-48bf-82c1-53030babaa81", + "updated_at": 1556638385, + "status": 4, + "username": "test-admin", + "email": "test@test.com" +} +``` + +## Update an Admin +**Endpoint** + +
/admins/{name_or_id}
+ +| Attribute | Description | +|----------------------|--------------------------------------------| +| `name_or_id` | The **Admin**'s current username or custom ID | +| `email`
optional | The **Admin**'s new email address | +| `username`
optional | The **Admin**'s new username | +| `custom_id`
optional | The **Admin**'s new custom ID | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "created_at": 1556638385, + "id": "665b4070-541f-48bf-82c1-53030babaa81", + "updated_at": 1556639017, + "status": 4, + "username": "test-renamed", + "email": "test@test.com" +} +``` + +## Delete an Admin +**Endpoint** + +
/admins/{name_or_id}
+ +| Attribute | Description | +|--------------|-----------------------------------| +| `name_or_id` | The **Admin**'s username or ID | + +**Response** + +``` +HTTP 204 No Content +``` + +## List an Admin's Roles +**Endpoint** + +
/admins/{name_or_id}/roles
+ +| Attribute | Description | +|--------------|-----------------------------------| +| `name_or_id` | The **Admin**'s username or ID | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "roles": [{ + "comment": "Read access to all endpoints, across all workspaces", + "created_at": 1556563122, + "id": "7574eb1d-c9fa-46a9-bd3a-3f1b4b196287", + "name": "read-only", + "is_default": false + }, { + "comment": "Full access to all endpoints, across all workspaces—except RBAC Admin API", + "created_at": 1556563122, + "id": "7fdea5c8-2bfa-4aa9-9c21-7bb9e607186d", + "name": "admin", + "is_default": false + }] +} +``` + +## Create or Update an Admin's Roles +**Endpoint** + +
/admins/{name_or_id}/roles
+ +| Attribute | Description | +|--------------|-----------------------------------------------------------| +| `name_or_id` | The **Admin**'s current username or ID | +| `roles` | (comma separated) string of names of Roles to create or update for an **Admin** | + +**Response** + +``` +HTTP 201 OK +``` + + +```json +{ + "roles": [{ + "comment": "Read access to all endpoints, across all workspaces", + "created_at": 1556563122, + "id": "7574eb1d-c9fa-46a9-bd3a-3f1b4b196287", + "name": "read-only", + "is_default": false + }, { + "comment": "Full access to all endpoints, across all workspaces—except RBAC Admin API", + "created_at": 1556563122, + "id": "7fdea5c8-2bfa-4aa9-9c21-7bb9e607186d", + "name": "admin", + "is_default": false + }, { + "comment": "Full access to all endpoints, across all workspaces", + "created_at": 1556563122, + "id": "99bd8d18-f5b6-410e-aefe-d75f4252f13c", + "name": "super-admin", + "is_default": false + }] +} +``` + +## Delete an Admin's Role +**Endpoint** + +
/admins/{name_or_id}/roles
+ +| Attribute | Description | +|--------------|-----------------------------------------------------------| +| `name_or_id` | The **Admin**'s current username or custom ID | +| `roles` | (comma separated) string of names of Roles to remove from an **Admin** | + +**Response** + +``` +HTTP 204 No Content +``` + +## List an Admin's Workspaces +**Endpoint** + +
/admins/{name_or_id}/workspaces
+ +| Attribute | Description | +|--------------|-----------------------------------| +| `name_or_id` | The **Admin**'s username or ID | + +**Response** + +``` +HTTP 200 OK +``` + +```json +[{ + "created_at": 1556563122, + "config": { + "portal": true, + "portal_auto_approve": true + }, + "id": "00000000-0000-0000-0000-000000000000", + "name": "default", + "meta": {} +}, { + "created_at": 1556570807, + "config": { + "portal": true + }, + "id": "57b3ce24-6d29-427f-af13-15bd60430e56", + "name": "sdfgsdfg", + "meta": { + "color": "#3894f0" + } +}] +``` + diff --git a/app/enterprise/1.3-x/admin-api/audit-log.md b/app/enterprise/1.3-x/admin-api/audit-log.md new file mode 100644 index 000000000000..c8ff51750b12 --- /dev/null +++ b/app/enterprise/1.3-x/admin-api/audit-log.md @@ -0,0 +1,427 @@ +--- +title: Admin API Audit Log +--- + +## Introduction + +Kong Enterprise provides a granular logging facility on its Admin API. This +allows cluster administrators to keep detailed track of changes made to the +cluster configuration throughout its lifetime, aiding in compliance efforts and +providing valuable data points during forensic investigations. Generated audit +log trails are [Workspace](/enterprise/{{page.kong_version}}/admin-api/workspaces/reference) +- and [RBAC](/enterprise/{{page.kong_version}}/admin-api/rbac/reference)-aware, +providing Kong operators a deep and wide look into changes happening within +the cluster. + +[Back to TOC](#table-of-contents) + +## Getting Started + +Audit logging is disabled by default. It is configured via the Kong configuration: + +```bash +# via Kong configuration file, e.g., kong.conf +audit_log = on # audit logging is enabled +audit_log = off # audit logging is disabled +``` + +```bash +# or via environmental variables +$ export KONG_AUDIT_LOG=on +$ export KONG_AUDIT_LOG=off +``` + +As with other Kong configurations, changes take effect on kong reload or kong +restart. + +[Back to TOC](#table-of-contents) + +## Request Audits + +### Generating and Viewing Audit Logs + +Audit logging provides granular details of each HTTP request that was handled by +Kong's Admin API. Audit log data is written to Kong's back database. As a result, +request audit logs are available via the Admin API (in addition to via direct +database query). For example, consider a query to the Admin API to the `/status` +endpoint: + +``` +vagrant@ubuntu-xenial:/kong$ http :8001/status +HTTP/1.1 200 OK +Access-Control-Allow-Origin: * +Connection: keep-alive +Content-Type: application/json; charset=utf-8 +Date: Tue, 13 Nov 2018 17:32:47 GMT +Server: kong/0.34-enterprise-edition +Transfer-Encoding: chunked +X-Kong-Admin-Request-ID: ZuUfPfnxNn7D2OTU6Xi4zCnQkavzMUNM + +{ + "database": { + "reachable": true + }, + "server": { + "connections_accepted": 1, + "connections_active": 1, + "connections_handled": 1, + "connections_reading": 0, + "connections_waiting": 0, + "connections_writing": 1, + "total_requests": 1 + } +} +``` + +The above interaction with the Admin API would generate a correlating entry in +the audit log table—querying the audit log via the Admin API returns the details +of of the interaction above: + +``` +$ http :8001/audit/requests +HTTP/1.1 200 OK +Access-Control-Allow-Origin: * +Connection: keep-alive +Content-Type: application/json; charset=utf-8 +Date: Tue, 13 Nov 2018 17:35:24 GMT +Server: kong/0.34-enterprise-edition +Transfer-Encoding: chunked +X-Kong-Admin-Request-ID: VXgMG1Y3rZKbjrzVYlSdLNPw8asVwhET + +{ + "data": [ + { + "client_ip": "127.0.0.1", + "expire": 1544722367698, + "method": "GET", + "path": "/status", + "request_id": "ZuUfPfnxNn7D2OTU6Xi4zCnQkavzMUNM", + "request_timestamp": 1542130367699, + "status": 200, + "workspace": "0da4afe7-44ad-4e81-a953-5d2923ce68ae" + } + ], + "total": 1 +} +``` + +Note the value of the `request_id` field. This is tied to the +`X-Kong-Admin-Request-ID` response header received in the first transaction. +This allows close association of client requests and audit log records within +the Kong cluster. + +Because every audit log entry is made available via Kong's Admin API, it is +possible to transport audit log entries into existing logging warehouses, SIEM +solutions, or other remote services for duplication and inspection. + +[Back to TOC](#table-of-contents) + +### Workspaces and RBAC + +Audit log entries are written with an awareness of the requested Workspace, and +the RBAC user (if present). When RBAC is enforced, the RBAC user's UUID will be +written to the `rbac_user_id` field in the audit log entry: + +``` +{ + "data": [ + { + "client_ip": "127.0.0.1", + "expire": 1544722999857, + "method": "GET", + "path": "/status", + "rbac_user_id": "2e959b45-0053-41cc-9c2c-5458d0964331", + "request_id": "QUtUa3RMbRLxomqcL68ilOjjl68h56xr", + "request_timestamp": 1542130999858, + "status": 200, + "workspace": "0da4afe7-44ad-4e81-a953-5d2923ce68ae" + } + ], + "total": 1 +} +``` + +Note also the presence of the `workspace` field. This is the UUID of the Workspace with which the request was associated. + +[Back to TOC](#table-of-contents) + +### Limiting Audit Log Generation + +It may be desirable to ignore audit log generation for certain Admin API +requests, such as innocuous requests to the `/status` endpoint for +healthchecking, or to ignore requests for a given path prefix (e.g., a given +Workspace). To this end, the `audit_log_ignore_methods` and +`audit_log_ignore_paths` configuration options are presented: + +```bash +audit_log_ignore_methods = GET,OPTIONS +# do not generate an audit log entry for GET or OPTIONS HTTP requests +audit_log_ignore_paths = /foo,/status +# do not generate an audit log entry for requests that match the strings '/foo' or '/status' +``` + +Note that `audit_log_ignore_paths` values matched via simple string matching; +regular expression or anchored searching for ignored paths is not supported at +this time. + +[Back to TOC](#table-of-contents) + +## Database Audits + +### Generating and Viewing Audit Logs + +In addition to Admin API request data, Kong will generate granular audit log +entries for all insertions, updates, and deletions to the cluster database. +Database updates audit logs are also associated with Admin API request unique +IDs. Consider the following request to create a Consumer: + +``` +$ http :8001/consumers username=bob +HTTP/1.1 201 Created +Access-Control-Allow-Origin: * +Connection: keep-alive +Content-Type: application/json; charset=utf-8 +Date: Tue, 13 Nov 2018 17:50:18 GMT +Server: kong/0.34-enterprise-edition +Transfer-Encoding: chunked +X-Kong-Admin-Request-ID: 59fpTWlpUtHJ0qnAWBzQRHRDv7i5DwK2 + +{ + "created_at": 1542131418000, + "id": "16787ed7-d805-434a-9cec-5e5a3e5c9e4f", + "type": 0, + "username": "bob" +} + +``` + +As seen before, a request audit log is generated with details about the request. +Note the presence of the `payload` field, recorded when the request body is +present: + +``` +$ http :8001/audit/requests +HTTP/1.1 200 OK +Access-Control-Allow-Origin: * +Connection: keep-alive +Content-Type: application/json; charset=utf-8 +Date: Tue, 13 Nov 2018 17:52:41 GMT +Server: kong/0.34-dev-enterprise-edition +Transfer-Encoding: chunked +X-Kong-Admin-Request-ID: SpPaxLTkDNndzKaYiWuZl3xrxDUIiGRR + +{ + "data": [ + { + "client_ip": "127.0.0.1", + "expire": 1544723418013, + "method": "POST", + "path": "/consumers", + "payload": "{\"username\": \"bob\"}", + "request_id": "59fpTWlpUtHJ0qnAWBzQRHRDv7i5DwK2", + "request_timestamp": 1542131418014, + "status": 201, + "workspace": "fd51ce6e-59c0-4b6b-b991-aa708a9ff4d2" + } + ], + "total": 1 +} +``` + +Additionally, additional audit logs are generated to track the creation of the +database entity: + +``` +$ http :8001/audit/objects +HTTP/1.1 200 OK +Access-Control-Allow-Origin: * +Connection: keep-alive +Content-Type: application/json; charset=utf-8 +Date: Tue, 13 Nov 2018 17:53:27 GMT +Server: kong/0.34-dev-enterprise-edition +Transfer-Encoding: chunked +X-Kong-Admin-Request-ID: ZKra3QT0d3eJKl96jOUXYueLumo0ck8c + +{ + "data": [ + { + "dao_name": "consumers", + "entity": "{\"created_at\":1542131418000,\"id\":\"16787ed7-d805-434a-9cec-5e5a3e5c9e4f\",\"username\":\"bob\",\"type\":0}", + "entity_key": "16787ed7-d805-434a-9cec-5e5a3e5c9e4f", + "expire": 1544723418009, + "id": "7ebabee7-2b09-445d-bc1f-2092c4ddc4be", + "operation": "create", + "request_id": "59fpTWlpUtHJ0qnAWBzQRHRDv7i5DwK2" + }, + ], + "total": 1 +} +``` + +Object audit entries contain information about the entity updated, including the +entity body itself, its database primary key, and the type of operation +performed (`create`, `update`, or `delete`). Note also the associated + `request_id` field. + +[Back to TOC](#table-of-contents) + +### Limiting Audit Log Generation + +As with request audit logs, it may be desirable to skip generation of audit logs +for certain database tables. This is configurable via the +`audit_log_ignore_tables` Kong config option: + +``` +audit_log_ignore_tables = consumers +# do not generate database audit logs for changes to the consumers table +``` + +[Back to TOC](#table-of-contents) + +## Digital Signatures + +To provide nonrepudiation, audit logs may be signed with a private RSA key. When +enabled, a lexically sorted representation of each audit log entry is signed by +the defined private key; the signature is stored in an additional field within +the record itself. The public key should be stored elsewhere and can be used +later to validate the signature of the record. + +### Setting Up Log Signing + +Generate a private key via the `openssl` tool: + +```bash +$ openssl genrsa -out private.pem 2048 +``` + +Configure Kong to sign audit log records: + +``` +audit_log_signing_key = /path/to/private.pem +``` + +Audit log entries will now contain a field `signature`: + +``` +{ + "client_ip": "127.0.0.1", + "expire": 1544724298663, + "method": "GET", + "path": "/status", + "request_id": "Ka2GeB13RkRIbMwBHw0xqe2EEfY0uZG0", + "request_timestamp": 1542132298664, + "signature": "ctD8DXJEfuFAVdlYuhay7f4kmcZhfRPjX8Q6HlSJ+67aHjJIzzrlSxWKfmxnJ7WKRvlF7bU8PX/rtu1ytLQwmzW2LpMd/WFt34PKmyOFUByslkxCdfKKNHadZ+FfINzD+JrecFdXNJrSxKKHHTxj8g6vglAcoJMmuSB6cMsAuVUbO+CL6N/WV9RfCquxxkQUfqGoyEA09EeU4uC0xa8gcYAr1FMGcu+TdRbazfBqZayrKxn8iMV/7LUefMgzUrVdC7UFjZORo5Q0wl9U/iQWU5sRGiTo/HTQmU/a7EdyX3c6Wbmg2khYJFzUIkg9JRL/YUla+yfe3AL4KwFSH90xTw==", + "status": 200, + "workspace": "fd51ce6e-59c0-4b6b-b991-aa708a9ff4d2" +} +``` + +[Back to TOC](#table-of-contents) + +### Validating Signatures + +Record signatures can be regenerated and verified by `openssl` or other +cryptographic tools to confirm the validity of the signature. Re-generating the +signature requires serializing the record into a string format that can be +signed. The following is a canonical implementation written in Lua: + +```lua +local pl_sort = require "pl.tablex".sort + +local function serialize(data) + local p = {} + + for k, v in pl_sort(data) do + if type(v) == "table" then + p[#p + 1] = serialize(v) + else + p[#p + 1] = v + end + end + + return p +end + +table.concat(serialize(data), "|") +``` + +The contents of the record itself can be fed to this implementation (minus the +`signature` field) in order to derive the value passed to the RSA key signing +facility. Note that the `signature` field within each record is a Base-64 +encoded representation of the RSA signature itself. + +[Back to TOC](#table-of-contents) + +--- + +## Reference + +### API Reference + +#### List Request Audit Logs + +##### Endpoint + +
/audit/requests
+ +##### Response + +``` +HTTP 200 OK +``` + +```json +{ + "data": [ + { + "client_ip": "127.0.0.1", + "expire": 1544722367698, + "method": "GET", + "path": "/status", + "request_id": "ZuUfPfnxNn7D2OTU6Xi4zCnQkavzMUNM", + "request_timestamp": 1542130367699, + "status": 200, + "workspace": "0da4afe7-44ad-4e81-a953-5d2923ce68ae" + } + ], + "total": 1 +} +``` + +#### List Database Audit Logs + +##### Endpoint + +
/audit/objects
+ +##### Response + +``` +HTTP 200 OK +``` + +```json +{ + "data": [ + { + "dao_name": "consumers", + "entity": "{\"created_at\":1542131418000,\"id\":\"16787ed7-d805-434a-9cec-5e5a3e5c9e4f\",\"username\":\"bob\",\"type\":0}", + "entity_key": "16787ed7-d805-434a-9cec-5e5a3e5c9e4f", + "expire": 1544723418009, + "id": "7ebabee7-2b09-445d-bc1f-2092c4ddc4be", + "operation": "create", + "request_id": "59fpTWlpUtHJ0qnAWBzQRHRDv7i5DwK2" + }, + ], + "total": 1 +} +``` + +[Back to TOC](#table-of-contents) + +### Configuration Reference + +See the [Data & Admin Audit](/enterprise/{{page.kong_version}}/property-reference#data--admin-audit) +section of Kong Enterprise's Configuration Property Reference. + +[Back to TOC](#table-of-contents) diff --git a/app/enterprise/1.3-x/admin-api/index.md b/app/enterprise/1.3-x/admin-api/index.md new file mode 100644 index 000000000000..ac9a1a204f52 --- /dev/null +++ b/app/enterprise/1.3-x/admin-api/index.md @@ -0,0 +1,3027 @@ +--- +title: Admin API + +service_body: | + Attributes | Description + ---:| --- + `name`
*optional* | The Service name. + `retries`
*optional* | The number of retries to execute upon failure to proxy. Defaults to `5`. + `protocol` | The protocol used to communicate with the upstream. It can be one of `http` or `https`. Defaults to `"http"`. + `host` | The host of the upstream server. + `port` | The upstream server port. Defaults to `80`. + `path`
*optional* | The path to be used in requests to the upstream server. + `connect_timeout`
*optional* | The timeout in milliseconds for establishing a connection to the upstream server. Defaults to `60000`. + `write_timeout`
*optional* | The timeout in milliseconds between two successive write operations for transmitting a request to the upstream server. Defaults to `60000`. + `read_timeout`
*optional* | The timeout in milliseconds between two successive read operations for transmitting a request to the upstream server. Defaults to `60000`. + `tags`
*optional* | An optional set of strings associated with the Service, for grouping and filtering. + `url`
*shorthand-attribute* | Shorthand attribute to set `protocol`, `host`, `port` and `path` at once. This attribute is write-only (the Admin API never "returns" the url). + +service_json: | + { + "id": "9748f662-7711-4a90-8186-dc02f10eb0f5", + "created_at": 1422386534, + "updated_at": 1422386534, + "name": "my-service", + "retries": 5, + "protocol": "http", + "host": "example.com", + "port": 80, + "path": "/some_api", + "connect_timeout": 60000, + "write_timeout": 60000, + "read_timeout": 60000, + "tags": ["user-level", "low-priority"] + } + +service_data: | + "data": [{ + "id": "4e3ad2e4-0bc4-4638-8e34-c84a417ba39b", + "created_at": 1422386534, + "updated_at": 1422386534, + "name": "my-service", + "retries": 5, + "protocol": "http", + "host": "example.com", + "port": 80, + "path": "/some_api", + "connect_timeout": 60000, + "write_timeout": 60000, + "read_timeout": 60000, + "tags": ["user-level", "low-priority"] + }, { + "id": "a5fb8d9b-a99d-40e9-9d35-72d42a62d83a", + "created_at": 1422386534, + "updated_at": 1422386534, + "name": "my-service", + "retries": 5, + "protocol": "http", + "host": "example.com", + "port": 80, + "path": "/another_api", + "connect_timeout": 60000, + "write_timeout": 60000, + "read_timeout": 60000, + "tags": ["admin", "high-priority", "critical"] + }], + +route_body: | + Attributes | Description + ---:| --- + `name`
*optional* | The name of the Route. + `protocols` | A list of the protocols this Route should allow. When set to `["https"]`, HTTP requests are answered with a request to upgrade to HTTPS. Defaults to `["http", "https"]`. + `methods`
*semi-optional* | A list of HTTP methods that match this Route. When using `http` or `https` protocols, at least one of `hosts`, `paths`, or `methods` must be set. + `hosts`
*semi-optional* | A list of domain names that match this Route. When using `http` or `https` protocols, at least one of `hosts`, `paths`, or `methods` must be set. With form-encoded, the notation is `hosts[]=example.com&hosts[]=foo.test`. With JSON, use an Array. + `paths`
*semi-optional* | A list of paths that match this Route. When using `http` or `https` protocols, at least one of `hosts`, `paths`, or `methods` must be set. With form-encoded, the notation is `paths[]=/foo&paths[]=/bar`. With JSON, use an Array. + `https_redirect_status_code` | The status code Kong responds with when all properties of a Route match except the protocol i.e. if the protocol of the request is `HTTP` instead of `HTTPS`. `Location` header is injected by Kong if the field is set to 301, 302, 307 or 308. Defaults to `426`. + `regex_priority`
*optional* | A number used to choose which route resolves a given request when several routes match it using regexes simultaneously. When two routes match the path and have the same `regex_priority`, the older one (lowest `created_at`) is used. Note that the priority for non-regex routes is different (longer non-regex routes are matched before shorter ones). Defaults to `0`. + `strip_path`
*optional* | When matching a Route via one of the `paths`, strip the matching prefix from the upstream request URL. Defaults to `true`. + `preserve_host`
*optional* | When matching a Route via one of the `hosts` domain names, use the request `Host` header in the upstream request headers. If set to `false`, the upstream `Host` header will be that of the Service's `host`. + `snis`
*semi-optional* | A list of SNIs that match this Route when using stream routing. When using `tcp` or `tls` protocols, at least one of `snis`, `sources`, or `destinations` must be set. + `sources`
*semi-optional* | A list of IP sources of incoming connections that match this Route when using stream routing. Each entry is an object with fields "ip" (optionally in CIDR range notation) and/or "port". When using `tcp` or `tls` protocols, at least one of `snis`, `sources`, or `destinations` must be set. + `destinations`
*semi-optional* | A list of IP destinations of incoming connections that match this Route when using stream routing. Each entry is an object with fields "ip" (optionally in CIDR range notation) and/or "port". When using `tcp` or `tls` protocols, at least one of `snis`, `sources`, or `destinations` must be set. + `tags`
*optional* | An optional set of strings associated with the Route, for grouping and filtering. + `service`
*optional* | The Service this Route is associated to. This is where the Route proxies traffic to. With form-encoded, the notation is `service.id=`. With JSON, use `"service":{"id":""}`. + +route_json: | + { + "id": "51e77dc2-8f3e-4afa-9d0e-0e3bbbcfd515", + "created_at": 1422386534, + "updated_at": 1422386534, + "name": "my-route", + "protocols": ["http", "https"], + "methods": ["GET", "POST"], + "hosts": ["example.com", "foo.test"], + "paths": ["/foo", "/bar"], + "https_redirect_status_code": 426, + "regex_priority": 0, + "strip_path": true, + "preserve_host": false, + "tags": ["user-level", "low-priority"], + "service": {"id":"fc73f2af-890d-4f9b-8363-af8945001f7f"} + } + +route_data: | + "data": [{ + "id": "4506673d-c825-444c-a25b-602e3c2ec16e", + "created_at": 1422386534, + "updated_at": 1422386534, + "name": "my-route", + "protocols": ["http", "https"], + "methods": ["GET", "POST"], + "hosts": ["example.com", "foo.test"], + "paths": ["/foo", "/bar"], + "https_redirect_status_code": 426, + "regex_priority": 0, + "strip_path": true, + "preserve_host": false, + "tags": ["user-level", "low-priority"], + "service": {"id":"d35165e2-d03e-461a-bdeb-dad0a112abfe"} + }, { + "id": "af8330d3-dbdc-48bd-b1be-55b98608834b", + "created_at": 1422386534, + "updated_at": 1422386534, + "name": "my-route", + "protocols": ["tcp", "tls"], + "https_redirect_status_code": 426, + "regex_priority": 0, + "strip_path": true, + "preserve_host": false, + "snis": ["foo.test", "example.com"], + "sources": [{"ip":"10.1.0.0/16", "port":1234}, {"ip":"10.2.2.2"}, {"port":9123}], + "destinations": [{"ip":"10.1.0.0/16", "port":1234}, {"ip":"10.2.2.2"}, {"port":9123}], + "tags": ["admin", "high-priority", "critical"], + "service": {"id":"a9daa3ba-8186-4a0d-96e8-00d80ce7240b"} + }], + +consumer_body: | + Attributes | Description + ---:| --- + `username`
*semi-optional* | The unique username of the consumer. You must send either this field or `custom_id` with the request. + `custom_id`
*semi-optional* | Field for storing an existing unique ID for the consumer - useful for mapping Kong with users in your existing database. You must send either this field or `username` with the request. + `tags`
*optional* | An optional set of strings associated with the Consumer, for grouping and filtering. + +consumer_json: | + { + "id": "127dfc88-ed57-45bf-b77a-a9d3a152ad31", + "created_at": 1422386534, + "username": "my-username", + "custom_id": "my-custom-id", + "tags": ["user-level", "low-priority"] + } + +consumer_data: | + "data": [{ + "id": "9aa116fd-ef4a-4efa-89bf-a0b17c4be982", + "created_at": 1422386534, + "username": "my-username", + "custom_id": "my-custom-id", + "tags": ["user-level", "low-priority"] + }, { + "id": "ba641b07-e74a-430a-ab46-94b61e5ea66b", + "created_at": 1422386534, + "username": "my-username", + "custom_id": "my-custom-id", + "tags": ["admin", "high-priority", "critical"] + }], + +plugin_body: | + Attributes | Description + ---:| --- + `name` | The name of the Plugin that's going to be added. Currently the Plugin must be installed in every Kong instance separately. + `route`
*optional* | If set, the plugin will only activate when receiving requests via the specified route. Leave unset for the plugin to activate regardless of the Route being used. Defaults to `null`. With form-encoded, the notation is `route.id=`. With JSON, use `"route":{"id":""}`. + `service`
*optional* | If set, the plugin will only activate when receiving requests via one of the routes belonging to the specified Service. Leave unset for the plugin to activate regardless of the Service being matched. Defaults to `null`. With form-encoded, the notation is `service.id=`. With JSON, use `"service":{"id":""}`. + `consumer`
*optional* | If set, the plugin will activate only for requests where the specified has been authenticated. (Note that some plugins can not be restricted to consumers this way.). Leave unset for the plugin to activate regardless of the authenticated consumer. Defaults to `null`. With form-encoded, the notation is `consumer.id=`. With JSON, use `"consumer":{"id":""}`. + `config`
*optional* | The configuration properties for the Plugin which can be found on the plugins documentation page in the [Kong Hub](https://docs.konghq.com/hub/). + `run_on` | Control on which Kong nodes this plugin will run, given a Service Mesh scenario. Accepted values are: * `first`, meaning "run on the first Kong node that is encountered by the request". On an API Getaway scenario, this is the usual operation, since there is only one Kong node in between source and destination. In a sidecar-to-sidecar Service Mesh scenario, this means running the plugin only on the Kong sidecar of the outbound connection. * `second`, meaning "run on the second node that is encountered by the request". This option is only relevant for sidecar-to-sidecar Service Mesh scenarios: this means running the plugin only on the Kong sidecar of the inbound connection. * `all` means "run on all nodes", meaning both sidecars in a sidecar-to-sidecar scenario. This is useful for tracing/logging plugins. Defaults to `"first"`. + `protocols` | A list of the request protocols that will trigger this plugin. Possible values are `"http"`, `"https"`, `"tcp"`, and `"tls"`. The default value, as well as the possible values allowed on this field, may change depending on the plugin type. For example, plugins that only work in stream mode will may only support `"tcp"` and `"tls"`. Defaults to `["http", "https"]`. + `enabled`
*optional* | Whether the plugin is applied. Defaults to `true`. + `tags`
*optional* | An optional set of strings associated with the Plugin, for grouping and filtering. + +plugin_json: | + { + "id": "ec1a1f6f-2aa4-4e58-93ff-b56368f19b27", + "name": "rate-limiting", + "created_at": 1422386534, + "route": null, + "service": null, + "consumer": null, + "config": {"hour":500, "minute":20}, + "run_on": "first", + "protocols": ["http", "https"], + "enabled": true, + "tags": ["user-level", "low-priority"] + } + +plugin_data: | + "data": [{ + "id": "a4407883-c166-43fd-80ca-3ca035b0cdb7", + "name": "rate-limiting", + "created_at": 1422386534, + "route": null, + "service": null, + "consumer": null, + "config": {"hour":500, "minute":20}, + "run_on": "first", + "protocols": ["http", "https"], + "enabled": true, + "tags": ["user-level", "low-priority"] + }, { + "id": "01c23299-839c-49a5-a6d5-8864c09184af", + "name": "rate-limiting", + "created_at": 1422386534, + "route": null, + "service": null, + "consumer": null, + "config": {"hour":500, "minute":20}, + "run_on": "first", + "protocols": ["tcp", "tls"], + "enabled": true, + "tags": ["admin", "high-priority", "critical"] + }], + +certificate_body: | + Attributes | Description + ---:| --- + `cert` | PEM-encoded public certificate of the SSL key pair. + `key` | PEM-encoded private key of the SSL key pair. + `tags`
*optional* | An optional set of strings associated with the Certificate, for grouping and filtering. + `snis`
*shorthand-attribute* | An array of zero or more hostnames to associate with this certificate as SNIs. This is a sugar parameter that will, under the hood, create an SNI object and associate it with this certificate for your convenience. To set this attribute this certificate must have a valid private key associated with it. + +certificate_json: | + { + "id": "ce44eef5-41ed-47f6-baab-f725cecf98c7", + "created_at": 1422386534, + "cert": "-----BEGIN CERTIFICATE-----...", + "key": "-----BEGIN RSA PRIVATE KEY-----...", + "tags": ["user-level", "low-priority"] + } + +certificate_data: | + "data": [{ + "id": "02621eee-8309-4bf6-b36b-a82017a5393e", + "created_at": 1422386534, + "cert": "-----BEGIN CERTIFICATE-----...", + "key": "-----BEGIN RSA PRIVATE KEY-----...", + "tags": ["user-level", "low-priority"] + }, { + "id": "66c7b5c4-4aaf-4119-af1e-ee3ad75d0af4", + "created_at": 1422386534, + "cert": "-----BEGIN CERTIFICATE-----...", + "key": "-----BEGIN RSA PRIVATE KEY-----...", + "tags": ["admin", "high-priority", "critical"] + }], + +sni_body: | + Attributes | Description + ---:| --- + `name` | The SNI name to associate with the given certificate. May contain a single wildcard in the leftmost (suffix) or rightmost (prefix) position. This can be helpful when maintaining multiple subdomains, as a single SNI configured with a wildcard name can be used to match multiple subdomains, instead of creating an SNI entity for each. Valid wildcard positions are `mydomain.*`, `*.mydomain.com`, and `*.www.mydomain.com`. Plain SNI names (no wildcard) take priority when matching, followed by prefix and then suffix. + `tags`
*optional* | An optional set of strings associated with the SNIs, for grouping and filtering. + `certificate` | The id (a UUID) of the certificate with which to associate the SNI hostname. The Certificate must have a valid private key associated with it to be used by the SNI object. With form-encoded, the notation is `certificate.id=`. With JSON, use `"certificate":{"id":""}`. + +sni_json: | + { + "id": "7fca84d6-7d37-4a74-a7b0-93e576089a41", + "name": "my-sni", + "created_at": 1422386534, + "tags": ["user-level", "low-priority"], + "certificate": {"id":"d044b7d4-3dc2-4bbc-8e9f-6b7a69416df6"} + } + +sni_data: | + "data": [{ + "id": "a9b2107f-a214-47b3-add4-46b942187924", + "name": "my-sni", + "created_at": 1422386534, + "tags": ["user-level", "low-priority"], + "certificate": {"id":"04fbeacf-a9f1-4a5d-ae4a-b0407445db3f"} + }, { + "id": "43429efd-b3a5-4048-94cb-5cc4029909bb", + "name": "my-sni", + "created_at": 1422386534, + "tags": ["admin", "high-priority", "critical"], + "certificate": {"id":"d26761d5-83a4-4f24-ac6c-cff276f2b79c"} + }], + +certificate_authority_body: | + Attributes | Description + ---:| --- + `cert` | PEM-encoded public CA certificate. + +certificate_authority_json: | + { + "id": "322dce96-d434-4e0d-9038-311b3520f0a3", + "created_at": 1566597621, + "cert": "-----BEGIN CERTIFICATE-----...", + } + +certificate_authority_data: | + "data": [{ + "id": "322dce96-d434-4e0d-9038-311b3520f0a3", + "created_at": 1566597621, + "cert": "-----BEGIN CERTIFICATE-----...", + }, { + "id": "43629afd-bda5-4248-94cb-5cc4029909bb", + "created_at": 1566597621, + "cert": "-----BEGIN CERTIFICATE-----...", + }], + +upstream_body: | + Attributes | Description + ---:| --- + `name` | This is a hostname, which must be equal to the `host` of a Service. + `hash_on`
*optional* | What to use as hashing input: `none` (resulting in a weighted-round-robin scheme with no hashing), `consumer`, `ip`, `header`, or `cookie`. Defaults to `"none"`. + `hash_fallback`
*optional* | What to use as hashing input if the primary `hash_on` does not return a hash (eg. header is missing, or no consumer identified). One of: `none`, `consumer`, `ip`, `header`, or `cookie`. Not available if `hash_on` is set to `cookie`. Defaults to `"none"`. + `hash_on_header`
*semi-optional* | The header name to take the value from as hash input. Only required when `hash_on` is set to `header`. + `hash_fallback_header`
*semi-optional* | The header name to take the value from as hash input. Only required when `hash_fallback` is set to `header`. + `hash_on_cookie`
*semi-optional* | The cookie name to take the value from as hash input. Only required when `hash_on` or `hash_fallback` is set to `cookie`. If the specified cookie is not in the request, Kong will generate a value and set the cookie in the response. + `hash_on_cookie_path`
*semi-optional* | The cookie path to set in the response headers. Only required when `hash_on` or `hash_fallback` is set to `cookie`. Defaults to `"/"`. + `slots`
*optional* | The number of slots in the loadbalancer algorithm (`10`-`65536`). Defaults to `10000`. + `healthchecks.active.https_verify_certificate`
*optional* | Whether to check the validity of the SSL certificate of the remote host when performing active health checks using HTTPS. Defaults to `true`. + `healthchecks.active.unhealthy.http_statuses`
*optional* | An array of HTTP statuses to consider a failure, indicating unhealthiness, when returned by a probe in active health checks. Defaults to `[429, 404, 500, 501, 502, 503, 504, 505]`. With form-encoded, the notation is `http_statuses[]=429&http_statuses[]=404`. With JSON, use an Array. + `healthchecks.active.unhealthy.tcp_failures`
*optional* | Number of TCP failures in active probes to consider a target unhealthy. Defaults to `0`. + `healthchecks.active.unhealthy.timeouts`
*optional* | Number of timeouts in active probes to consider a target unhealthy. Defaults to `0`. + `healthchecks.active.unhealthy.http_failures`
*optional* | Number of HTTP failures in active probes (as defined by `healthchecks.active.unhealthy.http_statuses`) to consider a target unhealthy. Defaults to `0`. + `healthchecks.active.unhealthy.interval`
*optional* | 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. Defaults to `0`. + `healthchecks.active.http_path`
*optional* | Path to use in GET HTTP request to run as a probe on active health checks. Defaults to `"/"`. + `healthchecks.active.timeout`
*optional* | Socket timeout for active health checks (in seconds). Defaults to `1`. + `healthchecks.active.healthy.http_statuses`
*optional* | An array of HTTP statuses to consider a success, indicating healthiness, when returned by a probe in active health checks. Defaults to `[200, 302]`. With form-encoded, the notation is `http_statuses[]=200&http_statuses[]=302`. With JSON, use an Array. + `healthchecks.active.healthy.interval`
*optional* | 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. Defaults to `0`. + `healthchecks.active.healthy.successes`
*optional* | Number of successes in active probes (as defined by `healthchecks.active.healthy.http_statuses`) to consider a target healthy. Defaults to `0`. + `healthchecks.active.https_sni`
*optional* | 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. + `healthchecks.active.concurrency`
*optional* | Number of targets to check concurrently in active health checks. Defaults to `10`. + `healthchecks.active.type`
*optional* | Whether to perform active health checks using HTTP or HTTPS, or just attempt a TCP connection. Possible values are `tcp`, `http` or `https`. Defaults to `"http"`. + `healthchecks.passive.unhealthy.http_failures`
*optional* | 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. Defaults to `0`. + `healthchecks.passive.unhealthy.http_statuses`
*optional* | An array of HTTP statuses which represent unhealthiness when produced by proxied traffic, as observed by passive health checks. Defaults to `[429, 500, 503]`. With form-encoded, the notation is `http_statuses[]=429&http_statuses[]=500`. With JSON, use an Array. + `healthchecks.passive.unhealthy.tcp_failures`
*optional* | Number of TCP failures in proxied traffic to consider a target unhealthy, as observed by passive health checks. Defaults to `0`. + `healthchecks.passive.unhealthy.timeouts`
*optional* | Number of timeouts in proxied traffic to consider a target unhealthy, as observed by passive health checks. Defaults to `0`. + `healthchecks.passive.type`
*optional* | Whether to perform passive health checks interpreting HTTP/HTTPS statuses, or just check for TCP connection success. Possible values are `tcp`, `http` or `https` (in passive checks, `http` and `https` options are equivalent.). Defaults to `"http"`. + `healthchecks.passive.healthy.successes`
*optional* | 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. Defaults to `0`. + `healthchecks.passive.healthy.http_statuses`
*optional* | An array of HTTP statuses which represent healthiness when produced by proxied traffic, as observed by passive health checks. Defaults to `[200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 300, 301, 302, 303, 304, 305, 306, 307, 308]`. With form-encoded, the notation is `http_statuses[]=200&http_statuses[]=201`. With JSON, use an Array. + `tags`
*optional* | An optional set of strings associated with the Upstream, for grouping and filtering. + +upstream_json: | + { + "id": "91020192-062d-416f-a275-9addeeaffaf2", + "created_at": 1422386534, + "name": "my-upstream", + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/", + "slots": 10000, + "healthchecks": { + "active": { + "https_verify_certificate": true, + "unhealthy": { + "http_statuses": [429, 404, 500, 501, 502, 503, 504, 505], + "tcp_failures": 0, + "timeouts": 0, + "http_failures": 0, + "interval": 0 + }, + "http_path": "/", + "timeout": 1, + "healthy": { + "http_statuses": [200, 302], + "interval": 0, + "successes": 0 + }, + "https_sni": "example.com", + "concurrency": 10, + "type": "http" + }, + "passive": { + "unhealthy": { + "http_failures": 0, + "http_statuses": [429, 500, 503], + "tcp_failures": 0, + "timeouts": 0 + }, + "type": "http", + "healthy": { + "successes": 0, + "http_statuses": [200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 300, 301, 302, 303, 304, 305, 306, 307, 308] + } + } + }, + "tags": ["user-level", "low-priority"] + } + +upstream_data: | + "data": [{ + "id": "a2e013e8-7623-4494-a347-6d29108ff68b", + "created_at": 1422386534, + "name": "my-upstream", + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/", + "slots": 10000, + "healthchecks": { + "active": { + "https_verify_certificate": true, + "unhealthy": { + "http_statuses": [429, 404, 500, 501, 502, 503, 504, 505], + "tcp_failures": 0, + "timeouts": 0, + "http_failures": 0, + "interval": 0 + }, + "http_path": "/", + "timeout": 1, + "healthy": { + "http_statuses": [200, 302], + "interval": 0, + "successes": 0 + }, + "https_sni": "example.com", + "concurrency": 10, + "type": "http" + }, + "passive": { + "unhealthy": { + "http_failures": 0, + "http_statuses": [429, 500, 503], + "tcp_failures": 0, + "timeouts": 0 + }, + "type": "http", + "healthy": { + "successes": 0, + "http_statuses": [200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 300, 301, 302, 303, 304, 305, 306, 307, 308] + } + } + }, + "tags": ["user-level", "low-priority"] + }, { + "id": "147f5ef0-1ed6-4711-b77f-489262f8bff7", + "created_at": 1422386534, + "name": "my-upstream", + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/", + "slots": 10000, + "healthchecks": { + "active": { + "https_verify_certificate": true, + "unhealthy": { + "http_statuses": [429, 404, 500, 501, 502, 503, 504, 505], + "tcp_failures": 0, + "timeouts": 0, + "http_failures": 0, + "interval": 0 + }, + "http_path": "/", + "timeout": 1, + "healthy": { + "http_statuses": [200, 302], + "interval": 0, + "successes": 0 + }, + "https_sni": "example.com", + "concurrency": 10, + "type": "http" + }, + "passive": { + "unhealthy": { + "http_failures": 0, + "http_statuses": [429, 500, 503], + "tcp_failures": 0, + "timeouts": 0 + }, + "type": "http", + "healthy": { + "successes": 0, + "http_statuses": [200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 300, 301, 302, 303, 304, 305, 306, 307, 308] + } + } + }, + "tags": ["admin", "high-priority", "critical"] + }], + +target_body: | + Attributes | Description + ---:| --- + `target` | The target address (ip or hostname) and port. If the hostname resolves to an SRV record, the `port` value will be overridden by the value from the DNS record. + `weight`
*optional* | The weight this target gets within the upstream loadbalancer (`0`-`1000`). If the hostname resolves to an SRV record, the `weight` value will be overridden by the value from the DNS record. Defaults to `100`. + `tags`
*optional* | An optional set of strings associated with the Target, for grouping and filtering. + +target_json: | + { + "id": "a3ad71a8-6685-4b03-a101-980a953544f6", + "created_at": 1422386534, + "upstream": {"id":"b87eb55d-69a1-41d2-8653-8d706eecefc0"}, + "target": "example.com:8000", + "weight": 100, + "tags": ["user-level", "low-priority"] + } + +target_data: | + "data": [{ + "id": "4e8d95d4-40f2-4818-adcb-30e00c349618", + "created_at": 1422386534, + "upstream": {"id":"58c8ccbb-eafb-4566-991f-2ed4f678fa70"}, + "target": "example.com:8000", + "weight": 100, + "tags": ["user-level", "low-priority"] + }, { + "id": "ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6", + "created_at": 1422386534, + "upstream": {"id":"4fe14415-73d5-4f00-9fbc-c72a0fccfcb2"}, + "target": "example.com:8000", + "weight": 100, + "tags": ["admin", "high-priority", "critical"] + }], + + +--- + +Kong comes with an **internal** RESTful Admin API for administration purposes. +Requests to the Admin API can be sent to any node in the cluster, and Kong will +keep the configuration consistent across all nodes. + +- `8001` is the default port on which the Admin API listens. +- `8444` is the default port for HTTPS traffic to the Admin API. + +This API is designed for internal use and provides full control over Kong, so +care should be taken when setting up Kong environments to avoid undue public +exposure of this API. See [this document][secure-admin-api] for a discussion +of methods to secure the Admin API. + +## Supported Content Types + +The Admin API accepts 2 content types on every endpoint: + +- **application/x-www-form-urlencoded** + +Simple enough for basic request bodies, you will probably use it most of the time. +Note that when sending nested values, Kong expects nested objects to be referenced +with dotted keys. Example: + +``` +config.limit=10&config.period=seconds +``` + +Arrays and sets can be specified in various ways: + +1. Sending same parameter multiple times: + ``` + hosts=example.com&hosts=example.org + ``` +2. Using array notation: + ``` + hosts[1]=example.com&hosts[2]=example.org + ``` + or + ``` + hosts[]=example.com&hosts[]=example.org + ``` + Array and object notation can also be mixed: + + ``` + config.hosts[1]=example.com&config.hosts[2]=example.org + ``` + + +- **application/json** + +Handy for complex bodies (ex: complex plugin configuration), in that case simply send +a JSON representation of the data you want to send. Example: + +```json +{ + "config": { + "limit": 10, + "period": "seconds" + } +} +``` + +JSON arrays can be specified as well: + +```json +{ + "config": { + "limit": 10, + "period": "seconds", + "hosts": [ "example.com", "example.org" ] + } +} +``` + +--- + +## Information Routes + + + +### Retrieve Node Information + +Retrieve generic details about a node. + +
/
+ +*Response* + +``` +HTTP 200 OK +``` + +```json +{ + "hostname": "", + "node_id": "6a72192c-a3a1-4c8d-95c6-efabae9fb969", + "lua_version": "LuaJIT 2.1.0-beta3", + "plugins": { + "available_on_server": [ + ... + ], + "enabled_in_cluster": [ + ... + ] + }, + "configuration" : { + ... + }, + "tagline": "Welcome to Kong", + "version": "0.14.0" +} +``` + +* `node_id`: A UUID representing the running Kong node. This UUID + is randomly generated when Kong starts, so the node will have a + different `node_id` each time it is restarted. +* `available_on_server`: Names of plugins that are installed on the node. +* `enabled_in_cluster`: Names of plugins that are enabled/configured. + That is, the plugins configurations currently in the datastore shared + by all Kong nodes. + + +--- + +### Retrieve Node Status + +Retrieve usage information about a node, with some basic information +about the connections being processed by the underlying nginx process, +the status of the database connection, and node's memory usage. + +If you want to monitor the Kong process, since Kong is built on top +of nginx, every existing nginx monitoring tool or agent can be used. + + +
/status
+ +*Response* + +``` +HTTP 200 OK +``` + +```json +{ + "database": { + "reachable": true + }, + "memory": { + "workers_lua_vms": [{ + "http_allocated_gc": "0.02 MiB", + "pid": 18477 + }, { + "http_allocated_gc": "0.02 MiB", + "pid": 18478 + }], + "lua_shared_dicts": { + "kong": { + "allocated_slabs": "0.04 MiB", + "capacity": "5.00 MiB" + }, + "kong_db_cache": { + "allocated_slabs": "0.80 MiB", + "capacity": "128.00 MiB" + }, + } + }, + "server": { + "total_requests": 3, + "connections_active": 1, + "connections_accepted": 1, + "connections_handled": 1, + "connections_reading": 0, + "connections_writing": 1, + "connections_waiting": 0 + } +} +``` + +* `memory`: Metrics about the memory usage. + * `workers_lua_vms`: An array with all workers of the Kong node, where each + entry contains: + * `http_allocated_gc`: HTTP submodule's Lua virtual machine's memory + usage information, as reported by `collectgarbage("count")`, for every + active worker, i.e. a worker that received a proxy call in the last 10 + seconds. + * `pid`: worker's process identification number. + * `lua_shared_dicts`: An array of information about dictionaries that are + shared with all workers in a Kong node, where each array node contains how + much memory is dedicated for the specific shared dictionary (`capacity`) + and how much of said memory is in use (`allocated_slabs`). + These shared dictionaries have least recent used (LRU) eviction + capabilities, so a full dictionary, where `allocated_slabs == capacity`, + will work properly. However for some dictionaries, e.g. cache HIT/MISS + shared dictionaries, increasing their size can be beneficial for the + overall performance of a Kong node. + * The memory usage unit and precision can be changed using the querystring + arguments `unit` and `scale`: + * `unit`: one of `b/B`, `k/K`, `m/M`, `g/G`, which will return results + in bytes, kibibytes, mebibytes, or gibibytes, respectively. When + "bytes" are requested, the memory values in the response will have a + number type instead of string. Defaults to `m`. + * `scale`: the number of digits to the right of the decimal points when + values are given in human-readable memory strings (unit other than + "bytes"). Defaults to `2`. + You can get the shared dictionaries memory usage in kibibytes with 4 + digits of precision by doing: `GET /status?unit=k&scale=4` +* `server`: Metrics about the nginx HTTP/S server. + * `total_requests`: The total number of client requests. + * `connections_active`: The current number of active client + connections including Waiting connections. + * `connections_accepted`: The total number of accepted client + connections. + * `connections_handled`: The total number of handled connections. + Generally, the parameter value is the same as accepts unless + some resource limits have been reached. + * `connections_reading`: The current number of connections + where Kong is reading the request header. + * `connections_writing`: The current number of connections + where nginx is writing the response back to the client. + * `connections_waiting`: The current number of idle client + connections waiting for a request. +* `database`: Metrics about the database. + * `reachable`: A boolean value reflecting the state of the + database connection. Please note that this flag **does not** + reflect the health of the database itself. + + +--- + +## Tags + +Tags are strings associated to entities in Kong. Each tag must be composed of one or more +alphanumeric characters, `_`, `-`, `.` or `~`. + +Most core entities can be *tagged* via their `tags` attribute, upon creation or edition. + +Tags can be used to filter core entities as well, via the `?tags` querystring parameter. + +For example: if you normally get a list of all the Services by doing: + +``` +GET /services +``` + +You can get the list of all the Services tagged `example` by doing: + +``` +GET /services?tags=example +``` + +Similarly, if you want to filter Services so that you only get the ones tagged `example` *and* +`admin`, you can do that like so: + +``` +GET /services?tags=example,admin +``` + +Finally, if you wanted to filter the Services tagged `example` *or* `admin`, you could use: + +``` +GET /services?tags=example/admin +``` + +Some notes: + +* A maximum of 5 tags can be queried simultaneously in a single request with `,` or `/` +* Mixing operators is not supported: if you try to mix `,` with `/` in the same querystring, + you will receive an error. +* You may need to quote and/or escape some characters when using them from the + command line. +* Filtering by `tags` is not supported in foreign key relationship endpoints. For example, + the `tags` parameter will be ignored in a request such as `GET /services/foo/routes?tags=a,b` +* `offset` parameters are not guaranteed to work if the `tags` parameter is altered or removed + + +### List All Tags + +Returns a paginated list of all the tags in the system. + +The list of entities will not be restricted to a single entity type: all the +entities tagged with tags will be present on this list. + +If an entity is tagged with more than one tag, the `entity_id` for that entity +will appear more than once in the resulting list. Similarly, if several entities +have been tagged with the same tag, the tag will appear in several items of this list. + + +
/tags
+ +*Response* + +``` +HTTP 200 OK +``` + +``` json +{ + { + "data": [ + { "entity_name": "services", + "entity_id": "acf60b10-125c-4c1a-bffe-6ed55daefba4", + "tag": "s1", + }, + { "entity_name": "services", + "entity_id": "acf60b10-125c-4c1a-bffe-6ed55daefba4", + "tag": "s2", + }, + { "entity_name": "routes", + "entity_id": "60631e85-ba6d-4c59-bd28-e36dd90f6000", + "tag": "s1", + }, + ... + ], + "offset" = "c47139f3-d780-483d-8a97-17e9adc5a7ab", + "next" = "/tags?offset=c47139f3-d780-483d-8a97-17e9adc5a7ab", + } +} +``` + + +--- + +### List Entity Ids by Tag + +Returns the entities that have been tagged with the specified tag. + +The list of entities will not be restricted to a single entity type: all the +entities tagged with tags will be present on this list. + + +
/tags/:tags
+ +*Response* + +``` +HTTP 200 OK +``` + +``` json +{ + { + "data": [ + { "entity_name": "services", + "entity_id": "c87440e1-0496-420b-b06f-dac59544bb6c", + "tag": "example", + }, + { "entity_name": "routes", + "entity_id": "8a99e4b1-d268-446b-ab8b-cd25cff129b1", + "tag": "example", + }, + ... + ], + "offset" = "1fb491c4-f4a7-4bca-aeba-7f3bcee4d2f9", + "next" = "/tags/example?offset=1fb491c4-f4a7-4bca-aeba-7f3bcee4d2f9", + } +} +``` + + +--- + +## Service Object + +Service entities, as the name implies, are abstractions of each of your own +upstream services. Examples of Services would be a data transformation +microservice, a billing API, etc. + +The main attribute of a Service is its URL (where Kong should proxy traffic +to), which can be set as a single string or by specifying its `protocol`, +`host`, `port` and `path` individually. + +Services are associated to Routes (a Service can have many Routes associated +with it). Routes are entry-points in Kong and define rules to match client +requests. Once a Route is matched, Kong proxies the request to its associated +Service. See the [Proxy Reference][proxy-reference] for a detailed explanation +of how Kong proxies traffic. + +Services can be both [tagged and filtered by tags](#tags). + + +```json +{{ page.service_json }} +``` + +### Add Service + +##### Create Service + +
/services
+ + +*Request Body* + +{{ page.service_body }} + + +*Response* + +``` +HTTP 201 Created +``` + +```json +{{ page.service_json }} +``` + + +--- + +### List Services + +##### List All Services + +
/services
+ + +*Response* + +``` +HTTP 200 OK +``` + +```json +{ +{{ page.service_data }} + "next": "http://localhost:8001/services?offset=6378122c-a0a1-438d-a5c6-efabae9fb969" +} +``` + + +--- + +### Retrieve Service + +##### Retrieve Service + +
/services/{name or id}
+ +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the Service to retrieve. + + +##### Retrieve Service Associated to a Specific Route + +
/routes/{route name or id}/service
+ +Attributes | Description +---:| --- +`route name or id`
**required** | The unique identifier **or** the name of the Route associated to the Service to be retrieved. + + +##### Retrieve Service Associated to a Specific Plugin + +
/plugins/{plugin id}/service
+ +Attributes | Description +---:| --- +`plugin id`
**required** | The unique identifier of the Plugin associated to the Service to be retrieved. + + +*Response* + +``` +HTTP 200 OK +``` + +```json +{{ page.service_json }} +``` + + +--- + +### Update Service + +##### Update Service + +
/services/{name or id}
+ +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the Service to update. + + +##### Update Service Associated to a Specific Route + +
/routes/{route name or id}/service
+ +Attributes | Description +---:| --- +`route name or id`
**required** | The unique identifier **or** the name of the Route associated to the Service to be updated. + + +##### Update Service Associated to a Specific Plugin + +
/plugins/{plugin id}/service
+ +Attributes | Description +---:| --- +`plugin id`
**required** | The unique identifier of the Plugin associated to the Service to be updated. + + +*Request Body* + +{{ page.service_body }} + + +*Response* + +``` +HTTP 200 OK +``` + +```json +{{ page.service_json }} +``` + + +--- + +### Update Or Create Service + +##### Create Or Update Service + +
/services/{name or id}
+ +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the Service to create or update. + + +##### Create Or Update Service Associated to a Specific Route + +
/routes/{route name or id}/service
+ +Attributes | Description +---:| --- +`route name or id`
**required** | The unique identifier **or** the name of the Route associated to the Service to be created or updated. + + +##### Create Or Update Service Associated to a Specific Plugin + +
/plugins/{plugin id}/service
+ +Attributes | Description +---:| --- +`plugin id`
**required** | The unique identifier of the Plugin associated to the Service to be created or updated. + + +*Request Body* + +{{ page.service_body }} + + +Inserts (or replaces) the Service under the requested resource with the +definition specified in the body. The Service will be identified via the `name +or id` attribute. + +When the `name or id` attribute has the structure of a UUID, the Service being +inserted/replaced will be identified by its `id`. Otherwise it will be +identified by its `name`. + +When creating a new Service without specifying `id` (neither in the URL nor in +the body), then it will be auto-generated. + +Notice that specifying a `name` in the URL and a different one in the request +body is not allowed. + + +*Response* + +``` +HTTP 201 Created or HTTP 200 OK +``` + +See POST and PATCH responses. + + +--- + +### Delete Service + +##### Delete Service + +
/services/{name or id}
+ +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the Service to delete. + + +##### Delete Service Associated to a Specific Route + +
/routes/{route name or id}/service
+ +Attributes | Description +---:| --- +`route name or id`
**required** | The unique identifier **or** the name of the Route associated to the Service to be deleted. + + +*Response* + +``` +HTTP 204 No Content +``` + + +--- + +## Route Object + +Route entities define rules to match client requests. Each Route is +associated with a Service, and a Service may have multiple Routes associated to +it. Every request matching a given Route will be proxied to its associated +Service. + +The combination of Routes and Services (and the separation of concerns between +them) offers a powerful routing mechanism with which it is possible to define +fine-grained entry-points in Kong leading to different upstream services of +your infrastructure. + +Routes can be both [tagged and filtered by tags](#tags). + + +```json +{{ page.route_json }} +``` + +### Add Route + +##### Create Route + +
/routes
+ + +##### Create Route Associated to a Specific Service + +
/services/{service name or id}/routes
+ +Attributes | Description +---:| --- +`service name or id`
**required** | The unique identifier or the `name` attribute of the Service that should be associated to the newly-created Route. + + +*Request Body* + +{{ page.route_body }} + + +*Response* + +``` +HTTP 201 Created +``` + +```json +{{ page.route_json }} +``` + + +--- + +### List Routes + +##### List All Routes + +
/routes
+ + +##### List Routes Associated to a Specific Service + +
/services/{service name or id}/routes
+ +Attributes | Description +---:| --- +`service name or id`
**required** | The unique identifier or the `name` attribute of the Service whose Routes are to be retrieved. When using this endpoint, only Routes associated to the specified Service will be listed. + + +*Response* + +``` +HTTP 200 OK +``` + +```json +{ +{{ page.route_data }} + "next": "http://localhost:8001/routes?offset=6378122c-a0a1-438d-a5c6-efabae9fb969" +} +``` + + +--- + +### Retrieve Route + +##### Retrieve Route + +
/routes/{name or id}
+ +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the Route to retrieve. + + +##### Retrieve Route Associated to a Specific Plugin + +
/plugins/{plugin id}/route
+ +Attributes | Description +---:| --- +`plugin id`
**required** | The unique identifier of the Plugin associated to the Route to be retrieved. + + +*Response* + +``` +HTTP 200 OK +``` + +```json +{{ page.route_json }} +``` + + +--- + +### Update Route + +##### Update Route + +
/routes/{name or id}
+ +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the Route to update. + + +##### Update Route Associated to a Specific Plugin + +
/plugins/{plugin id}/route
+ +Attributes | Description +---:| --- +`plugin id`
**required** | The unique identifier of the Plugin associated to the Route to be updated. + + +*Request Body* + +{{ page.route_body }} + + +*Response* + +``` +HTTP 200 OK +``` + +```json +{{ page.route_json }} +``` + + +--- + +### Update Or Create Route + +##### Create Or Update Route + +
/routes/{name or id}
+ +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the Route to create or update. + + +##### Create Or Update Route Associated to a Specific Plugin + +
/plugins/{plugin id}/route
+ +Attributes | Description +---:| --- +`plugin id`
**required** | The unique identifier of the Plugin associated to the Route to be created or updated. + + +*Request Body* + +{{ page.route_body }} + + +Inserts (or replaces) the Route under the requested resource with the +definition specified in the body. The Route will be identified via the `name +or id` attribute. + +When the `name or id` attribute has the structure of a UUID, the Route being +inserted/replaced will be identified by its `id`. Otherwise it will be +identified by its `name`. + +When creating a new Route without specifying `id` (neither in the URL nor in +the body), then it will be auto-generated. + +Notice that specifying a `name` in the URL and a different one in the request +body is not allowed. + + +*Response* + +``` +HTTP 201 Created or HTTP 200 OK +``` + +See POST and PATCH responses. + + +--- + +### Delete Route + +##### Delete Route + +
/routes/{name or id}
+ +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the Route to delete. + + +*Response* + +``` +HTTP 204 No Content +``` + + +--- + +## Consumer Object + +The Consumer object represents a consumer - or a user - of a Service. You can +either rely on Kong as the primary datastore, or you can map the consumer list +with your database to keep consistency between Kong and your existing primary +datastore. + +Consumers can be both [tagged and filtered by tags](#tags). + + +```json +{{ page.consumer_json }} +``` + +### Add Consumer + +##### Create Consumer + +
/consumers
+ + +*Request Body* + +{{ page.consumer_body }} + + +*Response* + +``` +HTTP 201 Created +``` + +```json +{{ page.consumer_json }} +``` + + +--- + +### List Consumers + +##### List All Consumers + +
/consumers
+ + +*Response* + +``` +HTTP 200 OK +``` + +```json +{ +{{ page.consumer_data }} + "next": "http://localhost:8001/consumers?offset=6378122c-a0a1-438d-a5c6-efabae9fb969" +} +``` + + +--- + +### Retrieve Consumer + +##### Retrieve Consumer + +
/consumers/{username or id}
+ +Attributes | Description +---:| --- +`username or id`
**required** | The unique identifier **or** the username of the Consumer to retrieve. + + +##### Retrieve Consumer Associated to a Specific Plugin + +
/plugins/{plugin id}/consumer
+ +Attributes | Description +---:| --- +`plugin id`
**required** | The unique identifier of the Plugin associated to the Consumer to be retrieved. + + +*Response* + +``` +HTTP 200 OK +``` + +```json +{{ page.consumer_json }} +``` + + +--- + +### Update Consumer + +##### Update Consumer + +
/consumers/{username or id}
+ +Attributes | Description +---:| --- +`username or id`
**required** | The unique identifier **or** the username of the Consumer to update. + + +##### Update Consumer Associated to a Specific Plugin + +
/plugins/{plugin id}/consumer
+ +Attributes | Description +---:| --- +`plugin id`
**required** | The unique identifier of the Plugin associated to the Consumer to be updated. + + +*Request Body* + +{{ page.consumer_body }} + + +*Response* + +``` +HTTP 200 OK +``` + +```json +{{ page.consumer_json }} +``` + + +--- + +### Update Or Create Consumer + +##### Create Or Update Consumer + +
/consumers/{username or id}
+ +Attributes | Description +---:| --- +`username or id`
**required** | The unique identifier **or** the username of the Consumer to create or update. + + +##### Create Or Update Consumer Associated to a Specific Plugin + +
/plugins/{plugin id}/consumer
+ +Attributes | Description +---:| --- +`plugin id`
**required** | The unique identifier of the Plugin associated to the Consumer to be created or updated. + + +*Request Body* + +{{ page.consumer_body }} + + +Inserts (or replaces) the Consumer under the requested resource with the +definition specified in the body. The Consumer will be identified via the `username +or id` attribute. + +When the `username or id` attribute has the structure of a UUID, the Consumer being +inserted/replaced will be identified by its `id`. Otherwise it will be +identified by its `username`. + +When creating a new Consumer without specifying `id` (neither in the URL nor in +the body), then it will be auto-generated. + +Notice that specifying a `username` in the URL and a different one in the request +body is not allowed. + + +*Response* + +``` +HTTP 201 Created or HTTP 200 OK +``` + +See POST and PATCH responses. + + +--- + +### Delete Consumer + +##### Delete Consumer + +
/consumers/{username or id}
+ +Attributes | Description +---:| --- +`username or id`
**required** | The unique identifier **or** the username of the Consumer to delete. + + +*Response* + +``` +HTTP 204 No Content +``` + + +--- + +## Plugin Object + +A Plugin entity represents a plugin configuration that will be executed during +the HTTP request/response lifecycle. It is how you can add functionalities +to Services that run behind Kong, like Authentication or Rate Limiting for +example. You can find more information about how to install and what values +each plugin takes by visiting the [Kong Hub](https://docs.konghq.com/hub/). + +When adding a Plugin Configuration to a Service, every request made by a client to +that Service will run said Plugin. If a Plugin needs to be tuned to different +values for some specific Consumers, you can do so by creating a separate +plugin instance that specifies both the Service and the Consumer, through the +`service` and `consumer` fields. + +Plugins can be both [tagged and filtered by tags](#tags). + + +```json +{{ page.plugin_json }} +``` + +See the [Precedence](#precedence) section below for more details. + +#### Precedence + +A plugin will always be run once and only once per request. But the +configuration with which it will run depends on the entities it has been +configured for. + +Plugins can be configured for various entities, combination of entities, or +even globally. This is useful, for example, when you wish to configure a plugin +a certain way for most requests, but make _authenticated requests_ behave +slightly differently. + +Therefore, there exists an order of precedence for running a plugin when it has +been applied to different entities with different configurations. The rule of +thumb is: the more specific a plugin is with regards to how many entities it +has been configured on, the higher its priority. + +The complete order of precedence when a plugin has been configured multiple +times is: + +1. Plugins configured on a combination of: a Route, a Service, and a Consumer. + (Consumer means the request must be authenticated). +2. Plugins configured on a combination of a Route and a Consumer. + (Consumer means the request must be authenticated). +3. Plugins configured on a combination of a Service and a Consumer. + (Consumer means the request must be authenticated). +4. Plugins configured on a combination of a Route and a Service. +5. Plugins configured on a Consumer. + (Consumer means the request must be authenticated). +6. Plugins configured on a Route. +7. Plugins configured on a Service. +8. Plugins configured to run globally. + +**Example**: if the `rate-limiting` plugin is applied twice (with different +configurations): for a Service (Plugin config A), and for a Consumer (Plugin +config B), then requests authenticating this Consumer will run Plugin config B +and ignore A. However, requests that do not authenticate this Consumer will +fallback to running Plugin config A. Note that if config B is disabled +(its `enabled` flag is set to `false`), config A will apply to requests that +would have otherwise matched config B. + + +### Add Plugin + +##### Create Plugin + +
/plugins
+ + +##### Create Plugin Associated to a Specific Route + +
/routes/{route id}/plugins
+ +Attributes | Description +---:| --- +`route id`
**required** | The unique identifier of the Route that should be associated to the newly-created Plugin. + + +##### Create Plugin Associated to a Specific Service + +
/services/{service id}/plugins
+ +Attributes | Description +---:| --- +`service id`
**required** | The unique identifier of the Service that should be associated to the newly-created Plugin. + + +##### Create Plugin Associated to a Specific Consumer + +
/consumers/{consumer id}/plugins
+ +Attributes | Description +---:| --- +`consumer id`
**required** | The unique identifier of the Consumer that should be associated to the newly-created Plugin. + + +*Request Body* + +{{ page.plugin_body }} + + +*Response* + +``` +HTTP 201 Created +``` + +```json +{{ page.plugin_json }} +``` + + +--- + +### List Plugins + +##### List All Plugins + +
/plugins
+ + +##### List Plugins Associated to a Specific Route + +
/routes/{route id}/plugins
+ +Attributes | Description +---:| --- +`route id`
**required** | The unique identifier of the Route whose Plugins are to be retrieved. When using this endpoint, only Plugins associated to the specified Route will be listed. + + +##### List Plugins Associated to a Specific Service + +
/services/{service id}/plugins
+ +Attributes | Description +---:| --- +`service id`
**required** | The unique identifier of the Service whose Plugins are to be retrieved. When using this endpoint, only Plugins associated to the specified Service will be listed. + + +##### List Plugins Associated to a Specific Consumer + +
/consumers/{consumer id}/plugins
+ +Attributes | Description +---:| --- +`consumer id`
**required** | The unique identifier of the Consumer whose Plugins are to be retrieved. When using this endpoint, only Plugins associated to the specified Consumer will be listed. + + +*Response* + +``` +HTTP 200 OK +``` + +```json +{ +{{ page.plugin_data }} + "next": "http://localhost:8001/plugins?offset=6378122c-a0a1-438d-a5c6-efabae9fb969" +} +``` + + +--- + +### Retrieve Plugin + +##### Retrieve Plugin + +
/plugins/{plugin id}
+ +Attributes | Description +---:| --- +`plugin id`
**required** | The unique identifier of the Plugin to retrieve. + + +*Response* + +``` +HTTP 200 OK +``` + +```json +{{ page.plugin_json }} +``` + + +--- + +### Update Plugin + +##### Update Plugin + +
/plugins/{plugin id}
+ +Attributes | Description +---:| --- +`plugin id`
**required** | The unique identifier of the Plugin to update. + + +*Request Body* + +{{ page.plugin_body }} + + +*Response* + +``` +HTTP 200 OK +``` + +```json +{{ page.plugin_json }} +``` + + +--- + +### Update Or Create Plugin + +##### Create Or Update Plugin + +
/plugins/{plugin id}
+ +Attributes | Description +---:| --- +`plugin id`
**required** | The unique identifier of the Plugin to create or update. + + +*Request Body* + +{{ page.plugin_body }} + + +Inserts (or replaces) the Plugin under the requested resource with the +definition specified in the body. The Plugin will be identified via the `name +or id` attribute. + +When the `name or id` attribute has the structure of a UUID, the Plugin being +inserted/replaced will be identified by its `id`. Otherwise it will be +identified by its `name`. + +When creating a new Plugin without specifying `id` (neither in the URL nor in +the body), then it will be auto-generated. + +Notice that specifying a `name` in the URL and a different one in the request +body is not allowed. + + +*Response* + +``` +HTTP 201 Created or HTTP 200 OK +``` + +See POST and PATCH responses. + + +--- + +### Delete Plugin + +##### Delete Plugin + +
/plugins/{plugin id}
+ +Attributes | Description +---:| --- +`plugin id`
**required** | The unique identifier of the Plugin to delete. + + +*Response* + +``` +HTTP 204 No Content +``` + + +--- + +### Retrieve Enabled Plugins + +Retrieve a list of all installed plugins on the Kong node. + +
/plugins/enabled
+ +*Response* + +``` +HTTP 200 OK +``` + +```json +{ + "enabled_plugins": [ + "jwt", + "acl", + "cors", + "oauth2", + "tcp-log", + "udp-log", + "file-log", + "http-log", + "key-auth", + "hmac-auth", + "basic-auth", + "ip-restriction", + "request-transformer", + "response-transformer", + "request-size-limiting", + "rate-limiting", + "response-ratelimiting", + "aws-lambda", + "bot-detection", + "correlation-id", + "datadog", + "galileo", + "ldap-auth", + "loggly", + "statsd", + "syslog" + ] +} +``` + + +--- + +### Retrieve Plugin Schema + +Retrieve the schema of a plugin's configuration. This is useful to +understand what fields a plugin accepts, and can be used for building +third-party integrations to the Kong's plugin system. + + +
/plugins/schema/{plugin name}
+ +*Response* + +``` +HTTP 200 OK +``` + +```json +{ + "fields": { + "hide_credentials": { + "default": false, + "type": "boolean" + }, + "key_names": { + "default": "function", + "required": true, + "type": "array" + } + } +} +``` + + +--- + +## Certificate Object + +A certificate object represents a public certificate, and can be optionally paired with the +corresponding private key. These objects are used by Kong to handle SSL/TLS termination for +encrypted requests, or for use as a trusted CA store when validating peer certificate of +client/service. Certificates are optionally associated with SNI objects to +tie a cert/key pair to one or more hostnames. + +Certificates can be both [tagged and filtered by tags](#tags). + + +```json +{{ page.certificate_json }} +``` + +### Add Certificate + +##### Create Certificate + +
/certificates
+ + +*Request Body* + +{{ page.certificate_body }} + + +*Response* + +``` +HTTP 201 Created +``` + +```json +{{ page.certificate_json }} +``` + + +--- + +### List Certificates + +##### List All Certificates + +
/certificates
+ + +*Response* + +``` +HTTP 200 OK +``` + +```json +{ +{{ page.certificate_data }} + "next": "http://localhost:8001/certificates?offset=6378122c-a0a1-438d-a5c6-efabae9fb969" +} +``` + + +--- + +### Retrieve Certificate + +##### Retrieve Certificate + +
/certificates/{certificate id}
+ +Attributes | Description +---:| --- +`certificate id`
**required** | The unique identifier of the Certificate to retrieve. + + +*Response* + +``` +HTTP 200 OK +``` + +```json +{{ page.certificate_json }} +``` + + +--- + +### Update Certificate + +##### Update Certificate + +
/certificates/{certificate id}
+ +Attributes | Description +---:| --- +`certificate id`
**required** | The unique identifier of the Certificate to update. + + +*Request Body* + +{{ page.certificate_body }} + + +*Response* + +``` +HTTP 200 OK +``` + +```json +{{ page.certificate_json }} +``` + + +--- + +### Update Or Create Certificate + +##### Create Or Update Certificate + +
/certificates/{certificate id}
+ +Attributes | Description +---:| --- +`certificate id`
**required** | The unique identifier of the Certificate to create or update. + + +*Request Body* + +{{ page.certificate_body }} + + +Inserts (or replaces) the Certificate under the requested resource with the +definition specified in the body. The Certificate will be identified via the `name +or id` attribute. + +When the `name or id` attribute has the structure of a UUID, the Certificate being +inserted/replaced will be identified by its `id`. Otherwise it will be +identified by its `name`. + +When creating a new Certificate without specifying `id` (neither in the URL nor in +the body), then it will be auto-generated. + +Notice that specifying a `name` in the URL and a different one in the request +body is not allowed. + + +*Response* + +``` +HTTP 201 Created or HTTP 200 OK +``` + +See POST and PATCH responses. + + +--- + +### Delete Certificate + +##### Delete Certificate + +
/certificates/{certificate id}
+ +Attributes | Description +---:| --- +`certificate id`
**required** | The unique identifier of the Certificate to delete. + + +*Response* + +``` +HTTP 204 No Content +``` + + +--- + +## SNI Object + +An SNI object represents a many-to-one mapping of hostnames to a certificate. +That is, a certificate object can have many hostnames associated with it; when +Kong receives an SSL request, it uses the SNI field in the Client Hello to +lookup the certificate object based on the SNI associated with the certificate. + +SNIs can be both [tagged and filtered by tags](#tags). + + +```json +{{ page.sni_json }} +``` + +### Add SNI + +##### Create SNI + +
/snis
+ + +##### Create SNI Associated to a Specific Certificate + +
/certificates/{certificate name or id}/snis
+ +Attributes | Description +---:| --- +`certificate name or id`
**required** | The unique identifier or the `name` attribute of the Certificate that should be associated to the newly-created SNI. + + +*Request Body* + +{{ page.sni_body }} + + +*Response* + +``` +HTTP 201 Created +``` + +```json +{{ page.sni_json }} +``` + + +--- + +### List SNIs + +##### List All SNIs + +
/snis
+ + +##### List SNIs Associated to a Specific Certificate + +
/certificates/{certificate name or id}/snis
+ +Attributes | Description +---:| --- +`certificate name or id`
**required** | The unique identifier or the `name` attribute of the Certificate whose SNIs are to be retrieved. When using this endpoint, only SNIs associated to the specified Certificate will be listed. + + +*Response* + +``` +HTTP 200 OK +``` + +```json +{ +{{ page.sni_data }} + "next": "http://localhost:8001/snis?offset=6378122c-a0a1-438d-a5c6-efabae9fb969" +} +``` + + +--- + +### Retrieve SNI + +##### Retrieve SNI + +
/snis/{name or id}
+ +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the SNI to retrieve. + + +*Response* + +``` +HTTP 200 OK +``` + +```json +{{ page.sni_json }} +``` + + +--- + +### Update SNI + +##### Update SNI + +
/snis/{name or id}
+ +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the SNI to update. + + +*Request Body* + +{{ page.sni_body }} + + +*Response* + +``` +HTTP 200 OK +``` + +```json +{{ page.sni_json }} +``` + + +--- + +### Update Or Create SNI + +##### Create Or Update SNI + +
/snis/{name or id}
+ +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the SNI to create or update. + + +*Request Body* + +{{ page.sni_body }} + + +Inserts (or replaces) the SNI under the requested resource with the +definition specified in the body. The SNI will be identified via the `name +or id` attribute. + +When the `name or id` attribute has the structure of a UUID, the SNI being +inserted/replaced will be identified by its `id`. Otherwise it will be +identified by its `name`. + +When creating a new SNI without specifying `id` (neither in the URL nor in +the body), then it will be auto-generated. + +Notice that specifying a `name` in the URL and a different one in the request +body is not allowed. + + +*Response* + +``` +HTTP 201 Created or HTTP 200 OK +``` + +See POST and PATCH responses. + + +--- + +### Delete SNI + +##### Delete SNI + +
/snis/{name or id}
+ +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the SNI to delete. + + +*Response* + +``` +HTTP 204 No Content +``` + +--- + +## Certificate Authority Object + +A certificate authority object represents a public CA certificate. +These objects are used by Kong to verify client certificates presented to the mTLS plugin. + + +```json +{{ page.certificate_authority_json }} +``` + +### Add Certificate Authority + +##### Create Certificate Authority + +
/ca_certificates
+ + +*Request Body* + +{{ page.certificate_authority_body }} + + +*Response* + +``` +HTTP 201 Created +``` + +```json +{{ page.certificate_authority_json }} +``` + + +--- + +### List Certificate Authorities + +##### List all Certificate Authorities + +
/ca_certificates
+ + +*Response* + +``` +HTTP 200 OK +``` + +```json +{ +{{ page.certificate_authority_data }} + "next": "http://localhost:8001/ca_certificates?offset=6378122c-a0a1-438d-a5c6-efabae9fb969" +} +``` + + +--- + +### Retrieve Certificate Authority + +##### Retrieve Certificate Authority + +
/ca_certificates/{certificate authority id}
+ +Attributes | Description +---:| --- +`certificate authority id`
**required** | The unique identifier of the certificate authority to retrieve. + + +*Response* + +``` +HTTP 200 OK +``` + +```json +{{ page.certificate_authority_json }} +``` + + +--- + +### Update Certificate Authority + +##### Update Certificate Authority + +
/ca_certificates/{certificate authority id}
+ +Attributes | Description +---:| --- +`certificate authority id`
**required** | The unique identifier of the certificate authority to update. + + +*Request Body* + +{{ page.certificate_authority_body }} + + +*Response* + +``` +HTTP 200 OK +``` + +```json +{{ page.certificate_authority_json }} +``` + + +--- + +### Update or create Certificate Authority + +##### Create or update Certificate Authority + +
/ca_certificates/{certificate authority id}
+ +Attributes | Description +---:| --- +`certificate authority id`
**required** | The unique identifier of the certificate authority to create or update. + + +*Request Body* + +{{ page.certificate_authority_body }} + + +Inserts (or replaces) the certificate authority under the requested resource with the +definition specified in the body. The certificate authority will be identified via the ` id` attribute. + +When creating a new certificate authority without specifying `id` (neither in the URL nor in +the body), then it will be auto-generated. + + +*Response* + +``` +HTTP 201 Created or HTTP 200 OK +``` + +See POST and PATCH responses. + + +--- + +### Delete Certificate Authority + +##### Delete Certificate Authority + +
/ca_certificates/{certificate authority id}
+ +Attributes | Description +---:| --- +`certificate authority id`
**required** | The unique identifier of the certificate authority to delete. + + +*Response* + +``` +HTTP 204 No Content +``` + + + +--- + +## Upstream Object + +The upstream object represents a virtual hostname and can be used to loadbalance +incoming requests over multiple services (targets). So for example an upstream +named `service.v1.xyz` for a Service object whose `host` is `service.v1.xyz`. +Requests for this Service would be proxied to the targets defined within the upstream. + +An upstream also includes a [health checker][healthchecks], which is able to +enable and disable targets based on their ability or inability to serve +requests. The configuration for the health checker is stored in the upstream +object, and applies to all of its targets. + +Upstreams can be both [tagged and filtered by tags](#tags). + + +```json +{{ page.upstream_json }} +``` + +### Add Upstream + +##### Create Upstream + +
/upstreams
+ + +*Request Body* + +{{ page.upstream_body }} + + +*Response* + +``` +HTTP 201 Created +``` + +```json +{{ page.upstream_json }} +``` + + +--- + +### List Upstreams + +##### List All Upstreams + +
/upstreams
+ + +*Response* + +``` +HTTP 200 OK +``` + +```json +{ +{{ page.upstream_data }} + "next": "http://localhost:8001/upstreams?offset=6378122c-a0a1-438d-a5c6-efabae9fb969" +} +``` + + +--- + +### Retrieve Upstream + +##### Retrieve Upstream + +
/upstreams/{name or id}
+ +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the Upstream to retrieve. + + +##### Retrieve Upstream Associated to a Specific Target + +
/targets/{target host:port or id}/upstream
+ +Attributes | Description +---:| --- +`target host:port or id`
**required** | The unique identifier **or** the host:port of the Target associated to the Upstream to be retrieved. + + +*Response* + +``` +HTTP 200 OK +``` + +```json +{{ page.upstream_json }} +``` + + +--- + +### Update Upstream + +##### Update Upstream + +
/upstreams/{name or id}
+ +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the Upstream to update. + + +##### Update Upstream Associated to a Specific Target + +
/targets/{target host:port or id}/upstream
+ +Attributes | Description +---:| --- +`target host:port or id`
**required** | The unique identifier **or** the host:port of the Target associated to the Upstream to be updated. + + +*Request Body* + +{{ page.upstream_body }} + + +*Response* + +``` +HTTP 200 OK +``` + +```json +{{ page.upstream_json }} +``` + + +--- + +### Update Or Create Upstream + +##### Create Or Update Upstream + +
/upstreams/{name or id}
+ +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the Upstream to create or update. + + +##### Create Or Update Upstream Associated to a Specific Target + +
/targets/{target host:port or id}/upstream
+ +Attributes | Description +---:| --- +`target host:port or id`
**required** | The unique identifier **or** the host:port of the Target associated to the Upstream to be created or updated. + + +*Request Body* + +{{ page.upstream_body }} + + +Inserts (or replaces) the Upstream under the requested resource with the +definition specified in the body. The Upstream will be identified via the `name +or id` attribute. + +When the `name or id` attribute has the structure of a UUID, the Upstream being +inserted/replaced will be identified by its `id`. Otherwise it will be +identified by its `name`. + +When creating a new Upstream without specifying `id` (neither in the URL nor in +the body), then it will be auto-generated. + +Notice that specifying a `name` in the URL and a different one in the request +body is not allowed. + + +*Response* + +``` +HTTP 201 Created or HTTP 200 OK +``` + +See POST and PATCH responses. + + +--- + +### Delete Upstream + +##### Delete Upstream + +
/upstreams/{name or id}
+ +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the Upstream to delete. + + +##### Delete Upstream Associated to a Specific Target + +
/targets/{target host:port or id}/upstream
+ +Attributes | Description +---:| --- +`target host:port or id`
**required** | The unique identifier **or** the host:port of the Target associated to the Upstream to be deleted. + + +*Response* + +``` +HTTP 204 No Content +``` + + +--- + +### Show Upstream Health for Node + +Displays the health status for all Targets of a given Upstream, according to +the perspective of a specific Kong node. Note that, being node-specific +information, making this same request to different nodes of the Kong cluster +may produce different results. For example, one specific node of the Kong +cluster may be experiencing network issues, causing it to fail to connect to +some Targets: these Targets will be marked as unhealthy by that node +(directing traffic from this node to other Targets that it can successfully +reach), but healthy to all others Kong nodes (which have no problems using that +Target). + +The `data` field of the response contains an array of Target objects. +The health for each Target is returned in its `health` field: + +* If a Target fails to be activated in the ring balancer due to DNS issues, + its status displays as `DNS_ERROR`. +* When [health checks][healthchecks] are not enabled in the Upstream + configuration, the health status for active Targets is displayed as + `HEALTHCHECKS_OFF`. +* When health checks are enabled and the Target is determined to be healthy, + either automatically or [manually](#set-target-as-healthy), + its status is displayed as `HEALTHY`. This means that this Target is + currently included in this Upstream's load balancer ring. +* When a Target has been disabled by either active or passive health checks + (circuit breakers) or [manually](#set-target-as-unhealthy), + its status is displayed as `UNHEALTHY`. The load balancer is not directing + any traffic to this Target via this Upstream. + + +
/upstreams/{name or id}/health/
+ +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the Upstream for which to display Target health. + + +*Response* + +``` +HTTP 200 OK +``` + +```json +{ + "total": 2, + "node_id": "cbb297c0-14a9-46bc-ad91-1d0ef9b42df9", + "data": [ + { + "created_at": 1485524883980, + "id": "18c0ad90-f942-4098-88db-bbee3e43b27f", + "health": "HEALTHY", + "target": "127.0.0.1:20000", + "upstream_id": "07131005-ba30-4204-a29f-0927d53257b4", + "weight": 100 + }, + { + "created_at": 1485524914883, + "id": "6c6f34eb-e6c3-4c1f-ac58-4060e5bca890", + "health": "UNHEALTHY", + "target": "127.0.0.1:20002", + "upstream_id": "07131005-ba30-4204-a29f-0927d53257b4", + "weight": 200 + } + ] +} +``` + + +--- + +## Target Object + +A target is an ip address/hostname with a port that identifies an instance of a backend +service. Every upstream can have many targets, and the targets can be +dynamically added. Changes are effectuated on the fly. + +Because the upstream maintains a history of target changes, the targets cannot +be deleted or modified. To disable a target, post a new one with `weight=0`; +alternatively, use the `DELETE` convenience method to accomplish the same. + +The current target object definition is the one with the latest `created_at`. + +Targets can be both [tagged and filtered by tags](#tags). + + +```json +{{ page.target_json }} +``` + +### Add Target + +##### Create Target Associated to a Specific Upstream + +
/upstreams/{upstream host:port or id}/targets
+ +Attributes | Description +---:| --- +`upstream host:port or id`
**required** | The unique identifier or the `host:port` attribute of the Upstream that should be associated to the newly-created Target. + + +*Request Body* + +{{ page.target_body }} + + +*Response* + +``` +HTTP 201 Created +``` + +```json +{{ page.target_json }} +``` + + +--- + +### List Targets + +##### List Targets Associated to a Specific Upstream + +
/upstreams/{upstream host:port or id}/targets
+ +Attributes | Description +---:| --- +`upstream host:port or id`
**required** | The unique identifier or the `host:port` attribute of the Upstream whose Targets are to be retrieved. When using this endpoint, only Targets associated to the specified Upstream will be listed. + + +*Response* + +``` +HTTP 200 OK +``` + +```json +{ +{{ page.target_data }} + "next": "http://localhost:8001/targets?offset=6378122c-a0a1-438d-a5c6-efabae9fb969" +} +``` + + +--- + +### Delete Target + +Disable a target in the load balancer. Under the hood, this method creates +a new entry for the given target definition with a `weight` of 0. + + +
/upstreams/{upstream name or id}/targets/{host:port or id}
+ +Attributes | Description +---:| --- +`upstream name or id`
**required** | The unique identifier **or** the name of the upstream for which to delete the target. +`host:port or id`
**required** | The host:port combination element of the target to remove, or the `id` of an existing target entry. + + +*Response* + +``` +HTTP 204 No Content +``` + + +--- + +### Set Target As Healthy + +Set the current health status of a target in the load balancer to "healthy" +in the entire Kong cluster. + +This endpoint can be used to manually re-enable a target that was previously +disabled by the upstream's [health checker][healthchecks]. Upstreams only +forward requests to healthy nodes, so this call tells Kong to start using this +target again. + +This resets the health counters of the health checkers running in all workers +of the Kong node, and broadcasts a cluster-wide message so that the "healthy" +status is propagated to the whole Kong cluster. + + +
/upstreams/{upstream name or id}/targets/{target or id}/healthy
+ +Attributes | Description +---:| --- +`upstream name or id`
**required** | The unique identifier **or** the name of the upstream. +`target or id`
**required** | The host/port combination element of the target to set as healthy, or the `id` of an existing target entry. + + +*Response* + +``` +HTTP 204 No Content +``` + + +--- + +### Set Target As Unhealthy + +Set the current health status of a target in the load balancer to "unhealthy" +in the entire Kong cluster. + +This endpoint can be used to manually disable a target and have it stop +responding to requests. Upstreams only forward requests to healthy nodes, so +this call tells Kong to start skipping this target in the ring-balancer +algorithm. + +This call resets the health counters of the health checkers running in all +workers of the Kong node, and broadcasts a cluster-wide message so that the +"unhealthy" status is propagated to the whole Kong cluster. + +[Active health checks][active] continue to execute for unhealthy +targets. Note that if active health checks are enabled and the probe detects +that the target is actually healthy, it will automatically re-enable it again. +To permanently remove a target from the ring-balancer, you should [delete a +target](#delete-target) instead. + + +
/upstreams/{upstream name or id}/targets/{target or id}/unhealthy
+ +Attributes | Description +---:| --- +`upstream name or id`
**required** | The unique identifier **or** the name of the upstream. +`target or id`
**required** | The host/port combination element of the target to set as unhealthy, or the `id` of an existing target entry. + + +*Response* + +``` +HTTP 204 No Content +``` + + +--- + +### List All Targets + +Lists all targets of the upstream. Multiple target objects for the same +target may be returned, showing the history of changes for a specific target. +The target object with the latest `created_at` is the current definition. + + +
/upstreams/{name or id}/targets/all/
+ +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the upstream for which to list the targets. + + +*Response* + +``` +HTTP 200 OK +``` + +```json +{ + "total": 2, + "data": [ + { + "created_at": 1485524883980, + "id": "18c0ad90-f942-4098-88db-bbee3e43b27f", + "target": "127.0.0.1:20000", + "upstream_id": "07131005-ba30-4204-a29f-0927d53257b4", + "weight": 100 + }, + { + "created_at": 1485524914883, + "id": "6c6f34eb-e6c3-4c1f-ac58-4060e5bca890", + "target": "127.0.0.1:20002", + "upstream_id": "07131005-ba30-4204-a29f-0927d53257b4", + "weight": 200 + } + ] +} +``` + +## Enterprise Exclusive Admin API + +
+
+
+ +
+

The following documentation refers to Kong Enterprise specific Admin API functionality. For a complete reference checkout the Kong Admin API Reference.

+
+
+ +
+
+

+ + Workspaces +

+

Segment your cluster into Workspaces for specific teams.

+ + View reference → + +
+ +
+

+ + RBAC +

+

Authenticate Kong Admins with Basic Auth, OIDC, LDAP, and Sessions. Authorize Admins with RBAC and Workspaces.

+ + Learn more → + +
+ +
+

+ + Admins +

+

Create and manage Admins for Kong Enterprise

+ Learn more → +
+ +
+

+ + Vitals +

+

Enable metrics about the health and performance of Kong.

+ Learn more → +
+ +
+

+ + Audit Logging +

+

Generate and view audit logs.

+ Learn more → +
+
+ +--- + +[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/1.3-x/admin-api/rbac/examples.md b/app/enterprise/1.3-x/admin-api/rbac/examples.md new file mode 100644 index 000000000000..fe90252af467 --- /dev/null +++ b/app/enterprise/1.3-x/admin-api/rbac/examples.md @@ -0,0 +1,1050 @@ +--- +title: RBAC Examples +book: rbac +--- + +## Introduction + +This chapter aims to provide a step-by-step tutorial on how to set up +RBAC and see it in action, with an end-to-end use case. The chosen +use case demonstrates how **RBAC with workspaces** can be coupled +to achieve a flexible organization of teams and users in complex +hierarchies. Make sure to read the [RBAC Overview][rbac-overview] page +and to glance over the [RBAC Admin API][rbac-admin] chapter, keeping it +open as a reference. + +## Use Case + +For the sake of example, let's say a given company has a Kong Enterprise +cluster to be shared with 3 teams: teamA, teamB, and teamC. While the Kong +cluster are shared among these teams, they want to be able to segment +their entities in such a way that management of entities in one team doesn't +disrupt operation in some other team. As shown in the +[Workspaces Examples Page][workspaces-examples], such a use case is possible +with workspaces. On top of workspaces, though, each team wants to enforce +access control over their Workspace, which is possible with RBAC. **To sum up, +Workspaces and RBAC are complementary: Workspaces provide segmentation of +Admin API entities, while RBAC provides access control**. + +## Bootstrapping the first RBAC user—the Super Admin + +**Note:** It is possible to create the first Super Admin at the time +of migration as described in the [Getting Started Guide][getting-started-guide]. +If you chose this option, skip to [Enforcing RBAC](#enforcing-rbac). + +Before anything, we will assume the Kong Admin—or, more interestingly, +the KongOps Engineer—in charge of operating Kong, will create a Super Admin +user, before actually enforcing RBAC and restarting Kong with RBAC enabled. + +As Kong ships with a handy set of default RBAC Roles—the `super-admin`, +the `admin`, and `read-only`—the task of creating a Super Admin user is +quite easy: + +Create the RBAC user, named `super-admin`: + +``` +http :8001/rbac/users name=super-admin +{ + "user_token": "M8J5A88xKXa7FNKsMbgLMjkm6zI2anOY", + "id": "da80838d-49f8-40f6-b673-6fff3e2c305b", + "enabled": true, + "created_at": 1531009435000, + "name": "super-admin" +} +``` + +As the `super-admin` user name coincides with an existing `super-admin` +role, it gets automatically added to the `super-admin` role—which can be +confirmed with the following command: + +``` +http :8001/rbac/users/super-admin/roles +{ + "roles": [ + { + "comment": "Full access to all endpoints, across all workspaces", + "created_at": 1531009724000, + "name": "super-admin", + "id": "b924ac91-e83f-4136-a5a4-4a7ff92594a8" + } + ], + "user": { + "created_at": 1531009858000, + "id": "e6897cc0-0c34-4a9c-9f0b-cc65b4f04d68", + "name": "super-admin", + "enabled": true, + "user_token": "vajeOlkybsn0q0VD9qw9B3nHYOErgY7b8" + } +} + +``` + +## Enforcing RBAC + +As the `super-admin` user has just been created, the Kong Admin may now +restart Kong with RBAC enforced, with, e.g.: + +``` +KONG_ENFORCE_RBAC=on kong restart +``` + +**NOTE**: This is one of the possible ways of enforcing RBAC and restarting +Kong; another possibility is editing the Kong configuration file and +restarting. + +Before we move on, note that we will be using the Super Admin user, but we +could, in fact, be moving without RBAC enabled, and having our Kong Admin do +all the job of setting up the RBAC hierarchy. We want, however, to stress the +fact that RBAC is powerful enough to allow a flexible separation of tasks. To +summarize: + +- **Kong Admin**: this user has physical access to Kong infrastructure; her +task is to bootstrap the Kong cluster as well as its configuration, including +initial RBAC users; +- **RBAC Super Admin**: created by the Kong Admin, has the role of managing +RBAC users, roles, etc; this could all be done by the **Kong Admin**, but let's +give him a break. + +## Super Admin creates the teams Workspaces + +The Super Admin will now set up our 3 teams: teamA, teamB, and teamC, creating +one workspace for each, one admin for each. Enough talking. + +Creating workspaces for each team—this overlaps a bit with +[Workspaces Examples][workspaces-examples], yes, but it will make our +exploration of RBAC + Workspaces easier: + +**Team A**: + +``` +http :8001/workspaces name=teamA Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "name": "teamA", + "created_at": 1531014100000, + "id": "1412f3a6-4d9b-4b9d-964e-60d8d63a9d46" +} + +``` + +**Team B**: + +``` +http :8001/workspaces name=teamB Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "name": "teamB", + "created_at": 1531014143000, + "id": "7dee8c56-c6db-4125-b87a-b508baa33c66" +} +``` + +**Team C**: + +``` +http :8001/workspaces name=teamC Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "name": "teamC", + "created_at": 1531014171000, + "id": "542c8662-17cc-49eb-af50-6eb14f3b2e8a" +} +``` + +**NOTE**: this is the RBAC Super Admin creating workspaces—note his +token being passed in through the `Kong-Admin-Token` HTTP header. + +## Super Admin Creates one Admin for each Team: + +**Team A**: + +``` +http :8001/teamA/rbac/users name=adminA Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "user_token": "qv1VLIpl8kHj7lC1QOKwRdCMXanqEDii", + "id": "4d315ff9-8c1a-4844-9ea2-21b16204a154", + "enabled": true, + "created_at": 1531015165000, + "name": "adminA" +} +``` + +**Team B**: + +``` +http :8001/teamB/rbac/users name=adminB Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "user_token": "IX5vHVgYqM40tLcctdmzRtHyfxB4ToYv", + "id": "49641fc0-8c9d-4507-bc7a-2acac8f2903a", + "enabled": true, + "created_at": 1531015221000, + "name": "adminB" +} +``` + +**Team C**: + +``` +http :8001/teamC/rbac/users name=adminC Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "user_token": "w2f7tsuUW4BerXocZIMRQHE84nK2ZAo7", + "id": "74643f69-8852-49f9-b363-21971bac4f52", + "enabled": true, + "created_at": 1531015304000, + "name": "teamC" +} +``` + +With this, all of the teams have one admin and each admin can only be seen +in his corresponding workspace. To verify: + +``` +http :8001/teamA/rbac/users Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "total": 1, + "data": [ + { + "created_at": 1531014784000, + "id": "1faaacd1-709f-4762-8c3e-79f268ec8faf", + "name": "adminA", + "enabled": true, + "user_token": "n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG" + } + ] +} +``` + +Similarly, workspaces teamB and teamC only show their respective admins: + +``` +http :8001/teamB/rbac/users Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "total": 1, + "data": [ + { + "created_at": 1531014805000, + "id": "3a829408-c1ee-4764-8222-2d280a5de441", + "name": "adminB", + "enabled": true, + "user_token": "C8b6kTTN10JFyU63ORjmCQwVbvK4maeq" + } + ] +} +``` + +``` +http :8001/teamC/rbac/users Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "total": 1, + "data": [ + { + "created_at": 1531014813000, + "id": "84d43cdb-5274-4b74-ad22-615e50f005e3", + "name": "adminC", + "enabled": true, + "user_token": "zN5Nj8U1MiGR7vVQKvl8odaGBDI6mjgY" + } + ] +} +``` + +## Super Admin Creates Admin Roles for Teams + +Super Admin is now done creating RBAC Admin users for each team; his next +task is to create admin roles that will effectively grant permissions to admin +users. + +The admin role must have access to all of the Admin API, restricted to his +workspace. + +Setting up the Admin role—pay close attention to the request parameters: + +``` +http :8001/teamA/rbac/roles/ name=admin Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "created_at": 1531016728000, + "id": "d40e61ab-8dad-4ef2-a48b-d11379f7b8d1", + "name": "admin" +} +``` + +Creating role endpoint permissions: + +``` +http :8001/teamA/rbac/roles/admin/endpoints/ endpoint=* workspace=teamA actions=* Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "total": 1, + "data": [ + { + "endpoint": "*", + "created_at": 1531017322000, + "role_id": "d40e61ab-8dad-4ef2-a48b-d11379f7b8d1", + "actions": [ + "delete", + "create", + "update", + "read" + ], + "negative": false, + "workspace": "teamA" + } + ] +} +``` + +Next logical step is to add the adminA user—admin of Team A—to the Admin +role in his workspace: + +``` +http :8001/teamA/rbac/users/adminA/roles/ roles=admin Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "roles": [ + { + "comment": "Default user role generated for adminA", + "created_at": 1531014784000, + "id": "e2941b41-92a4-4f49-be89-f1a452bdecd0", + "name": "adminA" + }, + { + "created_at": 1531016728000, + "id": "d40e61ab-8dad-4ef2-a48b-d11379f7b8d1", + "name": "admin" + } + ], + "user": { + "created_at": 1531014784000, + "id": "1faaacd1-709f-4762-8c3e-79f268ec8faf", + "name": "adminA", + "enabled": true, + "user_token": "n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG" + } +} +``` + +Note the admin role in the list above. + +With these steps, Team A's admin user is now able to manage his team. To +validate that, let's try to list RBAC users in Team B using Team A's admin +user token—and see that we are not allowed to do so: + +``` +http :8001/teamB/rbac/users Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "message": "Invalid RBAC credentials" +} +``` + +Said admin is, however, allowed to list RBAC users in Team A's workspace: + +``` +http :8001/teamA/rbac/users Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "total": 1, + "data": [ + { + "created_at": 1531014784000, + "id": "1faaacd1-709f-4762-8c3e-79f268ec8faf", + "name": "adminA", + "enabled": true, + "user_token": "n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG" + } + ] +} +``` + +If the same procedure is repeated for Team B and Team C, they will end up with +a similar set up, with an admin role and an admin user, both restricted to the +team's workspace. + +And so Super Admin ends his participation; individual team admins are now able +to set up his teams users and entities! + +## Team Admins Create Team Regular Users + +From this point on, team admins are able to drive the process; the next logical +step is for Team users to be created; such team users could be, for example, +engineers that are part of Team A (or B or C). Let's go ahead and do that, +using Admin A's user token. + +Before regular users can be created, a role needs to be available for them. +Such a role needs to have permissions to all of Admin API endpoints, except +RBAC and Workspaces—regular users will not need access to these in general +and, if they do, the Admin can grant them. + +**Creating the regular users role**: + +``` +http :8001/teamA/rbac/roles/ name=users Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "created_at": 1531020346000, + "id": "9846b92c-6820-4741-ac31-425b3d6abc5b", + "name": "users" +} +``` + +**Creating permissions in the regular users role**: + +First, permission to all of Admin API—positive permission on \*: + +``` +http :8001/teamA/rbac/roles/users/endpoints/ endpoint=* workspace=teamA actions=* Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "endpoint": "*", + "created_at": 1531020573000, + "role_id": "9846b92c-6820-4741-ac31-425b3d6abc5b", + "actions": [ + "delete", + "create", + "update", + "read" + ], + "negative": false, + "workspace": "teamA" +} +``` + +Then, filter out RBAC and workspaces with negative permissions: + +``` +http :8001/teamA/rbac/roles/users/endpoints/ endpoint=/rbac/* workspace=teamA actions=* Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "endpoint": "/rbac/*", + "created_at": 1531020744000, + "role_id": "9846b92c-6820-4741-ac31-425b3d6abc5b", + "actions": [ + "delete", + "create", + "update", + "read" + ], + "negative": true, + "workspace": "teamA" +} +``` + +``` +http :8001/teamA/rbac/roles/users/endpoints/ endpoint=/workspaces/* workspace=teamA actions=* Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "endpoint": "/workspaces/*", + "created_at": 1531020778000, + "role_id": "9846b92c-6820-4741-ac31-425b3d6abc5b", + "actions": [ + "delete", + "create", + "update", + "read" + ], + "negative": true, + "workspace": "teamA" +} +``` + +**IMPORTANT**: as explained in the [Wildcards in Permissions][rbac-wildcards] +section, the meaning of `*` is not the expected generic globbing one might +be used to. As such, `/rbac/*` or `/workspaces/*` do not match all of the +RBAC and Workspaces endpoints. For example, to cover all of the RBAC API, +one would have to define permissions for the following endpoints: + +- `/rbac/*` +- `/rbac/*/*` +- `/rbac/*/*/*` +- `/rbac/*/*/*/*` +- `/rbac/*/*/*/*/*` + +Team A just got 3 new members: foogineer, bargineer, and bazgineer. Admin A +will welcome them to the team by creating RBAC users for them and giving them +access to Kong! + +Create foogineer: + +``` +http :8001/teamA/rbac/users name=foogineer Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "created_at": 1531019797000, + "id": "0b4111da-2827-4767-8651-a327f7a559e9", + "name": "foogineer", + "enabled": true, + "user_token": "dNeYvYAwvjOJdoReVJZXF8vLBXQioKkI" +} +``` + +Add foogineer to the `users` role: + +``` +http :8001/teamA/rbac/users/foogineer/roles roles=users Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "roles": [ + { + "comment": "Default user role generated for foogineer", + "created_at": 1531019797000, + "id": "125c4212-b882-432d-a323-9cbe38b1d0df", + "name": "foogineer" + }, + { + "created_at": 1531020346000, + "id": "9846b92c-6820-4741-ac31-425b3d6abc5b", + "name": "users" + } + ], + "user": { + "created_at": 1531019797000, + "id": "0b4111da-2827-4767-8651-a327f7a559e9", + "name": "foogineer", + "enabled": true, + "user_token": "dNeYvYAwvjOJdoReVJZXF8vLBXQioKkI" + } +} +``` + +Create bargineer: + +``` +http :8001/teamA/rbac/users name=bargineer Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "created_at": 1531019837000, + "id": "25dfa68e-32e8-48d8-815f-6fedfd2fb4a6", + "name": "bargineer", + "enabled": true, + "user_token": "eZj3WUc46wO3zEJbLP3Y4VGvNaUgGlyv" +} +``` + +Add bargineer to the `users` role: + +``` +http :8001/teamA/rbac/users/bargineer/roles roles=users Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "roles": [ + { + "comment": "Default user role generated for bargineer", + "created_at": 1531019837000, + "id": "3edb00c2-9ae1-423d-ac81-bec702c29e37", + "name": "bargineer" + }, + { + "created_at": 1531020346000, + "id": "9846b92c-6820-4741-ac31-425b3d6abc5b", + "name": "users" + } + ], + "user": { + "created_at": 1531019837000, + "id": "25dfa68e-32e8-48d8-815f-6fedfd2fb4a6", + "name": "bargineer", + "enabled": true, + "user_token": "eZj3WUc46wO3zEJbLP3Y4VGvNaUgGlyv" + } +} +``` + +Create bazgineer: + +``` +http :8001/teamA/rbac/users name=bazgineer Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "created_at": 1531019937000, + "id": "ea7207d7-0d69-427b-b288-ce696b7f4690", + "name": "bazgineer", + "enabled": true, + "user_token": "r8NhaT213Zm8o1woQF4ZyQyCVjFRgGp3" +} +``` + +Add bazgineer to the `users` role: + +``` +http :8001/teamA/rbac/users/bazgineer/roles roles=users Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "roles": [ + { + "comment": "Default user role generated for bazgineer", + "created_at": 1531019937000, + "id": "fa409bb6-c86c-45d2-8a6b-ac8e71de2cc9", + "name": "bazgineer" + }, + { + "created_at": 1531020346000, + "name": "users", + "id": "9846b92c-6820-4741-ac31-425b3d6abc5b" + } + ], + "user": { + "created_at": 1531019937000, + "id": "ea7207d7-0d69-427b-b288-ce696b7f4690", + "name": "bazgineer", + "enabled": true, + "user_token": "r8NhaT213Zm8o1woQF4ZyQyCVjFRgGp3" + } +} +``` + +## Regular Team Users use their tokens! + +foogineer, bargineer, and bazgineer all have gotten their RBAC user tokens +from their Team A admin, and are now allowed to explore Kong—within the +confines of their Team A workspace. Let's validate they can in fact do anything +they wish, except over RBAC and Workspaces. + +Try listing Workspaces: + +``` +http :8001/teamA/workspaces/ Kong-Admin-Token:dNeYvYAwvjOJdoReVJZXF8vLBXQioKkI +{ + "message": "foogineer, you do not have permissions to read this resource" +} +``` + +Enable some plugin—e.g., key-auth: + +``` +http :8001/teamA/plugins name=key-auth Kong-Admin-Token:dNeYvYAwvjOJdoReVJZXF8vLBXQioKkI +{ + "created_at": 1531021732000, + "config": { + "key_in_body": false, + "run_on_preflight": true, + "anonymous": "", + "hide_credentials": false, + "key_names": [ + "apikey" + ] + }, + "id": "cdc85ef0-804b-4f92-aafd-3ff58512e445", + "enabled": true, + "name": "key-auth" +} +``` + +List currently enabled plugins: + +``` +http :8001/teamA/plugins Kong-Admin-Token:dNeYvYAwvjOJdoReVJZXF8vLBXQioKkI +{ + "total": 1, + "data": [ + { + "created_at": 1531021732000, + "config": { + "key_in_body": false, + "run_on_preflight": true, + "anonymous": "", + "hide_credentials": false, + "key_names": [ + "apikey" + ] + }, + "id": "cdc85ef0-804b-4f92-aafd-3ff58512e445", + "name": "key-auth", + "enabled": true + } + ] +} +``` + +This ends our use case tutorial; it demonstrates the power of RBAC and +workspaces with a real-world scenario. Following, we will approach **Entity-Level +RBAC**, an extension of our powerful access control to entity-level granularity. + +# Entity-Level RBAC: a Primer + +Kong Enterprise's new RBAC implementation goes one step further in permissions +granularity: in addition to "endpoint" permissions, it supports entity-level +permissions, meaning that particular entities, identified by their unique ID, +can be allowed or disallowed access in a role. + +Refreshing our minds, RBAC is [enforced][rbac-enforce] with the `enforce_rbac` +configuration directive—or with its `KONG_ENFORCE_RBAC` environment variable +counterpart. Such directive is an enum, with 4 possible values: + +- `on`: similarly to the previous RBAC implementation, applies Endpoint-level +access control +- `entity`: applies **only** Entity-level access control +- `both`: applies **both Endpoint and Entity level access control** +- `off`: disables RBAC enforcement + +If one sets it to either `entity` or `both`, Kong will enforce entity-level +access control. However, as with endpoint-level access control, permissions +must be bootstrapped before enforcement is enabled. + +## Creating Entity-Level Permissions + +Team A just got one new, temporary, team member: qux. Admin A, the admin of +Team A, has already created his qux RBAC user; he needs, however, to limit +access that qux has over entities in Team A workspace, giving him read access +to only a couple of entities—say, a Service and a Route. For that, he will +use Entity-Level RBAC. + +**Admin A creates a role for the temporary user qux**: + +``` +http :8001/teamA/rbac/roles name=qux-role Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "name": "qux-role", + "created_at": 1531065975000, + "id": "ffe93269-7993-4308-965e-0286d0bc87b9" +} +``` + +We will assume the following entities exist: + +A service: + +``` +http :8001/teamA/services Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "next": null, + "data": [ + { + "host": "httpbin.org", + "created_at": 1531066074, + "connect_timeout": 60000, + "id": "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43", + "protocol": "http", + "name": "service1", + "read_timeout": 60000, + "port": 80, + "path": null, + "updated_at": 1531066074, + "retries": 5, + "write_timeout": 60000 + } + ] +} +``` + +and a Route to that Service: + +``` +http :8001/teamA/routes Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "next": null, + "data": [ + { + "created_at": 1531066253, + "id": "d25afc46-dc59-48b2-b04f-d3ebe19f6d4b", + "hosts": null, + "updated_at": 1531066253, + "preserve_host": false, + "regex_priority": 0, + "service": { + "id": "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43" + }, + "paths": [ + "/anything" + ], + "methods": null, + "strip_path": false, + "protocols": [ + "http", + "https" + ] + } + ] +} +``` + +**Admin A creates entity permissions in qux-role**: + +Add service1—whose ID is 3ed24101-19a7-4a0b-a10f-2f47bcd4ff43: + +``` +http :8001/teamA/rbac/roles/qux-role/entities entity_id=3ed24101-19a7-4a0b-a10f-2f47bcd4ff43 actions=read Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "created_at": 1531066684000, + "role_id": "ffe93269-7993-4308-965e-0286d0bc87b9", + "entity_id": "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43", + "negative": false, + "entity_type": "services", + "actions": [ + "read" + ] +} +``` + +Add the route—whose ID is d25afc46-dc59-48b2-b04f-d3ebe19f6d4b: + +``` +http :8001/teamA/rbac/roles/qux-role/entities entity_id=d25afc46-dc59-48b2-b04f-d3ebe19f6d4b actions=read Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "created_at": 1531066728000, + "role_id": "ffe93269-7993-4308-965e-0286d0bc87b9", + "entity_id": "d25afc46-dc59-48b2-b04f-d3ebe19f6d4b", + "negative": false, + "entity_type": "routes", + "actions": [ + "read" + ] +} +``` + +**Admin A adds qux to his role**: + +``` +http :8001/teamA/rbac/users/qux/roles roles=qux-role Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "roles": [ + { + "comment": "Default user role generated for qux", + "created_at": 1531065373000, + "name": "qux", + "id": "31614171-4174-42b4-9fae-43c9ce14830f" + }, + { + "created_at": 1531065975000, + "name": "qux-role", + "id": "ffe93269-7993-4308-965e-0286d0bc87b9" + } + ], + "user": { + "created_at": 1531065373000, + "id": "4d87bf78-5824-4756-b0d0-ceaa9bd9b2d5", + "name": "qux", + "enabled": true, + "user_token": "sUnv6uBehM91amYRNWESsgX3HzqoBnR5" + } +} +``` + +Checking permissions appear listed: + +``` +http :8001/teamA/rbac/users/qux/permissions Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "entities": { + "d25afc46-dc59-48b2-b04f-d3ebe19f6d4b": { + "actions": [ + "read" + ], + "negative": false + }, + "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43": { + "actions": [ + "read" + ], + "negative": false + } + }, + "endpoints": {} +} +``` + +That is, 2 entities permissions and no endpoint permissions. + +Admin A is done setting up qux, and qux can now use his user token to read +his two entities over Kong's admin API. + +We will assume that Admin A [enabled entity-level enforcement][rbac-enforce]. +Note that as qux has **no endpoint-level permissions**, if both endpoint and +entity-level enforcement is enabled, he will not be able to read his entities - +endpoint-level validation comes before entity-level. + +**qux tries listing all RBAC users** + +``` +http :8001/teamA/rbac/users/ Kong-Admin-Token:sUnv6uBehM91amYRNWESsgX3HzqoBnR5 +{ + "message": "qux, you do not have permissions to read this resource" +} +``` + +**qux tries listing all Workspaces** + +``` +http :8001/teamA/rbac/workspaces/ Kong-Admin-Token:sUnv6uBehM91amYRNWESsgX3HzqoBnR5 +{ + "message": "qux, you do not have permissions to read this resource" +} +``` + +**qux tries to access service1** + +``` +http :8001/teamA/services/service1 Kong-Admin-Token:sUnv6uBehM91amYRNWESsgX3HzqoBnR5 +{ + "host": "httpbin.org", + "created_at": 1531066074, + "connect_timeout": 60000, + "id": "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43", + "protocol": "http", + "name": "service1", + "read_timeout": 60000, + "port": 80, + "path": null, + "updated_at": 1531066074, + "retries": 5, + "write_timeout": 60000 +} +``` + +Similarly, he can access his Route: + +``` +http :8001/teamA/routes/3ed24101-19a7-4a0b-a10f-2f47bcd4ff43 Kong-Admin-Token:sUnv6uBehM91amYRNWESsgX3HzqoBnR5 +{ + "created_at": 1531066253, + "strip_path": false, + "hosts": null, + "preserve_host": false, + "regex_priority": 0, + "updated_at": 1531066253, + "paths": [ + "/anything" + ], + "service": { + "id": "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43" + }, + "methods": null, + "protocols": [ + "http", + "https" + ], + "id": "d25afc46-dc59-48b2-b04f-d3ebe19f6d4b" +} +``` + +## Closing Remarks + +We will end this chapter with a few closing remarks. + +## Wildcards in Permissions + +RBAC supports the use of wildcards—represented by the `*` character—in many +aspects of permissions: + +**Creating endpoint permissions—`/rbac/roles/:role/endpoints`** + +To create an endpoint permission, one must pass the parameters below, all of +which can be replaced by a * character: + +- `endpoint`: `*` matches **any endpoint** +- `workspace`: `*` matches **any workspace** +- `actions`: `*` evaluates to **all actions—read, update, create, delete** + +**Special case**: `endpoint`, in addition to a single `*`, also accepts `*` +within the endpoint itself, replacing a URL segment between `/`; for example, +all of the following are valid endpoints: + +- `/rbac/*`: where `*` replaces any possible segment—e.g., `/rbac/users`, +`/rbac/roles`, etc +- `/services/*/plugins`: `*` matches any Service name or ID + +Note, however, that `*` **is not** a generic, shell-like, glob pattern. + +If `workspace` is ommitted, it defaults to the current request's workspace. For +example, a role-endpoint permission created with `/teamA/roles/admin/endpoints` +is scoped to workspace `teamA`. + +**Creating entity permissions—`/rbac/roles/:role/entities`** + +Similarly, for entity permissions, the following parameters accept a `*` +character: + +- `entity_id`: `*` matches **any entity ID** + +## Entities Concealing in Entity-Level RBAC + +With Entity-Level RBAC enabled, endpoints that list all entities of a +particular collection will only list entities that the user has access to; +in the example above, if user qux listed all Routes, he would only get as +response the entities he has access to—even though there could be more: + +``` +http :8001/teamA/routes Kong-Admin-Token:sUnv6uBehM91amYRNWESsgX3HzqoBnR5 +{ + "next": null, + "data": [ + { + "created_at": 1531066253, + "id": "d25afc46-dc59-48b2-b04f-d3ebe19f6d4b", + "hosts": null, + "updated_at": 1531066253, + "preserve_host": false, + "regex_priority": 0, + "service": { + "id": "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43" + }, + "paths": [ + "/anything" + ], + "methods": null, + "strip_path": false, + "protocols": [ + "http", + "https" + ] + } + ] +} +``` + +Some Kong endpoints carry a `total` field in responses; with Entity-Level RBAC +enabled, the global count of entities is displayed, but only entities the user +has access to are themselves shown; for example, if Team A has a number of +plugins configured, but qux only has access to one of them, the following +would be the expected output for a GET request to `/teamA/plugins`: + +``` +http :8001/teamA/plugins Kong-Admin-Token:sUnv6uBehM91amYRNWESsgX3HzqoBnR5 +{ + "total": 2, + "data": [ + { + "created_at": 1531070344000, + "config": { + "key_in_body": false, + "run_on_preflight": true, + "anonymous": "", + "hide_credentials": false, + "key_names": [ + "apikey" + ] + }, + "id": "8813dd0b-3e9d-4bcf-8a10-3112654f86e7", + "name": "key-auth", + "enabled": true + } + ] +} +``` + +Notice the `total` field is 2, but qux only got one entity in the response. + +## Creating Entities in Entity-Level RBAC + +As entity-level RBAC provides access control to individual existing entities, +it does not apply to creation of new entities; for that, endpoint-level +permissions must be configured and enforced. For example, if endpoint-level +permissions are not enforced, qux will be able to create new entities: + +``` +http :8001/teamA/routes paths[]=/anything service.id=3ed24101-19a7-4a0b-a10f-2f47bcd4ff43 strip_path=false Kong-Admin-Token:sUnv6uBehM91amYRNWESsgX3HzqoBnR5 +{ + "created_at": 1531070828, + "strip_path": false, + "hosts": null, + "preserve_host": false, + "regex_priority": 0, + "updated_at": 1531070828, + "paths": [ + "/anything" + ], + "service": { + "id": "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43" + }, + "methods": null, + "protocols": [ + "http", + "https" + ], + "id": "6ee76f74-3c96-46a9-ae48-72df0717d244" +} +``` + +and qux will automatically have permissions to perform any actions to entities +he created. + +--- + +[rbac-overview]: /enterprise/{{page.kong_version}}/rbac/overview +[rbac-enforce]: /enterprise/{{page.kong_version}}/rbac/overview#enforcing-rbac +[rbac-wildcard]: /enterprise/{{page.kong_version}}/rbac/examples/#wildcards-in-permissions +[rbac-admin]: /enterprise/{{page.kong_version}}/rbac/admin-api +[workspaces-examples]: /enterprise/{{page.kong_version}}/rbac/examples +[getting-started-guide]: /enterprise/{{page.kong_version}}/getting-started/quickstart/#1-start-kong-enterprise diff --git a/app/enterprise/1.3-x/admin-api/rbac/reference.md b/app/enterprise/1.3-x/admin-api/rbac/reference.md new file mode 100644 index 000000000000..5ca178b74a59 --- /dev/null +++ b/app/enterprise/1.3-x/admin-api/rbac/reference.md @@ -0,0 +1,952 @@ +--- +title: RBAC Reference +book: rbac +--- + +## Introduction + +Kong Enterprise's RBAC feature is configurable through Kong's [Admin +API] or via the [Kong Manager]. + +There are 4 basic entities involving RBAC. + +- **User**: The entity interacting with the system. Can be associated with + zero, one or more roles. Example: user `bob` has token `1234`. +- **Role**: Set of permissions (`role_endpoint` and + `role_entity`). Has a name and can be associated with zero, one or + more permissions. Example: user bob is associated with role + `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` +- **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`. + +## 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. | + +**Response** + +``` +HTTP 201 Created +``` + +```json +{ + "comment": null, + "created_at": 1557522650, + "enabled": true, + "id": "fa6881b2-f49f-4007-9475-577cd21d34f4", + "name": "doc_knight", + "user_token": "$2b$09$Za30VKAAAmyoB9zF2PNEF.9hgKcN2BdKkptPMCubPK/Ps08lzZjYG", + "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** + +``` +HTTP 200 OK +``` + +```json +{ + "created_at": 1557522650, + "enabled": true, + "id": "fa6881b2-f49f-4007-9475-577cd21d34f4", + "name": "doc_lord", + "user_token": "$2b$09$Za30VKAAAmyoB9zF2PNEF.9hgKcN2BdKkptPMCubPK/Ps08lzZjYG", + "user_token_ident": "4d870" +} +``` +___ + +## List Users +**Endpoint** + +
/rbac/users/
+ +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "data": [ + { + "comment": null, + "created_at": 1557512629, + "enabled": true, + "id": "f035f120-a95e-4327-b2ae-8fa264601d75", + "name": "doc_lord", + "user_token": "$2b$09$TIMneYcTosdG9WbzRsqcweAS2zote8g6I8HqXAtbFHR1pds2ymsh6", + "user_token_ident": "88ea3" + }, + { + "comment": null, + "created_at": 1557522650, + "enabled": true, + "id": "fa6881b2-f49f-4007-9475-577cd21d34f4", + "name": "doc_knight", + "user_token": "$2b$09$Za30VKAAAmyoB9zF2PNEF.9hgKcN2BdKkptPMCubPK/Ps08lzZjYG", + "user_token_ident": "4d870" + } + ], + "next": null +} +``` + +⚠️ **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. | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "comment": "this comment came from a patch request", + "created_at": 1557522650, + "enabled": true, + "id": "fa6881b2-f49f-4007-9475-577cd21d34f4", + "name": "donut_lord", + "user_token": "$2b$09$Za30VKAAAmyoB9zF2PNEF.9hgKcN2BdKkptPMCubPK/Ps08lzZjYG", + "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** + +``` +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. | + +**Response** + +``` +HTTP 201 Created +``` + +```json +{ + "comment": null, + "created_at": 1557532241, + "id": "b5c5cfd4-3330-4796-9b7b-6026e91e3ad6", + "is_default": false, + "name": "service_reader" +} +``` +___ + +## Retrieve a Role +Endpoint + +
/rbac/roles/{name_or_id}
+ +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "created_at": 1557532241, + "id": "b5c5cfd4-3330-4796-9b7b-6026e91e3ad6", + "is_default": false, + "name": "service_reader" +} +``` +___ + +## List Roles +**Endpoint** + +
/rbac/roles
+ +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "data": [ + { + "comment": "Full access to all endpoints, across all workspaces—except RBAC Admin API", + "created_at": 1557506249, + "id": "38a03d47-faae-4366-b430-f6c10aee5029", + "name": "admin" + }, + { + "comment": "Read access to all endpoints, across all workspaces", + "created_at": 1557506249, + "id": "4141675c-8beb-41a5-aa04-6258ab2d2f7f", + "name": "read-only" + }, + { + "comment": "Full access to all endpoints, across all workspaces", + "created_at": 1557506249, + "id": "888117e0-f2b3-404d-823b-dee595423505", + "name": "super-admin" + }, + { + "comment": null, + "created_at": 1557532241, + "id": "b5c5cfd4-3330-4796-9b7b-6026e91e3ad6", + "name": "doc_lord" + } + ], + "next": null +} +``` +___ + +## Update or Create a Role +**Endpoint** + +
/rbac/roles
+ +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `name` | The RBAC role name. | +| `comment`
optional | A string describing the RBAC user object. | + +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. + +**Response** + +If creating the entity: + +``` +HTTP 201 Created +``` + +If replacing the entity: + +``` +HTTP 200 OK +``` + +```json +{ + "comment": "the best", + "created_at": 1557532566, + "id": "b5c5cfd4-3330-4796-9b7b-6026e91e3ad6", + "is_default": false, + "name": "doc_lord" +} +``` + +## Update a Role +**Endpoint** + +
/rbac/roles/{name_or_id}
+ +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role or UUID. | + +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `comment`
optional | A string describing the RBAC role object. | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "comment": "comment from patch request", + "created_at": 1557532566, + "id": "b5c5cfd4-3330-4796-9b7b-6026e91e3ad6", + "is_default": false, + "name": "service_reader" +} +``` +___ + +## Delete a Role +**Endpoint** + +
/rbac/role/{name_or_id}
+ +| 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. | + + +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `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) | +| `comment`
optional | A string describing the RBAC permission object. | + +`endpoint` must be the path of the associated endpoint. They can be +exact matches, or contain wildcards, represented by `*`. + +- Exact matches; eg: + * /apis/ + * /apis/foo + +- Wildcards; eg: + * /apis/* + * /apis/*/plugins + +Where `*` replaces exactly one segment between slashes (or the end of +the path). + +Note that wildcards can be nested (`/rbac/*`, `/rbac/*/*`, +`/rbac/*/*/*` would refer to all paths under `/rbac/`) + +**Response** + +``` +HTTP 201 Created +``` + +```json +{ + "actions": [ + "delete", + "create", + "update", + "read" + ], + "created_at": 1557764505, + "endpoint": "/consumers", + "negative": false, + "role": { + "id": "23df9f20-e7cc-4da4-bc89-d3a08f976e50" + }, + "workspace": "default" +} +``` + +--- + +## 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. | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "actions": [ + "delete", + "create", + "update", + "read" + ], + "created_at": 1557764505, + "endpoint": "/consumers", + "negative": false, + "role": { + "id": "23df9f20-e7cc-4da4-bc89-d3a08f976e50" + }, + "workspace": "default" +} +``` + +--- + + + +## 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** + +``` +HTTP 200 OK +``` + +```json +{ + "data": [ + { + "actions": [ + "delete", + "create", + "update", + "read" + ], + "created_at": 1557764505, + "endpoint": "/consumers", + "negative": false, + "role": { + "id": "23df9f20-e7cc-4da4-bc89-d3a08f976e50" + }, + "workspace": "default" + }, + { + "actions": [ + "read" + ], + "created_at": 1557764438, + "endpoint": "/services", + "negative": false, + "role": { + "id": "23df9f20-e7cc-4da4-bc89-d3a08f976e50" + }, + "workspace": "default" + } + ] +} +``` + +--- + +## 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. | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "actions": [ + "delete", + "create", + "update", + "read" + ], + "created_at": 1557764438, + "endpoint": "/services", + "negative": false, + "role": { + "id": "23df9f20-e7cc-4da4-bc89-d3a08f976e50" + }, + "workspace": "default" +} +``` + +--- + + + +## 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. | + +**Response** + +``` +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. | +| `comment`
optional | A string describing the RBAC permission object | + +`entity_id` must be the ID of an entity in Kong; if the ID of a +workspace is given, the permission will apply to all entities in that +workspace. Future entities belonging to that workspace will get the +same permissions. A wildcard `*` will be interpreted as **all +entities** in the system. + + +**Response** + +``` +HTTP 201 Created +``` + +```json +{ + "actions": [ + "delete", + "create", + "read" + ], + "created_at": 1557771505, + "entity_id": "*", + "entity_type": "wildcard", + "negative": false, + "role": { + "id": "bba049fa-bf7e-40ef-8e89-553dda292e99" + } +} +``` + +--- + +## 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. | + +**Response** + +``` +HTTP 200 Ok +``` + +```json +{ + "actions": [ + "delete", + "create", + "read" + ], + "created_at": 1557771505, + "entity_id": "*", + "entity_type": "wildcard", + "negative": false, + "role": { + "id": "bba049fa-bf7e-40ef-8e89-553dda292e99" + } +} +``` + +--- + +## List Entity Permissons + +**Endpoint** +
/rbac/roles/{name_or_id}/entities
+ +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC permisson name or UUID. | + +**Response** + +``` +HTTP 200 Ok +``` + +```json +{ + "data": [ + { + "actions": [ + "delete", + "create", + "read" + ], + "created_at": 1557771505, + "entity_id": "*", + "entity_type": "wildcard", + "negative": false, + "role": { + "id": "bba049fa-bf7e-40ef-8e89-553dda292e99" + } + } + ] +} +``` + +--- +## 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. | + +**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. | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "actions": [ + "update" + ], + "created_at": 1557771505, + "entity_id": "*", + "entity_type": "wildcard", + "negative": false, + "role": { + "id": "bba049fa-bf7e-40ef-8e89-553dda292e99" + } +} +``` + +--- + +## 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. | + +**Response** + +``` +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" + ], + "negative": false + }, + "/*/rbac/*": { + "actions": [ + "delete", + "create", + "update", + "read" + ], + "negative": true + } + } + }, + "entities": {} +} +``` + +## 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 | +| --------- | ----------- | +| `roles` | Comma-separated list of role names to assign to the user. | + +**Response** + +``` +HTTP 201 Created +``` +```json +{ + "roles": [ + { + "created_at": 1557772263, + "id": "aae80073-095f-4553-ba9a-bee5ed3b8b91", + "name": "doc-knight" + } + ], + "user": { + "comment": null, + "created_at": 1557772232, + "enabled": true, + "id": "b65ca712-7ceb-4114-87f4-5c310492582c", + "name": "gruce-wayne", + "user_token": "$2b$09$gZnMKK/mm/d2rAXN7gL63uL43mjdX/62iwMqdyCQwLyC0af3ce/1K", + "user_token_ident": "88ea3" + } +} +``` + +--- +## 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 + +{ + "roles": [ + { + "comment": "Read access to all endpoints, across all workspaces", + "created_at": 1557765500, + "id": "a1c810ee-8366-4654-ba0c-963ffb9ccf2e", + "name": "read-only" + }, + { + "created_at": 1557772263, + "id": "aae80073-095f-4553-ba9a-bee5ed3b8b91", + "name": "doc-knight" + } + ], + "user": { + "comment": null, + "created_at": 1557772232, + "enabled": true, + "id": "b65ca712-7ceb-4114-87f4-5c310492582c", + "name": "gruce-wayne", + "user_token": "$2b$09$gZnMKK/mm/d2rAXN7gL63uL43mjdX/62iwMqdyCQwLyC0af3ce/1K", + "user_token_ident": "88ea3" + } +} +``` + +--- +## 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** + +``` +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** + +``` +HTTP 200 OK +``` +```json +{ + "endpoints": { + "*": { + "*": { + "actions": [ + "read" + ], + "negative": false + } + } + }, + "entities": {} +} + +``` diff --git a/app/enterprise/1.3-x/admin-api/vitals/index.md b/app/enterprise/1.3-x/admin-api/vitals/index.md new file mode 100644 index 000000000000..bd3525e05362 --- /dev/null +++ b/app/enterprise/1.3-x/admin-api/vitals/index.md @@ -0,0 +1,197 @@ +--- +title: Kong Vitals +--- + +### Introduction + +Vitals is a feature within Kong's Admin API and Kong Manager that provides +metrics about the health and performance of Kong nodes and Kong-proxied APIs. + +## Requirements + +- PostgresSQL 9.5+ or Cassandra 2.1+ + +## How to Enable and Disable Vitals + +Kong Enterprise ships with Vitals enabled by default. + +Vitals can be disabled (or re-enabled) in the configuration file (e.g kong.conf): + +```bash +# via your Kong configuration file; e.g., kong.conf +vitals = on # vitals is enabled +vitals = off # vitals is disabled +``` + +or by environment variables: + +```bash +# or via environment variables +$ export KONG_VITALS=on +$ export KONG_VITALS=off +``` + +Kong must be restarted for these changes to take effect. + +## Vitals Metrics + +Vitals metrics fall into two categories: +* Health Metrics - for monitoring the health of a Kong cluster +* Traffic Metrics — for monitoring the usage of upstream services + +Within these categories, Vitals collects the following metrics: + +- [Health Metrics](#health-metrics) + - [Latency](#latency) + - [Proxy Latency (Request)](#proxy-latency-request) + - [Upstream Latency](#upstream-latency) + - [Datastore Cache](#datastore-cache) + - [Datastore Cache Hit/Miss](#datastore-cache-hit-miss) + - [Datastore Cache Hit Ratio](#datastore-cache-hit-ratio) +- [Traffic Metrics](#traffic-metrics) + - [Request Counts](#request-counts) + - [Total Requests](#total-requests) + - [Requests per Consumer](#request-per-consumer) + - [Status Codes](#status-code) + - [Total Status Code Classes](#total-status-code-classes) + - [Total Status Codes per Service](#total-status-codes-per-service) + - [Total Status Codes per Route](#total-status-codes-per-route) + - [Total Status Codes per Consumer](#total-status-codes-per-consumer) + - [Total Status Codes per Consumer per Route](#total-status-codes-per-consumer-per-route) + +All metrics are collected at 1-second intervals and aggregated into 1-minute +intervals. The 1-second intervals are retained for one hour. The 1-minute +intervals are retained for 25 hours. + +If longer retention times are needed, the Vitals API can be used to pull metrics +out of Kong and into a data retention tool. + +### Health Metrics + +Health metrics give insight into the performance of a Kong cluster; for example, +how many requests it is processing and the latency on those requests. + +Health metrics are tracked for each node in a cluster as well as for the cluster +as a whole. In Kong, a node is a running process with a unique identifier, +configuration, cache layout, and connections to both Kong’s datastores and the +upstream APIs it proxies. Note that node identifiers are unique to the process, +and not to the host on which the process runs. In other words, each Kong restart +results in a new node, and therefore a new node ID. + +#### Latency + +The Vitals API may return null for Latency metrics—this occurs when no API +requests were proxied during the timeframe. Null latencies are not graphed in +Kong Manager—periods with null latencies appear as gaps in Vitals charts. + +##### Proxy Latency (Request) + +The Proxy Latency metrics are the min, max, and average values for the time, in milliseconds, that the Kong proxy spends processing API proxy requests. This includes time to execute plugins that run in the access phase as well as DNS lookup time. This does not include time spent in Kong’s load balancer, time spent sending the request to the upstream, or time spent on the response. + +These metrics are referenced in the Vitals API with the following labels: `latency_proxy_request_min_ms`, `latency_proxy_request_max_ms`, `latency_proxy_request_avg_ms` + +Latency is not reported when a request is prematurely ended by Kong (e.g., bad auth, rate limited, etc.)—note that this differs from the “Total Requests” metric that does count such requests. + +##### Upstream Latency + +The Upstream Latency metrics are the min, max, and average values for the time elapsed, in milliseconds, between Kong sending requests upstream and Kong receiving the first bytes of responses from upstream. + +These metrics are referenced in the Vitals API with the following labels: `latency_upstream_min_ms`, `latency_upstream_max_ms`, `latency_upstream_avg_ms` + +#### Datastore Cache + +##### Datastore Cache Hit/Miss + +The Datastore Cache Hit/Miss metrics are the count of requests to Kong's node-level datastore cache. When Kong workers need configuration information to respond to a given API proxy request, they first check their worker-specific cache (also known as L1 cache), then if the information isn’t available they check the node-wide datastore cache (also known as L2 cache). If neither cache contains the necessary information, Kong requests it from the datastore. + +A “Hit” indicates that an entity was retrieved from the data store cache. A “Miss” indicates that the record had to be fetched from the datastore. Not every API request will result in datastore cache access—some entities will be retrieved from Kong's worker-specific cache memory. + +These metrics are referenced in the Vitals API with the following labels: `cache_datastore_hits_total`, `cache_datastore_misses_total` + +##### Datastore Cache Hit Ratio + +This metric contains the ratio of datastore cache hits to the total count of datastore cache requests. + +> Note: Datastore Cache Hit Ratio cannot be calculated for time indices with no hits and no misses. + +### Traffic Metrics + +Traffic metrics provide insight into which of your services are being used, and by whom, and how they are responding. + +#### Request Counts + +##### Total Requests + + +This metric is the count of all API proxy requests received. This includes requests that were rejected due to rate-limiting, failed authentication, etc. + +This metric is referenced in the Vitals API with the following label: `requests_proxy_total` + +##### Requests Per Consumer + +This metric is the count of all API proxy requests received from each specific consumer. Consumers are identified by credentials in their requests (e.g., API key, OAuth token, etc) as required by the Kong Auth plugin(s) in use. + +This metric is referenced in the Vitals API with the following label: `requests_consumer_total` + +#### Status Codes + +##### Total Status Code Classes + +This metric is the count of all status codes grouped by status code class (e.g. 4xx, 5xx). + +This metric is referenced in the Vitals API with the following label: `status_code_classes_total` + +##### Total Status Codes per Service + +This metric is the total count of each specific status code for a given service. + +This metric is referenced in the Vitals API with the following label: `status_codes_per_service_total` + +##### Total Status Codes per Route + +This metric is the total count of each specific status code for a given route. + +This metric is referenced in the Vitals API with the following label: `status_codes_per_route_total` + +##### Total Status Codes per Consumer +This metric is the total count of each specific status code for a given consumer. + +This metric is referenced in the Vitals API with the following label: `status_codes_per_consumer_total` + +##### Total Status Codes per Consumer Per Route +This metric is the total count of each specific status code for a given consumer and route. + +This metric is referenced in the Vitals API with the following label: `status_codes_per_consumer_route_total` + +## Vitals API +Vitals data is available via endpoints on Kong’s Admin API. Access to these endpoints may be controlled via Admin API RBAC. The Vitals API is described in the attached OAS (Open API Spec, formerly Swagger) file [vitalsSpec.yaml][vitals_spec] + +## Vitals Data Visualization in Kong Manager + +Kong Manager includes visualization of Vitals data. Additional visualizations, dashboarding of Vitals data alongside data from other systems, etc., can be achieved using the Vitals API to integrate with common monitoring systems. + +### Time Frame Control + +A timeframe selector adjacent to Vitals charts in Kong Manager controls the timeframe of data visualized, which indirectly controls the granularity of the data. For example, the “Last 5 Minutes” choice will display 1-second resolution data, while longer time frames will show 1-minute resolution data. + +Timestamps on the x-axis of Vitals charts are displayed either in the browser's local time zone, or in UTC, depending on the UTC option that appears adjacent to Vitals charts. + +### Cluster and Node Data +Metrics can be displayed on Vitals charts at both node and cluster level. Controls are available to show cluster-wide metrics and/or node-specific metrics. Clicking on individual nodes will toggle the display of data from those nodes. Nodes can be identified by a unique Kong node identifier, by hostname, or by a combination of the two. + +### Status Code Data + +Visualizations of cluster-wide status code classes (1xx, 2xx, 3xx, 4xx, 5xx) can be found in the Status Codes page of Kong Manager. This page contains the counts of status code classes graphed over time, as well as the ratio of code classes to total requests. Note: this page does not include non-standard code classes (6xx, 7xx, etc.) Individual status code data can be viewed in the Consumer, Route, and Service details pages under the Activity tab. Both standard and non-standard status codes are visible in these views. + +## Known Issues + +Vitals data does not appear in Kong Manager or the Admin API. +First, make sure Vitals is enabled. (`vitals = on` in your Kong configuration). + +Then, check your log files. If you see `[vitals] kong_vitals_requests_consumers cache is full` or `[vitals] error attempting to push to list: no memory`, then Vitals is no longer able to track requests because its cache is full. This condition may resolve itself if traffic to the node subsides long enough for it to work down the cache. Regardless, the node will continue to proxy requests as usual. + +### Limitations in Cassandra 2.x + +Vitals data is purged regularly: 1-second data is purged after one hour, and 1-minute data is purged after 25 hours. Due to limitations in Cassandra 2.x query options, the counter table vitals_consumers is not purged. If it becomes necessary to prune this table, you will need to do so manually. + +[vitals_spec]: /enterprise/{{page.kong_version}}/admin-api/vitals/vitalsSpec.yaml diff --git a/app/enterprise/1.3-x/admin-api/vitals/vitals-influx-strategy.md b/app/enterprise/1.3-x/admin-api/vitals/vitals-influx-strategy.md new file mode 100644 index 000000000000..aa142a5f1375 --- /dev/null +++ b/app/enterprise/1.3-x/admin-api/vitals/vitals-influx-strategy.md @@ -0,0 +1,135 @@ +--- +title: Kong Vitals with InfluxDB +--- + +## Overview + +This document covers integrating Kong Vitals with a new or existing InfluxDB +time series server or cluster. Leveraging a time series database for Vitals data +can improve request and Vitals performance in very-high traffic Kong Enterprise +clusters (such as environments handling tens or hundreds of thousands of +requests per second), without placing addition write load on the database +backing the Kong cluster. + +For using Vitals with a database as the backend (i.e. PostgreSQL, Cassandra), +please refer to [Kong Vitals](/enterprise/{{page.kong_version}}/admin-api/vitals/). + +## Getting Started + +### Preparing InfluxDB + +This guide assumes an existing InfluxDB server or cluster is already installed +and is accepting write traffic. Production-ready InfluxDB installations should +be deployed as a separate effort, but for proof-of-concept testing, running a +local InfluxDB instance is possible via Docker: + +```bash +$ docker run -p 8086:8086 \ + -v $PWD:/var/lib/influxdb \ + influxdb +``` + +Writing Vitals data to InfluxDB requires that the `kong` database is created. +Currently, this operation must be done manually. This can be done via the +`influx` CLI: + +```bash +influx> create database kong; +``` + +Alternatively the [InfluxDB API](https://docs.influxdata.com/influxdb/v1.7/tools/api/#query-http-endpoint) +may be queried directly to create the database. + +### Configuring Kong + +In addition to enabling Vitals, Kong must be configured to use InfluxDB as the +backing strategy for Vitals. The InfluxDB host and port must also be defined: + +``` +vitals_strategy = influxdb +vitals_tsdb_address = 127.0.0.1:8086 # the IP or hostname, and port, of InfluxDB +``` + +As with other Kong configurations, changes take effect on kong reload or kong +restart. + +## InfluxDB Measurements + +Kong Vitals records metrics in two InfluxDB measurements- `kong_request`, which +contains field values for request latencies and HTTP, and tags for various Kong +entities associated with the requests (e.g., the Route and Service in question, +etc.), and `kong_datastore_cache`, which contains points about cache hits and +misses. Measurement schemas are listed below: + +``` +> show tag keys +name: kong_request +tagKey +------ +consumer +hostname +route +service +status_f +wid +workspace + +name: kong_datastore_cache +tagKey +------ +hostname +wid +``` + +``` +> show field keys +name: kong_request +fieldKey fieldType +-------- --------- +kong_latency integer +proxy_latency integer +request_latency integer +status integer + +name: kong_datastore_cache +fieldKey fieldType +-------- --------- + +hits integer +misses integer +``` + +The tag `wid` is used to differentiate the unique worker ID per host, to avoid +duplicate metrics shipped at the same point in time. + +As demonstrated above, the series cardinality of the `kong_request` measurement +varies based on the cardinality of the Kong cluster configuration - a greater +number of Service/Route/Consumer/Workspace combinations handled by Kong results +in a greater series cardinality as written by Vitals. Please consult the +[InfluxDB sizing guidelines](https://docs.influxdata.com/influxdb/v1.7/guides/hardware_sizing/) +for reference on appropriately sizing an InfluxDB node/cluster. Note that the +query behavior when reading Vitals data falls under the "moderate" load +category as defined by the above document - several `GROUP BY` statements and +functions are used to generate the Vitals API responses, which can require +significant CPU resources to execute when hundreds of thousands or millions of +data points are present. + +## Query Behavior + +Kong buffers Vitals metrics and writes InfluxDB points in batches to improve +throughput in InfluxDB and reduce overhead in the Kong proxy path. Each Kong +worker process flushes its buffer of metrics every 5 seconds or 5000 data points, +whichever comes first. + +Metrics points are written with microsecond (`u`) precision. To comply with +the [Vitals API](/enterprise/{{page.kong_version}}/admin-api/vitals/#vitals-api), measurement +values are read back grouped by second. Note that due to limitations in the +OpenResty API, writing values with microsecond precision requires an additional +syscall per request. + +Currently, Vitals InfluxDB data points are not downsampled or managed via +retention policy by Kong. InfluxDB operators are encouraged to manually manage +the retention policy of the `kong` database to reduce the disk space and memory +needed to manage Vitals data points. Currently, Kong Vitals ignores data points +older than 25 hours; it is safe to create a retention policy with a 25-hour +duration for measurements written by Kong. diff --git a/app/enterprise/1.3-x/admin-api/vitals/vitals-prometheus-strategy.md b/app/enterprise/1.3-x/admin-api/vitals/vitals-prometheus-strategy.md new file mode 100644 index 000000000000..8403b8015155 --- /dev/null +++ b/app/enterprise/1.3-x/admin-api/vitals/vitals-prometheus-strategy.md @@ -0,0 +1,221 @@ +--- +title: Kong Vitals with Prometheus +--- + +For using Vitals with a database as the backend (i.e. PostgreSQL, Cassandra), +please refer to [Kong Vitals](/enterprise/{{page.kong_version}}/admin-api/vitals/). + +## Setup Prometheus environment for Vitals + +### Download Prometheus + +The latest release of Prometheus can be found at the [Prometheus download page](https://prometheus.io/download/#prometheus). + +Prometheus should be running on a separate node from the one running Kong. +For users that are already using Prometheus in their infrastructure, it's +possible to use existing Prometheus nodes as Vitals storage backend. + +In this guide, we assume Prometheus is running on hostname `prometheus-node` +using default config that listens on port `9090`. + +### Download and configure StatsD exporter + +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. + +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 +be downloaded at +[statsd.rules.yaml](/enterprise/{{page.kong_version}}/plugins/statsd.rules.yaml). +Then start StatsD exporter with + +```bash +$ ./statsd_exporter --statsd.mapping-config=statsd.rules.yaml \ + --statsd.listen-unixgram='' +``` + +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) +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). + +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 +in Prometheus Exposition Format are exposed on port `9102`. + +### Configure Prometheus to scrape StatsD exporter + +To configure Prometheus to scrape StatsD exporter, add the following section to +`scrape_configs` in `prometheus.yaml`. + +```yaml +scrape_configs: + - job_name: 'vitals_statsd_exporter' + scrape_interval: "5s" + static_configs: + - targets: ['statsd-node:9102'] +``` + +Please update `statsd-node` with the actual hostname that runs StatsD exporter. + +If you are using service discovery, it will be more convenient to configure +multiple StatsD exporters in Prometheus. Please refer to the +[scape_configs](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#%3Cscrape_config%3E) +section of Prometheus document for further reading. + +By default, the Vitals graph in Kong Manager uses the configured target address +in the legend, which is named `instance` in the Prometheus metrics label. For some service +discovery setups where `instance` is `IP:PORT`, the user might want to relabel the `instance` +label to display a more meaningful hostname in the legend. +To do so, the user can also refer to the [scape_configs](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#%3Cscrape_config%3E) +section and rewrite the `instance` label with the corresponding meta label. + +For example, in a Kubernetes environment, use the following relabel rules: + +```yaml +scrape_configs: + - job_name: 'vitals_statsd_exporter' + kubernetes_sd_configs: + # your SD config to filter statsd exporter pods + relabel_configs: + - source_labels: [__meta_kubernetes_pod_name] + action: replace + target_label: 'instance' +``` + +### Enable Vitals with Prometheus strategy in Kong + +You can change this in your configuration to enable Vitals with Prometheus: + +```bash +# via your Kong configuration file +vitals = on +vitals_strategy = prometheus +vitals_statsd_address = statsd-node:9125 +vitals_tsdb_address = prometheus-node:9090 +``` + +```bash +# or via environment variables +$ export KONG_VITALS=on +$ export KONG_VITALS_STRATEGY=prometheus +$ export KONG_VITALS_STATSD_ADDRESS=statsd-node:9125 +$ export KONG_VITALS_TSDB_ADDRESS=prometheus-node:9090 +``` + +Please update `statsd-node` and `prometheus-node` with the actual hostname that +runs StatsD exporter and Prometheus. + +As with other Kong configurations, your changes take effect on `kong reload` or +`kong restart`. + +If you set `scrape_interval` in Prometheus other than the default value of `5` +seconds, you will also need to update the following: + +```bash +# via your Kong configuration file +vitals_prometheus_scrape_interval = new_value_in_seconds +``` + +```bash +# or via environment variables +$ export KONG_VITALS_PROMETHEUS_SCRAPE_INTERVAL=new_value_in_seconds +``` + +The above option configures `interval` parameter when querying Prometheus. +The value `new_value_in_seconds` should be equal or larger than +`scrape_interval` config in Prometheus. + +You can also configure Kong to send StatsD events with a different prefix from +the default value of `kong`. Make sure the prefix in statsd.rules +is same as that in Kong configuration: + +```bash +# via your Kong configuration file +vitals_statsd_prefix = kong-vitals +``` + +```bash +# or via environment variables +$ export KONG_VITALS_STATSD_PREFIX=kong-vitals +``` + +```yaml +# in statsd.rules +mappings: +# by API +- match: kong-vitals.api.*.request.count + name: "kong_requests_proxy" + labels: + job: "kong_metrics" +# follows other metrics +# ... +``` + +## Tuning and Optimization + +### StatsD exporter UDP buffer + +As the amount of concurrent requests increases, the length of the queue to store +unprocessed UDP events will grow as well. +It's necessary to increase the UDP read buffer size to avoid possible packet +dropping. + +To increase the UDP read buffer for the StatsD exporter process, run the binary +using the following example to set read buffer to around 3 MB: + +``` +$ ./statsd_exporter --statsd.mapping-config=statsd.rules.yaml \ + --statsd.listen-unixgram='' \ + --statsd.read-buffer=30000000 +``` + +To increase the UDP read buffer for the host that's running, adding the +following example line to `/etc/sysctl.conf`: + +``` +net.core.rmem_max = 60000000 +``` + +And then apply the setting with root privilege: + +``` +# sysctl -p +``` + +### StatsD exporter with Unix domain socket + +It is possible to further reduce network overhead by deploying StatsD exporter +on the same node with Kong and let the exporter listen on local Unix domain +socket. + +```bash +$ ./statsd_exporter --statsd.mapping-config=statsd.rules.yaml \ + --statsd.read-buffer=30000000 \ + --statsd.listen-unixgram='/tmp/statsd.sock' +``` + +By default the socket is created with permission `0755`, so that StatsD exporter + has to be running with the same user with Kong to allow Kong to write UDP + packets to the socket. To allow the exporter and Kong to run as different + users, the socket can be created with permission `0777` with the following: + +```bash +$ ./statsd_exporter --statsd.mapping-config=statsd.rules.yaml \ + --statsd.read-buffer=30000000 \ + --statsd.listen-unixgram='/tmp/statsd.sock' \ + --statsd.unixsocket-umask="777" +``` + + +## Accessing Vitals metrics from Prometheus + +You can also access Kong Vitals metrics in Prometheus and display on Grafana +or setup alerting rules. With the example StatsD mapping rules, all metrics are +labeled with `exported_job=kong_vitals`. With the above Prometheus scrape config +above, all metrics are also labeled with `job=vitals_statsd_exporter`. diff --git a/app/enterprise/1.3-x/admin-api/vitals/vitalsSpec.yaml b/app/enterprise/1.3-x/admin-api/vitals/vitalsSpec.yaml new file mode 100644 index 000000000000..78ebda2b54b4 --- /dev/null +++ b/app/enterprise/1.3-x/admin-api/vitals/vitalsSpec.yaml @@ -0,0 +1,734 @@ +swagger: '2.0' +info: + description: Vitals API + version: 1.3.0 + title: Vitals API +basePath: / +tags: + - name: health + description: Stats about the health of a Kong cluster + - name: traffic + description: Stats about traffic routed through Kong +schemes: + - http +paths: + /vitals: + get: + tags: + - vitals + summary: Get information about stats collected + description: '' + operationId: getVitalsInfo + produces: + - application/json + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/VitalsInfo' + /vitals/cluster: + get: + tags: + - health + summary: Get health stats for this Kong cluster + description: '' + operationId: getClusterStats + produces: + - application/json + parameters: + - name: interval + in: query + description: Granularity of the time series (minutes or seconds) + required: true + type: string + - name: start_ts + in: query + description: 'Requested start of the time series, in Unix epoch format (seconds)' + required: true + type: string + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/ClusterVitalsTimeSeriesWithMetadata' + '400': + description: Invalid query params + /vitals/cluster/status_codes: + get: + deprecated: true + tags: + - traffic + summary: Get the status code classes returned across the cluster + description: This operation is deprecated. Use /status_code_classes. + operationId: getClusterStatusCodeStats + produces: + - application/json + parameters: + - name: interval + in: query + description: Granularity of the time series (minutes or seconds) + required: true + type: string + - name: start_ts + in: query + description: 'Requested start of the time series, in Unix epoch format (seconds)' + required: true + type: string + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/ClusterVitalsStatusCodesWithMetadata' + '400': + description: Invalid query params + /vitals/nodes: + get: + tags: + - health + summary: Get health stats for all nodes + description: '' + operationId: getAllNodeStats + produces: + - application/json + parameters: + - name: interval + in: query + description: Granularity of the time series (minutes or seconds) + required: true + type: string + - name: start_ts + in: query + description: 'Requested start of the time series, in Unix epoch format (seconds)' + required: true + type: string + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/NodeVitalsTimeSeriesWithMetadata' + '400': + description: Invalid query params + '/vitals/nodes/{node_id}': + get: + tags: + - health + summary: Get stats for a specific node by UUID + description: '' + operationId: getNodeStatsByID + produces: + - application/json + parameters: + - name: node_id + type: string + in: path + description: Node to retrieve stats for + required: true + - name: interval + in: query + description: Granularity of the time series (minutes or seconds) + required: true + type: string + - name: start_ts + in: query + description: 'Requested start of the time series, in Unix epoch format (seconds)' + required: true + type: string + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/NodeVitalsTimeSeriesWithMetadata' + '400': + description: Invalid query params + '404': + description: Unable to find requested node + '/vitals/consumers/{consumer_id}/cluster': + get: + tags: + - traffic + deprecated: true + summary: Get count of requests for the given consumer across entire cluster + description: This operation is deprecated. Use /vitals/status_codes/by_consumer_and_route + operationId: getConsumerClusterStats + produces: + - application/json + parameters: + - name: consumer_id + type: string + in: path + description: Consumer to retrieve stats for + required: true + - name: interval + type: string + in: query + description: Granularity of the time series (minutes or seconds) + required: true + - name: start_ts + in: query + description: 'Requested start of the time series, in Unix epoch format (seconds)' + required: true + type: string + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/ClusterConsumersTimeSeriesWithMetadata' + '400': + description: Invalid query params + '404': + description: Unable to find requested consumer + /{workspace_name}/vitals/status_code_classes: + get: + tags: + - traffic + summary: Get status code classes for a cluster or workspace. + description: '' + operationId: getStatusCodeClassesByWorkspace + produces: + - application/json + parameters: + - name: workspace_name + type: string + in: path + description: >- + Optional parameter. If provided, returns status code classes for the + workspace; otherwise, returns them for the cluster + required: true + - name: interval + type: string + in: query + description: Granularity of the time series (minutes or seconds) + required: true + - name: start_ts + in: query + description: 'Requested start of the time series, in Unix epoch format (seconds)' + required: true + type: string + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/StatusCodesByEntityMetadata' + '400': + description: Invalid query params + '404': + description: Unable to find requested consumer + /{workspace_name}/vitals/status_codes/by_service: + get: + tags: + - traffic + summary: Get a time series of status codes returned by a given service + description: '' + operationId: getStatusCodesByService + produces: + - application/json + parameters: + - name: service_id + type: string + in: query + description: Service to retrieve status codes for + required: true + - name: interval + type: string + in: query + description: Granularity of the time series (minutes or seconds) + required: true + - name: start_ts + in: query + description: 'Requested start of the time series, in Unix epoch format (seconds)' + required: true + type: string + - name: workspace_name + type: string + in: path + description: >- + This parameter is optional. When present, it limits the result to a + specific workspace. + required: true + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/StatusCodesByEntityTimeSeriesWithMetadata' + '400': + description: Invalid query params + '404': + description: Unable to find requested service + /{workspace_name}/vitals/status_codes/by_route: + get: + tags: + - traffic + summary: Get cluster-wide count of status for a given route + description: '' + operationId: getStatusCodesByRoute + produces: + - application/json + parameters: + - name: route_id + type: string + in: query + description: Route to retrieve status codes for + required: true + - name: interval + type: string + in: query + description: Granularity of the time series (minutes or seconds) + required: true + - name: start_ts + in: query + description: 'Requested start of the time series, in Unix epoch format (seconds)' + required: true + type: string + - name: workspace_name + type: string + in: path + description: >- + This parameter is optional. When present, it limits the result to a + specific workspace. + required: true + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/StatusCodesByEntityTimeSeriesWithMetadata' + '400': + description: Invalid query params + '404': + description: Unable to find requested route + '/{workspace_name}/vitals/status_codes/by_consumer_and_route': + get: + tags: + - traffic + summary: >- + Get status codes for all the routes called by the given consumer in the + given timeframe + description: '' + operationId: getStatusCodesByConsumerAndRoute + produces: + - application/json + parameters: + - name: consumer_id + type: string + in: query + description: Consumer to retrieve status codes for + required: true + - name: interval + type: string + in: query + description: Granularity of the time series (minutes or seconds) + required: true + - name: start_ts + in: query + description: 'Requested start of the time series, in Unix epoch format (seconds)' + required: true + type: string + - name: workspace_name + type: string + in: path + description: >- + This parameter is optional. When present, it limits the result to a + specific workspace. + required: true + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/StatusCodesByEntityTimeSeriesWithMetadata' + '400': + description: Invalid query params + '404': + description: Unable to find requested consumer +definitions: + ClusterVitalsMetadata: + properties: + level: + type: string + example: cluster + enum: + - cluster + - node + workspace_id: + type: string + description: UUID of workspace this time series is for + interval: + type: string + example: seconds + enum: + - seconds + - minutes + interval_width: + type: number + example: 60 + earliest_ts: + type: integer + example: 1514508300 + latest_ts: + type: integer + example: 1514508480 + stat_labels: + type: array + items: + type: string + example: + - cache_datastore_hits_total + - cache_datastore_misses_total + - latency_proxy_request_min_ms + - latency_proxy_request_max_ms + - latency_upstream_min_ms + - latency_upstream_max_ms + - requests_proxy_total + - latency_proxy_request_avg_ms + - latency_upstream_avg_ms + StatusCodesByEntityMetadata: + properties: + entity_type: + type: string + example: service|route + entity_id: + type: string + example: + level: + type: string + example: cluster + enum: + - cluster + workspace_id: + type: string + description: UUID of the workspace this time series is for + interval: + type: string + example: seconds + enum: + - seconds + - minutes + interval_width: + type: number + example: 60 + earliest_ts: + type: integer + example: 1514508300 + latest_ts: + type: integer + example: 1514508480 + stat_labels: + type: array + items: + type: string + example: + - status_codes_service|route_total + StatusCodesByEntityTimeSeriesWithMetadata: + type: object + properties: + meta: + $ref: '#/definitions/StatusCodesByEntityMetadata' + stats: + $ref: '#/definitions/StatusCodesByEntityStats' + ClusterVitalsStatusCodesMetadata: + properties: + level: + type: string + example: cluster + enum: + - cluster + interval: + type: string + example: seconds + enum: + - seconds + - minutes + interval_width: + type: number + example: 60 + earliest_ts: + type: integer + example: 1514508300 + latest_ts: + type: integer + example: 1514508480 + stat_labels: + type: array + items: + type: string + example: + - status_code_classes_total + ClusterVitalsStats: + properties: + cluster: + type: object + properties: + : + type: array + items: + type: integer + description: >- + List of stat values collected at "timestamp_n", in same order as + "meta.stat_labels" + example: + - 999 + - 130 + - 0 + - 35 + - 142 + - 528 + - 1146 + - 110 + - 156 + StatusCodesByEntityStats: + properties: + cluster: + type: object + description: Vitals status codes data available at the cluster level + properties: + : + type: object + properties: + : + type: integer + description: >- + The total count of a particular status code for the time + period + example: 1824 + ClusterVitalsStatusCodesStats: + properties: + cluster: + type: object + description: Vitals status codes data available at the cluster level + properties: + : + type: object + properties: + : + type: integer + description: >- + The total count of a particular status code class for the time + period + example: 1824 + ClusterVitalsTimeSeriesWithMetadata: + type: object + properties: + meta: + $ref: '#/definitions/ClusterVitalsMetadata' + stats: + $ref: '#/definitions/ClusterVitalsStats' + ClusterVitalsStatusCodesWithMetadata: + type: object + properties: + meta: + $ref: '#/definitions/ClusterVitalsStatusCodesMetadata' + stats: + $ref: '#/definitions/ClusterVitalsStatusCodesStats' + ClusterConsumersMetadata: + properties: + level: + type: string + example: cluster + enum: + - cluster + - node + interval: + type: string + example: seconds + enum: + - seconds + - minutes + interval_width: + type: number + example: 60 + earliest_ts: + type: integer + example: 1514508300 + latest_ts: + type: integer + example: 1514508480 + stat_labels: + type: array + items: + type: string + example: + - requests_consumer_total + ClusterConsumersStats: + properties: + cluster: + type: object + properties: + : + type: integer + description: >- + List of stat values collected at "timestamp_n", in same order as + "meta.stat_labels" + example: 47 + ClusterConsumersTimeSeriesWithMetadata: + type: object + properties: + meta: + $ref: '#/definitions/ClusterConsumersMetadata' + stats: + $ref: '#/definitions/ClusterConsumersStats' + NodeVitalsMetadata: + properties: + level: + type: string + example: node + enum: + - cluster + - node + workspace_id: + type: string + description: UUID of the workspace this time series is for + interval: + type: string + example: seconds + enum: + - seconds + - minutes + interval_width: + type: number + example: 60 + earliest_ts: + type: integer + example: 1514508300 + latest_ts: + type: integer + example: 1514508480 + stat_labels: + type: array + items: + type: string + example: + - cache_datastore_hits_total + - cache_datastore_misses_total + - latency_proxy_request_min_ms + - latency_proxy_request_max_ms + - latency_upstream_min_ms + - latency_upstream_max_ms + - requests_proxy_total + - latency_proxy_request_avg_ms + - latency_upstream_avg_ms + nodes: + type: object + description: >- + table of node ids that contributed to this time series. This element + is not included on cluster-level requests. + properties: + : + type: object + description: The id of a node included in this time series. + properties: + hostname: + type: string + description: The name of the host where this node runs + NodeVitalsStats: + properties: + : + type: object + description: >- + The node this time series is for, or "cluster" if it's a cluster-level + time series. + properties: + : + type: array + items: + type: integer + description: >- + List of stat values collected at "timestamp_n", in same order as + "meta.stat_labels" + example: + - 999 + - 130 + - 0 + - 35 + - 142 + - 528 + - 1146 + - 110 + - 156 + NodeVitalsTimeSeriesWithMetadata: + type: object + properties: + meta: + $ref: '#/definitions/NodeVitalsMetadata' + stats: + $ref: '#/definitions/NodeVitalsStats' + VitalsInfo: + type: object + example: + stats: + cache_datastore_hits_total: + levels: + cluster: + intervals: + minutes: + retention_period_seconds: 90000 + seconds: + retention_period_seconds: 3600 + nodes: + intervals: + minutes: + retention_period_seconds: 90000 + seconds: + retention_period_seconds: 3600 + properties: + stats: + type: object + properties: + : + type: object + properties: + levels: + type: object + description: >- + Vitals data is tracked and aggregated at different levels (per + cluster, per node) + properties: + cluster: + type: object + description: Vitals data available at the cluster level + properties: + intervals: + type: object + description: >- + Vitals data is available at different intervals + (seconds, minutes) + properties: + minutes: + type: object + properties: + retention_period_seconds: + type: integer + description: >- + Configured retention period (in seconds) for + the minutes interval + seconds: + type: object + properties: + retention_period_seconds: + type: integer + description: >- + Configured retention period (in seconds) for + the seconds interval + nodes: + type: object + description: Vitals data available at the node level + properties: + intervals: + type: object + description: >- + Vitals data is available at different intervals + (seconds, minutes) + properties: + minutes: + type: object + properties: + retention_period_seconds: + type: integer + description: >- + Configured retention period (in seconds) for + the minutes interval + seconds: + type: object + properties: + retention_period_seconds: + type: integer + description: >- + Configured retention period (in seconds) for + the seconds interval diff --git a/app/enterprise/1.3-x/admin-api/workspaces/examples.md b/app/enterprise/1.3-x/admin-api/workspaces/examples.md new file mode 100644 index 000000000000..f7714120ebf3 --- /dev/null +++ b/app/enterprise/1.3-x/admin-api/workspaces/examples.md @@ -0,0 +1,491 @@ +--- +title: Workspace Examples +book: workspaces +--- + +## Introduction + +This chapter aims to provide a step-by-step tutorial on how to set up +workspaces, entities, and see it in action. + +## Important Note: Conflicting APIs or Routes in workspaces + +Workspaces provide a way to segment Kong entities—entities in a workspace +are isolated from those in other workspaces. That said, entities +such as APIs and Routes have "routing rules", which are pieces of info +attached to APIs or Routes—such as HTTP method, URI, or host—that allow a +given proxy-side request to be routed to its corresponding upstream service. + +Admins configuring APIs (or Routes) in their workspaces do not want traffic +directed to their APIs or Routes to be swallowed by APIs or Routes in other +workspaces; Kong allows them to prevent such undesired behavior—as long as +certain measures are taken. Below we outline the conflict detection algorithm +used by Kong to determine if a conflict occurs. + +* At API or Route **creation or modification** time, Kong runs its internal +router: + - If no APIs or Routes are found with matching routing rules, the creation + or modification proceeds + - If APIs or Routes with matching routing rules are found **within the same + workspace**, proceed + - If APIs or Routes are found **in a different workspace**: + * If the matching API or Route **does not have an associated + `host` value**—`409 Conflict` + * If the matching API or Route's `host` is a wildcard + - If they are the same, a conflict is reported—`409 Conflict` + - If they are not equal, proceed + * If the matching API or Route's `host` is an absolute value, a + conflict is reported—`409 Conflict` + +## The Default workspace + +Kong creates a default workspace—unsurprisingly named `default`—whose goal +is to group all existing entities in Kong, where "existing entities" refers to: + +- Entities that were created in operation in previous versions & in case +one is migrating from an older Kong version; +- Entities that Kong creates at migration time—e.g., RBAC credentials, which +are provisioned at migration time as a convenience + +It will also hold entities that are created without being explicitly assigned to +a specific workspace. + +That said, it's worth noting that the default workspace is a workspace as any +other, the only difference being that it's created by Kong, at migration time. + +(Examples will be shown using the httpie HTTP command line client.) + +## Listing workspaces and its entities + +In a fresh Kong Enterprise install—or one just migrated to 0.33—submit the +following request: + +``` +http GET :8001/workspaces +{ + "total": 1, + "data": [ + { + "created_at": 1529627841000, + "id": "a43fc3f9-98e4-43b0-b703-c3b1004980d5", + "name": "default" + } + ] +} +``` + +## List entities in the default workspace + +To get a list of entities contained in—or referenced by—the default workspace, +let's issue the following request: + +``` +http GET :8001/workspaces/default/entities +{ + "data": [ + { + "workspace_id": "a43fc3f9-98e4-43b0-b703-c3b1004980d5", + "entity_id": "a43fc3f9-98e4-43b0-b703-c3b1004980d5", + "entity_type": "workspaces", + }, + { + "workspace_id": "a43fc3f9-98e4-43b0-b703-c3b1004980d5", + "entity_id": "e6b5f24a-8914-40b3-a1f5-02e88b33b1d3", + "entity_type": "portal_files", + }, + { + "workspace_id": "a43fc3f9-98e4-43b0-b703-c3b1004980d5", + "entity_id": "ee7a43f0-c4e5-4533-8000-5e8bd459049f", + "entity_type": "portal_files", + }, + ... + { + "workspace_id": "a43fc3f9-98e4-43b0-b703-c3b1004980d5", + "entity_id": "74e706b6-4f0d-411c-9369-55a61ecc5fa8", + "entity_type": "portal_files", + }, + ], + "total": 42 +} +``` + +As can be seen, a total of 42 entities were part of the default workspace—for +brevity, most of them were redacted here. + +## Creating a workspace and adding entities to it + +A more interesting example would be segmenting entities by teams; for the sake of +example, let's say they are teamA, teamB, and teamC. + +Each of these teams has its own set of entities—say, upstream services and +routes—and want to segregate their configurations and traffic; they can +achieve that with workspaces. + +``` +http POST :8001/workspaces name=teamA +{ + "created_at": 1528843468000, + "id": "735af96e-206f-43f7-88f0-b930d5fd4b7e", + "name": "teamA" +} +``` + +``` +http POST :8001/workspaces name=teamB +{ + "name": "teamB", + "created_at": 1529628574000, + "id": "a25728ac-6036-497c-82ee-524d4c22fcae" +} +``` + +``` +http POST :8001/workspaces name=teamC +{ + "name": "teamC", + "created_at": 1529628622000, + "id": "34b28f10-e1ec-4dad-9ac0-74780baee182" +} +``` + +At this point, if we list workspaces, we will get a total of 4—remember, +Kong provisions a "default" workspace and, on top of that, we created other +3. + +``` +{ + "data": [ + { + "created_at": 1529627841000, + "id": "a43fc3f9-98e4-43b0-b703-c3b1004980d5", + "name": "default" + }, + { + "created_at": 1529628818000, + "id": "5ed1c043-78cc-4fe2-924e-40b17ecd97bc", + "name": "teamA" + }, + { + "created_at": 1529628574000, + "id": "a25728ac-6036-497c-82ee-524d4c22fcae", + "name": "teamB" + }, + { + "created_at": 1529628622000, + "id": "34b28f10-e1ec-4dad-9ac0-74780baee182", + "name": "teamC" + } + ] + "total": 4, +} + +``` + +Having our teams' workspaces set up, let's add some entities to them. Say +they have a shared service—represented by the [Service][services] Kong +entity—and different routes associated with this upstream service. + +Creating the shared service: + +``` +http :8001/services url=http://httpbin.org/ name=shared-service +{ + "host": "httpbin.org", + "created_at": 1529699798, + "connect_timeout": 60000, + "id": "86608199-e3d8-48aa-b76d-d9ec36d8d445", + "protocol": "http", + "name": "shared-service", + "read_timeout": 60000, + "port": 80, + "path": "/", + "updated_at": 1529699798, + "retries": 5, + "write_timeout": 60000 +} +``` + +Notice the endpoint `/services` does not include a workspace prefix—which +is how one specifies the workspace under which a given API call applies to. +In such cases, the call applies to the `default` workspace. Let's confirm that +by listing all entities under the `default` workspace: + +``` +http :8001/workspaces/default/entities +{ + "data": [ + ... + { + "workspace_id": "dd516707-919e-4e72-9fd8-12f63a80a662", + "unique_field_name": "name", + "entity_id": "86608199-e3d8-48aa-b76d-d9ec36d8d445", + "entity_type": "services", + "unique_field_value": "shared-service" + } + ], + "total": 43 +} +``` + +Again, entities not relevant for this example were redacted; notice, though, +that our shared service is on the list. + +The next step is to add the shared service to our teams' workspaces. This can be +done as follows: + +``` +http :8001/workspaces/teamA/entities entities=86608199-e3d8-48aa-b76d-d9ec36d8d445 +http :8001/workspaces/teamB/entities entities=86608199-e3d8-48aa-b76d-d9ec36d8d445 +http :8001/workspaces/teamC/entities entities=86608199-e3d8-48aa-b76d-d9ec36d8d445 +``` + +To confirm the shared service was added, + +``` +http :8001/teamA/services +{ + "next": null, + "data": [ + { + "host": "httpbin.org", + "created_at": 1529699798, + "connect_timeout": 60000, + "id": "86608199-e3d8-48aa-b76d-d9ec36d8d445", + "protocol": "http", + "name": "shared-service", + "read_timeout": 60000, + "port": 80, + "path": "/", + "updated_at": 1529699798, + "retries": 5, + "write_timeout": 60000 + } + ] +} +``` + +The next step is to set up each team's routes to the shared service. Let's say +Team A, B, and C have routes `/headers`, `/ip`, and `/user-agent`, respectively. + +Putting into action, we have: + +``` +http POST :8001/teamA/routes paths[]=/headers service.id=86608199-e3d8-48aa-b76d-d9ec36d8d445 strip_path=false -f +{ + "created_at": 1529702016, + "hosts": null, + "id": "1850216b-35a2-4038-8544-34f58c7701f1", + "methods": null, + "paths": [ + "/headers" + ], + "preserve_host": false, + "protocols": [ + "http", + "https" + ], + "regex_priority": 0, + "service": { + "id": "86608199-e3d8-48aa-b76d-d9ec36d8d445" + }, + "strip_path": false, + "updated_at": 1529702016 +} +``` + +``` +http POST :8001/teamB/routes paths[]=/ip service.id=86608199-e3d8-48aa-b76d-d9ec36d8d445 strip_path=false -f +{ + "created_at": 1529702211, + "hosts": null, + "id": "c804699c-e492-4e33-96e1-c2398bc79986", + "methods": null, + "paths": [ + "/ip" + ], + "preserve_host": false, + "protocols": [ + "http", + "https" + ], + "regex_priority": 0, + "service": { + "id": "86608199-e3d8-48aa-b76d-d9ec36d8d445" + }, + "strip_path": false, + "updated_at": 1529702211 +} +``` + +``` +http POST :8001/teamC/routes paths[]=/user-agent service.id=86608199-e3d8-48aa-b76d-d9ec36d8d445 strip_path=false -f +{ + "created_at": 1529702339, + "hosts": null, + "id": "bbaac9db-52b3-46fe-bb2a-e9af2968aee9", + "methods": null, + "paths": [ + "/user-agent" + ], + "preserve_host": false, + "protocols": [ + "http", + "https" + ], + "regex_priority": 0, + "service": { + "id": "86608199-e3d8-48aa-b76d-d9ec36d8d445" + }, + "strip_path": false, + "updated_at": 1529702339 +} +``` + +Ready—now we have all teams with their routes sharing the same service! + +To make sure it's set up correctly, let's list the routes in each workspace. + +``` +http :8001/teamA/routes +{ + "next": null, + "data": [ + { + "created_at": 1529702016, + "id": "1850216b-35a2-4038-8544-34f58c7701f1", + "hosts": null, + "updated_at": 1529702016, + "preserve_host": false, + "regex_priority": 0, + "service": { + "id": "86608199-e3d8-48aa-b76d-d9ec36d8d445" + }, + "paths": [ + "/headers" + ], + "methods": null, + "strip_path": false, + "protocols": [ + "http", + "https" + ] + } + ] +} +``` + +As we wanted, Team A has a `/headers` route pointing to the shared service. + +``` +http :8001/teamB/routes +{ + "next": null, + "data": [ + { + "created_at": 1529702211, + "id": "c804699c-e492-4e33-96e1-c2398bc79986", + "hosts": null, + "updated_at": 1529702211, + "preserve_host": false, + "regex_priority": 0, + "service": { + "id": "86608199-e3d8-48aa-b76d-d9ec36d8d445" + }, + "paths": [ + "/ip" + ], + "methods": null, + "strip_path": false, + "protocols": [ + "http", + "https" + ] + } + ] +} +``` + +Team B has its `/ip` route. + +``` +http :8001/teamC/routes +{ + "next": null, + "data": [ + { + "created_at": 1529702339, + "id": "bbaac9db-52b3-46fe-bb2a-e9af2968aee9", + "hosts": null, + "updated_at": 1529702339, + "preserve_host": false, + "regex_priority": 0, + "service": { + "id": "86608199-e3d8-48aa-b76d-d9ec36d8d445" + }, + "paths": [ + "/user-agent" + ], + "methods": null, + "strip_path": false, + "protocols": [ + "http", + "https" + ] + } + ] +} +``` + +and Team C has its `/user-agent` route. + +With this setup, Teams A, B, and C only have access to their own Routes +entities through the Admin API. (Additionally, with RBAC's additional control, +granular read/write/delete/update rights can be further assigned to workspaces, +allowing flexible intra and inter-team permissioning schemes.) + +## Entities in different workspaces can have the same name! + +Different teams—belonging to different workspaces—are allowed to give any +name to their entities. To provide an example of that, let's say that Teams A, B, +and C want a particular consumer named `guest`—a different consumer for each +team, sharing the same username. + +``` +http :8001/teamA/consumers username=guest +{ + "created_at": 1529703386000, + "id": "2e230275-2a4a-41fd-b06b-bae37008aed2", + "type": 0, + "username": "guest" +} +``` + +``` +http :8001/teamB/consumers username=guest +{ + "created_at": 1529703390000, + "id": "8533e404-8d56-4481-a919-0ee35b8a768c", + "type": 0, + "username": "guest" +} +``` + +``` +http :8001/teamC/consumers username=guest +{ + "created_at": 1529703393000, + "id": "5fb180b0-0cd0-42e1-8d75-ce42a54b2909", + "type": 0, + "username": "guest" +} +``` + +With this, Teams A, B, and C will have the freedom to operate their `guest` +consumer independently, choosing authentication plugins or doing any other +operation that is allowed in the non-workspaced Kong world. + +Next: [RBAC Overview ›](/enterprise/{{page.kong_version}}/rbac/overview) + +--- + +[services]: /{{page.kong_version}}/admin-api/#service-object diff --git a/app/enterprise/1.3-x/admin-api/workspaces/reference.md b/app/enterprise/1.3-x/admin-api/workspaces/reference.md new file mode 100644 index 000000000000..4e376a4b1e59 --- /dev/null +++ b/app/enterprise/1.3-x/admin-api/workspaces/reference.md @@ -0,0 +1,490 @@ +--- +title: Workspaces Reference +book: workspaces + +workspace_body: | + Attribute | Description + ---:| --- + `name` | The **Workspace** name. + +workspace_entities_body: | + Attribute | Description + ---:| --- + `entities`| Comma-delimited list of entity identifiers +--- + +## Introduction + +Kong Enterprise's Workspaces feature is configurable through Kong's +[Admin API]. + +## Workspace Object + +The **Workspace** object describes the **Workspace** entity, which has an ID +and a name. + +### Add Workspace + +**Endpoint** + +
/workspaces/
+ +#### Request Body + +{{ page.workspace_body }} + +**Response** + +``` +HTTP 201 Created +``` + +```json +{ + "comment": null, + "config": { + "meta": null, + "portal": false, + "portal_access_request_email": null, + "portal_approved_email": null, + "portal_auth": null, + "portal_auth_conf": null, + "portal_auto_approve": null, + "portal_cors_origins": null, + "portal_developer_meta_fields": "[{\"label\":\"Full Name\",\"title\":\"full_name\",\"validator\":{\"required\":true,\"type\":\"string\"}}]", + "portal_emails_from": null, + "portal_emails_reply_to": null, + "portal_invite_email": null, + "portal_reset_email": null, + "portal_reset_success_email": null, + "portal_token_exp": null + }, + "created_at": 1557441226, + "id": "c663cca5-c6f6-474a-ae44-01f62aba16a9", + "meta": { + "color": null, + "thumbnail": null + }, + "name": "green-team" +} +``` + +### List Workspaces + +**Endpoint** + +
/workspaces/
+ +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "data": [ + { + "comment": null, + "config": { + "meta": null, + "portal": false, + "portal_access_request_email": null, + "portal_approved_email": null, + "portal_auth": null, + "portal_auth_conf": null, + "portal_auto_approve": null, + "portal_cors_origins": null, + "portal_developer_meta_fields": "[{\"label\":\"Full Name\",\"title\":\"full_name\",\"validator\":{\"required\":true,\"type\":\"string\"}}]", + "portal_emails_from": null, + "portal_emails_reply_to": null, + "portal_invite_email": null, + "portal_reset_email": null, + "portal_reset_success_email": null, + "portal_token_exp": null + }, + "created_at": 1557419951, + "id": "00000000-0000-0000-0000-000000000000", + "meta": { + "color": null, + "thumbnail": null + }, + "name": "default" + }, + { + "comment": null, + "config": { + "meta": null, + "portal": false, + "portal_access_request_email": null, + "portal_approved_email": null, + "portal_auth": null, + "portal_auth_conf": null, + "portal_auto_approve": null, + "portal_cors_origins": null, + "portal_developer_meta_fields": "[{\"label\":\"Full Name\",\"title\":\"full_name\",\"validator\":{\"required\":true,\"type\":\"string\"}}]", + "portal_emails_from": null, + "portal_emails_reply_to": null, + "portal_invite_email": null, + "portal_reset_email": null, + "portal_reset_success_email": null, + "portal_token_exp": null + }, + "created_at": 1557441226, + "id": "c663cca5-c6f6-474a-ae44-01f62aba16a9", + "meta": { + "color": null, + "thumbnail": null + }, + "name": "green-team" + } + ], + "next": null +} +``` + +### Update or Create a Workspace + +**Endpoint** + +
/workspaces/{id}
+ +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. + +#### Request Body + +Attribute | Description +---:| --- +`name` | The **Workspace** name. + +**Response** + +If creating the entity: + +``` +HTTP 201 Created +``` + +If replacing the entity: + +``` +HTTP 200 OK +``` + +```json +{ + "comment": null, + "config": { + "meta": null, + "portal": false, + "portal_access_request_email": null, + "portal_approved_email": null, + "portal_auth": null, + "portal_auth_conf": null, + "portal_auto_approve": null, + "portal_cors_origins": null, + "portal_developer_meta_fields": "[{\"label\":\"Full Name\",\"title\":\"full_name\",\"validator\":{\"required\":true,\"type\":\"string\"}}]", + "portal_emails_from": null, + "portal_emails_reply_to": null, + "portal_invite_email": null, + "portal_reset_email": null, + "portal_reset_success_email": null, + "portal_token_exp": null + }, + "created_at": 1557504202, + "id": "c663cca5-c6f6-474a-ae44-01f62aba16a9", + "meta": { + "color": null, + "thumbnail": null + }, + "name": "rocket-team" +} +``` + +### 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 + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "config": { + "portal": false, + "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": { }, + "name": "rocket-team" +} +``` + +### Retrieve Workspace Metadata + +#### Endpoint + +
/workspaces/{name or id}/meta
+ +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the **Workspace** to retrieve + +#### Response + +``` +HTTP 200 OK +``` + +```json +{ + "counts": { + "acls": 1, + "apis": 1, + "basicauth_credentials": 1, + "consumers": 1234, + "files": 41, + "hmacauth_credentials": 1, + "jwt_secrets": 1, + "keyauth_credentials": 1, + "oauth2_authorization_codes": 1, + "oauth2_credentials": 1, + "oauth2_tokens": 1, + "plugins": 5, + "rbac_roles": 3, + "rbac_users": 12, + "routes": 15, + "services": 2, + "ssl_certificates": 1, + "ssl_servers_names": 1, + "targets": 1, + "upstreams": 1 + } +} +``` + +### Delete a Workspace + +**Endpoint** + +
/workspaces/{name or id}
+ +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 +**Workspace** itself can be. + +**Response** + +``` +HTTP 204 No Content +``` + +### Update a Workspace + +**Endpoint** + +
/workspaces/{name or id}
+ +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** + +The behavior of `PATCH` endpoints prevents the renaming of a **Workspace**. + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "comment": "this is a sample comment in the patch request", + "config": { + "meta": null, + "portal": false, + "portal_access_request_email": null, + "portal_approved_email": null, + "portal_auth": null, + "portal_auth_conf": null, + "portal_auto_approve": null, + "portal_cors_origins": null, + "portal_developer_meta_fields": "[{\"label\":\"Full Name\",\"title\":\"full_name\",\"validator\":{\"required\":true,\"type\":\"string\"}}]", + "portal_emails_from": null, + "portal_emails_reply_to": null, + "portal_invite_email": null, + "portal_reset_email": null, + "portal_reset_success_email": null, + "portal_token_exp": null + }, + "created_at": 1557509909, + "id": "c543d2c8-d297-4c9c-adf5-cd64212868fd", + "meta": { + "color": null, + "thumbnail": null + }, + "name": "green-team" +} +``` + +### Add entities to a Workspace + +Workspaces are groups of entities. This endpoint allows one to add an entity, +identified by its unique identifier, to a **Workspace**. + +**Endpoint** + +
/workspaces/{name or id}/entities
+ +#### Request Body + +{{ page.workspace_entities_body }} + +**Response** + +``` +HTTP 200 Created +``` + +```json +[ + { + "connect_timeout": 60000, + "created_at": 1557510770, + "host": "httpbin.com", + "id": "8e15ca43-1d14-4f58-8f05-0327af74b5c5", + "name": "testservice", + "port": 80, + "protocol": "http", + "read_timeout": 60000, + "retries": 5, + "updated_at": 1557510770, + "write_timeout": 60000 + } +] +``` + +The response is the representation of the entity that was added to the +workspace—in this case, a Service. + +### List entities that are part of a Workspace + +**Endpoint** + +
/workspaces/{name or id}/entities
+ +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "data": [ + { + "entity_id": "8e15ca43-1d14-4f58-8f05-0327af74b5c5", + "entity_type": "services", + "unique_field_name": "name", + "unique_field_value": "testservice", + "workspace_id": "c543d2c8-d297-4c9c-adf5-cd64212868fd", + "workspace_name": "green-team" + }, + { + "entity_id": "8e15ca43-1d14-4f58-8f05-0327af74b5c5", + "entity_type": "services", + "unique_field_name": "id", + "unique_field_value": "8e15ca43-1d14-4f58-8f05-0327af74b5c5", + "workspace_id": "c543d2c8-d297-4c9c-adf5-cd64212868fd", + "workspace_name": "green-team" + } + ], + "total": 2 +} +``` + +In this case, the **Workspace** references two Services. + +### Delete entities from a Workspace + +**Endpoint** + +
/workspaces/{name or id}/entities
+ +#### Request Body + +{{ page.workspace_entities_body }} + +**Response** + +``` +HTTP 204 No Content +``` + +### Retrieve an entity from a Workspace + +This endpoint allows one to retrieve an entity from a workspace—useful, say, +for checking if a given entity is part of a given **Workspace**. + +**Endpoint** + +
/workspaces/{name or id}/entities/{name or id}
+ +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "entity_id": "8e15ca43-1d14-4f58-8f05-0327af74b5c5", + "entity_type": "services", + "workspace_id": "c543d2c8-d297-4c9c-adf5-cd64212868fd", + "workspace_name": "green-team" +} +``` + +### Delete a particular entity from a Workspace + +**Endpoint** + +
/workspaces/{name or id}/entities/{name or id}
+ +**Response** + +``` +HTTP 204 No Content +``` + +--- + +[Admin API]: /enterprise/{{page.kong_version}}/admin-api/ diff --git a/app/enterprise/1.3-x/auth.md b/app/enterprise/1.3-x/auth.md new file mode 100644 index 000000000000..f190620128e8 --- /dev/null +++ b/app/enterprise/1.3-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/1.3-x/brain-immunity/install-configure.md b/app/enterprise/1.3-x/brain-immunity/install-configure.md new file mode 100644 index 000000000000..f1430613b524 --- /dev/null +++ b/app/enterprise/1.3-x/brain-immunity/install-configure.md @@ -0,0 +1,716 @@ +--- +title: Kong Brain & Kong Immunity Installation and Configuration Guide +--- + + +### Introduction +**Kong Brain** and **Kong Immunity** help automate the entire API and service development life cycle. By automating processes for configuration, traffic analysis and the creation of documentation, Kong Brain and Kong Immunity help organizations improve efficiency, governance, reliability and security. Kong Brain automates API and service documentation and Kong Immunity uses advanced machine learning to analyze traffic patterns to diagnose and improve security. + +### Overview + +#### Kong Collector Plugin + +Kong Collector Plugin (Collector) configuration includes: + +* Kong Collector Plugin is included with Kong Enterprise, and used by Kong Brain and (optional) Kong Immunity. +* Configure the Collector, and Kong Brain is automatically enabled. +* If you have Kong Immunity, configure the Collector and Kong Immunity is automatically enabled. + +#### Kong Brain + +Kong Brain (Brain) features include: + +* Kong Brain uses the real-time Kong Collector Plugin. +* Once the Collector is configured, Kong Brain is automatically enabled. +* Kong Brain ingests your documentation and data flows, analyze changes and take action. +* Users can create workflows and approve changes directly in Kong Manager. +* Visually map services using the real-time Kong Service Map. + +#### Kong Immunity + +Kong Immunity (Immunity) features include: + +* Kong Immunity is optional. +* Once the Collector is configured, Kong Immunity is automatically enabled. +* View Kong Immunity alerts in the Kong Service Map and take action with just a few clicks. +* Instantly diagnose issues. Receive Slack alerts notifying users of anomalies that require attention. + +#### Kong Service Map + +* For information about the Kong Service Map, see **Using Kong’s Service Map**. + + +### Configure the Kong Collector Plugin + +#### Prerequisites + +Prerequisites for installing the Collector include: + +* A working Kong Enterprise system using Kong Enterprise 0.35.3+ or later, with a minimum of one Kong node and a working data store (PostgreSQL or Cassandra). +* Access to a platform for the Collector which has Docker installed. This system must be networked to “talk” to the Kong Enterprise system on which the Collector is installed. +* Bintray access credentials (supplied by Kong) to access the downloads. + +#### Overview + +With the Collector, Kong Enterprise collects, coalesces and stores requests made through Kong. This plugin makes a copy of requests through Kong (not affecting the hot path) which are “Teed” to Kong Brain and/or Kong Immunity platforms. See the diagram below for a visual of how Kong Collector Plugin works with Kong Enterprise. + +#### Configuration Order + +Configure the Collector in the following order, with configuration steps provided below: + +1. Deploy the Collector Plugin, which captures and sends traffic to the Collector for collection/processing. +2. Deploy and start the Collector infrastructure on your Docker aware platform. +3. Configure the components to talk to one another. +4. Test their configuration. + +#### Deploy the Collector + +Deploy the Collector Plugin from the Kong Manager or the Admin API: + +``` +$ http --form POST http://:8001//plugins name=collector config.service_token=foo config.host= config.port=5000 config.https=false config.log_bodies=true +``` + +It is possible to set up the Collector to only be applied to specific routes or services, by adding `route.id=` or `service.id=` to the request. +``` +$ http --form POST http://:8001//plugins name=collector config.service_token=foo config.host= config.port=5000 config.https=false config.log_bodies=true route.id=` +``` + + +### Configure the Collector + +#### Bintray Credentials + +Bintray is the download location for the files needed to install and run Brain and Immunity. Log in to Bintray and retrieve your BINTRAY_USERNAME and BINTRAY_API_KEY to proceed with the download. + +1. Getting BINTRAY_USERNAME: +2. Getting BINTRAY_API_KEY: + +Go to “Edit Profile”. + +1. Choose “API Key”. + +#### Setting up with Docker Compose + +The information needed to run the full Collector, Brain, and Immunity system is included in the docker-compose files. This starts several docker containers: a database, a collector, a worker and a scheduler. +Kong provides a private docker image that is used by the compose files. This image is distributed by Bintray, and for access, the following is required: + +1. Your Bintray User ID +2. Your Bintray API key +3. A system (where you want to run Brain and/or Immunity) with Docker installed and ready to run +4. A system (where you want to run Brain and/or Immunity) with Docker-compose installed and ready to run + +Your Bintray credentials should be furnished to you upon purchase of Kong Enterprise. If you do not have them, contact Kong Support to get a new copy. +First you must ssh/putty into your running instance where Brain and Immunity system will be installed. Then, log into Docker. +Command: +``` +sudo docker login -u -p kong-docker-kong-brain-immunity-base.bintray.io +``` + +Example: +``` +$ sudo docker login -u kongUser -p ef27888aba233eggg8889eeee9454ca67ca9b1aa8bdd kong-docker-kong-brain-immunity-base.bintray.io +``` +If you see “permission denied”, make sure you have run the above command as “sudo”. +Next, pull down the files Docker Compose will need. +Command: + +``` +wget https://:@kong.bintray.com/kong-brain-immunity-base/docker-compose.zip +``` + +Example: +``` +$ wget https://kong_user:ef27888aba233eefffffeef669454ca67ca9b1aa8bdd@kong.bintray.com/kong-brain-immunity-base/docker-compose.zip +``` + +If successful, you should see docker-compose.zip in your current dir. Unzip the package into the dir of your choice. +Next, run Docker Compose using the files to install Brain. Start the instances with docker-compose: +Command: +``` +KONG_HOST= KONG_PORT=<8001> docker-compose -f docker-compose.yml -f with-db.yml -f with-redis.yml up --remove-orphans` +`a +``` + +``` +`KONG_HOST - the public IP address or Hostname of the system which is running Brain` +`KONG_PORT - Usually 8001 but may be set otherwise` +``` + +Example: +``` +`$ sudo KONG_HOST=13.57.208.156 KONG_PORT=8001 docker-compose -f docker-compose.yml -f with-db.yml -f with-redis.yml up --remove-orphans` +``` + +If you get an error which mentions “empty string”, make sure you run the above command with sudo. +If the command is running successfully, you should see downloads occurring similar to the following: + +#### Opt-Out of Har Redaction + +Collector will default to NOT storing body data values and attachments in traffic data. You can see this as viewed in the Har['postData']['text'] field, all values that exist have been stripped and replaced with the value's type. This does not affect the performance of Brain or Immunity, however can impact your ability to investigate some Kong Immunity related alerts by looking at the offending HARs that created those alerts. +If you want to store body data in the Collector, you can set your Collector's REDACT_BODY_DATA by declaring it in your docker-compose up command as follows: +``` +$ REDACT_BODY_DATA=False docker-compose -f docker-compose.yml -f with-redis.yml up --remove-orphans +``` + + +#### Using different Postgres and Redis instances + +To use your own instances instead of the container provided ones, you can change the command to use either your database, redis, or both. +``` +`$ KONG_HOST= KONG_PORT=<8001> SQLALCHEMY_DATABASE_URI= docker-compose -f docker-compose.yml -f with-redis.yml up --remove-orphans` +``` + +``` +`$ REDIS_URI= KONG_HOST= KONG_PORT=<8001> docker-compose -f docker-compose.yml -f with-db.yml up --remove-orphans` +``` + +``` +`$ REDIS_URI= KONG_HOST= KONG_PORT=<8001> SQLALCHEMY_DATABASE_URI= docker-compose -f docker-compose.yml up --remove-orphans` +``` + + +#### Confirm Collector is working + +Requests to the status endpoint will confirm Collector is up and running in addition to providing Immunity and/or Brain status and version number. Open a browser and type in the following request: +Request: http://:/status +COLLECTOR_HOST - the *public* IP address of the computer where you ran Docker Compose. + +#### Configure Kong Routes to send data to Collector + +Each route in Kong that you want Collector to collect data on must be positively enabled to send data to Collector. You can do this using Kong Admin API to enable and configure a plugin on the route. +For each route you want to enable Collector on, make the following request: +``` +`$ http http://:8001//routes//plugins name=collector config.service_token=foo config.host= config.port=5000 config.https=false config.log_bodies=true` +``` + +If your Kong instance is using RBAC authorization for admin endpoints, be sure to pass your KONG-ADMIN-TOKEN in header. + +>POWER USER note: There are additional configuration options on the Collector plugin that allows for tuning of the batches that are sent to Brain. These are `config.queue_size` and `config.flush_timeout`. + +If you are experiencing performance issues, contact Kong Support and to optimize the batching. +You should now be ready to use Brain and Immunity! + +#### Monitor the Collector + +Once you have Collector up and running and Kong routes configured to send data to Collector, you can check the functioning of Brain in several ways. Brain exposes several API endpoints on port 5000. + +#### Check Collector receiving data + +``` +http://:/ +``` + +Will return json contains information about each of the last 100 requests that Collector has received. + +#### Using Kong Brain + +Once you have the Collector plugin and infrastructure up and running, Kong Brain does not require additional configuration as it is automatically enabled. Once data is flowing through the Collector system, Brain starts generating swagger files and service-maps as displayed on the Dev Portal. + +#### Generated Open-API Spec files + +To create Brain's Swagger files, the Collector endpoint /swagger returns a swagger file, generated considering traffic that match the submited filter parameters: `host`, `route_id`, `service_id` and `workspace_name`. Also, it fills the fields `title`, `version` and `description` within the swagger file with the respective submited parameters. + +#### **http://:/swagger?host=&openapi_version=<2|3>&route_id=&service_id=&workspace_name=?title=** + +### Using Kong Immunity + +#### Immunity Model Training + +Immunity automatically starts training its models once it is up and running and receiving data. Immunity will create a unique model for every unique endpoint + method combination it sees in incoming traffic. For example, if you have an endpoint "[_www.test-website.com/buy_](http://www.test-website.com/buy)" and traffic comes in with both GET and POST requests for that endpoint, Immunity will create two models one for the endpoint + GET traffic and one for the endpoint + POST traffic. + + +Our first model version gets created after the first hour and will continuously retrain itself for the first week to provide the best model possible. After that, every week all models retrain with a week of data. + + +We also provide clients an endpoint to retrigger training themselves. We recommend retraining when the context of your app is expected to change a lot. For example, maybe there is an upcoming app release that will change several endpoints. If this is the case, one can POST to http://:/resettrainer to start the training cycle all over again. + + +Let’s say you’d like slightly more control over the data your model sees, for example perhaps you know that weekend data is not particularly useful for model building because weekends are normally outliers that your team is prepared for. You can trigger model training for all models with a specified time period of data. Simply POST to **http://:/trainer**, with the start and end time of data you’d like included in training like this: + +``` +`curl -d '{"start":"2019-01-08 10:00:00", "end":"2019-01-09 23:30:00"}' \` +` -H "Content-Type: application/json" \` +` -X POST http://:/trainer` +``` +or, in the browser like this: + +#### **http://:/trainer?start=&end=** + +** datetime value format: YYYY-MM-DD HH:mm:ss + + +Additionally, you can specify the kong service_id or route_id of the urls you would like trained using the kong_entity parameter. Immunity would then only train urls associated with the ID provided, and with the data specified by the start and end dates. + +``` +`curl -d '{"start":"2019-01-08 10:00:00", "end":"2019-01-09 23:30:00", "kong_entity":"2beff163-061d-43ad-8d87-8f40d10805ba"}' \` +` -H "Content-Type: application/json" \` +` -X POST http://:/trainer` +``` + +#### Checking Models Trained + +Only endpoints + method combinations that have a model trained can be monitored for alerts. If you want to check which endpoints have models, you can use **http://:/monitoredendpoints** which will give back a list of all models in the system. Each item in this list contains the following identifying information for the model: + + + +* **base_url**: The url of the traffic used to train the model. +* **method**: The method of the traffic used to train the model. +* **route_id**: The Kong route_id that the traffic used to train the model is associated with. **service_id**: The Kong service_id that the traffic used to train the model is associated with. **model_version_id**: The model version number of the current, active model. +* **active_models**: A json object containing information on the active status of each of the 6 core alert types in Immunity (unknown_parameters, abnormal_value, latency, traffic, status codes, and value_type). + + + +In this object, the value is a specific alert type and the value is a boolean value where True indicates that the model is actively monitoring for that alert type. + + +In general, if a endpoint + method combination model does not appear on the returned object from /monitoredendpoints, this is likely because not enough traffic has been seen by Immunity to build a reliable model. + +### Configure Auto-Training + +#### Restarting Training Schedules + +Immunity automatically sets up training jobs when it first starts up, and retrains all models on an optimized schedule based on time since data started flowing through Immunity. If you have experienced large changes in the type of data you expect to be coming through Immunity and do not feel comfortable choosing an "optimal" time period to use for retraining with the /trainer endpoint, you can re-trigger Immunity's auto-training by posting to the /trainer/reset endpoint. Immunity will then recreate its retraining schedule as if it was just being started and newly ingesting data. + +``` +`curl -X POST http://:/trainer/reset` +``` + +#### Configuring Auto-Training Rules + +For best use, Immunity retrains on a regular basis. If you do not feel like you need to retrain your models regularly and are happy with the current model you have now, you can stop auto retraining via post request to the /trainer/config endpoint. This endpoint takes these parameters: + + + +* **kong_entity**: The route_id or service_id that you would like to turn on or off auto-training. +* **method**: One of values: GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE. Specifying a method will restrict the rule being made on auto-training to only traffic matching the method specified. When this value is null, all traffic from all methods will be included in the rule. +* **enable**: True or False, where true means auto-training is on and false means auto-training is off for the kong_entity specified. + + + +You can turn off auto-training for a particular route or service via curl request like this: + +``` +`curl -d '{"kong_entity":"your-route-id", "enable":false}' \` +` -H "Content-Type: application/json" \` +` -X POST http://:/trainer/config` +``` + +Similarly, if you turned off auto-training for a route and feel like turning it back on, you can post to /trainer/config with enable = true. + + +These configurations will only apply to training started by Immunity's auto-training schedule. Other training requests made by /trainer won't be affected by this configuration. + +#### Viewing Configuration Rules + +To see all of your configured training rules, just create a get request to /trainer/config like this: + +``` +`curl -X GET http://:/trainer/config` +``` + +A list of all your rules will be returned, where kong_entity refers to the service_id or route_id the rule applies to, and enabled is a true or false value. + +#### Resetting or Deleting Configured Rules + +To delete a single auto-train rule that you created, you can send a delete request to /trainer/config with a kong_entity parameter and value of the service_id or route_id of the rule you would like to delete. + +``` +`curl -d '{"kong_entity":"your-route-id"}' \` +` -H "Content-Type: application/json" \` +` -X DELETE http://:/trainer/config` +``` + +Without a rule established, Immunity will default to auto-training. In other words, once you delete a configured rule, Immunity will continue or start auto-training on the route or service of the deleted rule. + + +If you would like to delete all the configurations you create, you can do so by sending an empty DELETE request to /trainer/config like this: + +``` +`curl -X http://:/trainer/config` +``` + +### Immunity Generated Alerts + +Immunity evaluates your traffic every minute, and creates an alert when an anomalous event is detected. + +#### Types of Generated Alerts + +Immunity is monitoring different types of data points in all traffic coming through Kong. Alerts generated will be based on these data points. Here are the alert types of violations Immunity is looking for: +**value_type**: These alerts are triggered when incoming requests have a value to a parameter of a different type (such as Int instead of Str) than seen historically. +**unknown_parameter**: These alerts are triggered when requests include parameters not seen before. +**abnormal_value**: These alerts are triggered when requests contain values abnormal to historical values seen paired with its parameter. +**latency_ms**: These alerts are triggered when incoming requests are significantly slower than historical records. +**traffic**: These alerts are triggered when Immunity sees a rise on 4XX and 5XX codes for incoming traffic, or when the overall traffic experiences an abnormal spike or dip. +**statuscode**: When the proportion of 4XX or 5XX codes is increasing, regardless of traffic volume + +#### Retrieving Generated Alerts + +You can monitor the created alerts by running the following commands: + +``` +`curl -d '{"start":"2019-01-08 10:00:00", "end":"2019-01-09 23:30:00"}' \` +` -H "Content-Type: application/json" \` +` -X POST http://:/alerts` +``` + +Or, you can access the alerts via browser, passing in the end and start values as parameters like this: + +``` +http://:/alerts?start=2019-01-01 00:00:00&end=2019-01-02 00:00:00 +``` + +The /alerts endpoint takes these parameters and you can mix and match them to your monitoring needs: +**start and end**: Returns only alerts generated between the values in start and end parameters passed. +**alert_type**: Returns only alerts of the alert_type in specified in alert_type parameter. This parameter does not accept lists of alert types. The value passed must be one of [‘query_params’, ‘statuscode’, ‘latency_ms’, ‘traffic’] +**url**: Returns only the alerts associated with the endpoint specified with url parameter. +**method**: Returns only alerts with the method specified. Must be one of these values: GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, or TRACE. Full capitalization is necessary. +**workspace_name**: The name of the Kong workspace for the alerts you want returned. +**route_id**: The Kong Route id for the alerts you want returned +**service_id**: The Kong Service id for the alerts you want returned +**system_restored**: A true/false value indicated you only want returned alerts where the system_restored value is matching the boolean value passed into this parameter. +**severity**: One of "low", "medium", "high" which will restrict returned alerts of severities matching the value provided with this parameter. + +#### Alerts Object + +Two types of data are returned by the /alerts endpoint. The first is a list of the alerts generated, which are structured like this: +**id**: The alert_id of the alert. +**detected_at**: The time in which the generated alert was detected at. This time also correlates with the last time point in the data time series that generated this alert. For example, if the alert was generated on data from 1:00 pm to 1:01 pm, then the detected_at time would correspond with the most recent time point of 1:01 pm in the data used to make that alert. +**detected_at_unix**: The time from detected_at expressed in unix time. +**url**: The url who’s data generated this alert. +**alert_type**: the type of alert generated, will be one of [‘query_params’, ‘statuscode’, ‘latency_ms’, ‘traffic’] +**summary**: The summary of the alert generated, includes a description of the anomalous event for clarity. +**system_restored**: This parameter takes True or False as a value, and will return notifications where the anomalous event’s system_restored status matches the value passed in the parameter. +**severity**: The severity level of this alert, values within [low, medium, high]. + +#### Alerts Metadata + +The second type of data returned is alerts metadata which describes the overall count of alerts and breaks down counts by alert type, severity, system_restored, and filtered_total. + +#### Configure Alert Severity + +#### Severity-Levels + +Alerts can be classified on 4-severity levels: +low: The low severity classification denotes the least important alerts to the user. While the user ultimately decides what a low severity means to them, we recommend that low severity indicates an alert that you'd want to look at eventually, but not right away. It's an alert you wouldn't wake up at 2 am to fix but something you'll find useful down the road maybe with planning or minor bug fixing. +medium: A medium severity classification denotes a mid-level important alert to the user. We think of this level as not something you'd want to wake up at 2 am to fix, but not so unimportant that you would wait till sprint planning prep to address. This is a level where you'll likely address it within the sprint or couple of days following it coming up. +high: A high severity classification is the highest severity level of alert. These are the alerts that you want to be woken up for in the middle of the night, the alert who's ping means all hands on deck. +ignored: Alerts that are designated as ignored are not surfaced in the Kong Manager, slack alerts, nor /alerts endpoint. For the later, ignored relates will be returned when explicitly asked for via /alerts parameter "severity". + +#### Immunity Default Severities + +Immunity provides default severity levels based on the alert type, and these defaults are: + +* value_type: low +* unknown_parameter: low +* latency_ms: high +* traffic: medium +* statuscode: high + +#### Creating or Updated New Rules + +Of course, we think you know your system best and you can adjust the severities of your alerts to varying degrees of specificity. Users of Immunity will be able to configure alert severity on alert type, kong route_id or service_id, or any combination of the two. +For example, if you decide that for your system, unknown_parameter alerts are always system-breaking you can set the severity configuration for unknown_parameter alerts to high. Let's say after doing so, you find that while usually an unknown_parameter alert is what you consider high-severity, there's one route where it's actually more of a medium. You can then specify a medium severity for unknown_parameter alerts generated only on that route and preserve the high-severity setting for the rest of unknown_parameters for the rest of your system. + + +To set a severity configuration on alerts, Immunity provides a /alerts/config endpoint. Posting to /alerts/config will create a new configuration, and requires these parameters: + +* alert_name: one of the alert types from ['traffic', 'value_type', 'unknown_parameter', 'latency_ms', 'traffic', 'statuscode'], or null. +* kong_entity: a route_id or service_id for the entity you want to create the configuration for, or null. +* severity: the severity you want this rule to make, must be one of ['low', 'medium', 'high', 'ignored']. No other severity options will be accepted. + + + +In the example above, to set the first alert type wide rule for all unknown_parameter alerts in your system, you would pass 'unknown_parameter' to the "alert_name" parameter and null to the "kong_entity" parameter. Here's an example of what that curl would look like: + +``` +`curl -d '{"alert_name":"unknown_parameter", "kong_entity":null, "severity": "high"}' \` +` -H "Content-Type: application/json" \` +` -X POST http://:/alerts/config` +``` + +To add that second rule for unknown_parameter alerts only coming from a specific route, you'd make a request like this: + +``` +`curl -d '{"alert_name":"unknown_parameter", "kong_entity":"your-route-id", "severity": "medium"}' \` +` -H "Content-Type: application/json" \` +` -X POST http://:/alerts/config` +``` + +When determining which severity to assign, Immunity will look for your configurations and default to the configuration that's "most specific" to the alert in question. Immunity thinks of alert configuration specification like this (in order from most specific configuration to least specific configuration): + +* kong route_id + alert_name combo +* kong service_id + alert_name combo +* route_id +* service_id +* alert_name +* Immunity alert_name defaults + + + +When you hit the /alerts endpoint, for each alert, Immunity will first look for a rule specifying a severity for that route's kong route_id and alert_name. If it doesn't find a severity configuration, it moves down the list above until it returns the Immunity defaults for the alert's alert type. + +#### Removing-Alert-Severity-Rule + +You can remove alert-severity configuration rules by sending a delete request to /alerts/config. This endpoint takes these parameters: +kong_entity: The kong_entity of the rule you want deleted, or null for alert type rules. +alert_name: The alert type of the rule you wanted deleted, or null for a kong_entity rule you want deleted. + +``` +`curl -d '{"alert_name":"unknown_parameter", "kong_entity":"your-route-id"}' \` +` -H "Content-Type: application/json" \` +` -X DELETE http://:/alerts/config` +``` + +If you want to delete all configuration rules, you can by passing null values for both kong_entity and alert_name in your request. If you pass null for both kong_entity and alert_name parameters, all configurations will be deleted, like this: + +``` +`curl -d '{"alert_name":null, "kong_entity":null}' \` +` -H "Content-Type: application/json" \` +` -X DELETE http://:/alerts/config` +``` + +#### Seeing-Alert-Severity-Configuration + +To see what rules you already have made, make a get request to /alerts/config to see all the rules like this: + +``` +`curl -X GET http://:/alerts/config` +``` + +In return you'll get back a json like this, where each row is a configuration rule: + +``` +`[` +`` ```{'alert_name': null, 'kong_entity': 'route-id-1', 'severity': 'low'},` +` ``` ```{'alert_name': 'traffic', 'kong_entity': null, 'severity': 'high'},` +` ``` ```{'alert_name': 'value_type', 'kong_entity': 'route-id-2', 'severity': 'medium'}` +`]` +``` + +Any kong entity plus alert type rule will be represented by a json object with both alert_name and kong_entity are not null. In the example above, that would be +{'alert_name': 'value_type', 'kong_entity': 'route-id-2', 'severity': 'medium'}. An alert type wide rule will be represented by an json object where the alert_name is not null but the kong_entity is, like +`{'alert_name': 'traffic', 'kong_entity': null, 'severity': 'high'}`.A kong entity wide rule is the reverse with a json object that has a non-null kong_entity value but a null alert_name value like `{'alert_name': null, 'kong_entity': 'route-id-1', 'severity': 'low'}` + +#### Looking at Offending Hars + +For value_type, unknown_parameter, and abnormal_value alerts, you can retrieve the hars that created those alerts via the http://:/hars endpoint. This endpoint accepts alert_id and/or har_id as parameters and returns hars related to the parameters sent. You must specify one of these two parameters to receive hars on the http://:/hars endpoint. +These are the parameters http://:/hars accepts: + + +**alert_id**: The id of the alert related to the hars you'd like to inspect. This parameter only accepts one alert_id at a time (no lists). +**har_ids**: A list of har_ids you want returned. + + +The response will include these values: +**har_id**: The har id of the har returned +**alert_id**: The alert_id of the alert_returned. +**har**: The full har for the request that generated that har. + + +Here's an example using curl: + +``` +`curl -d '{"alert_id":1} \` +` -H "Content-Type: application/json" \` +` -X POST http://:/hars` +``` + +Here's an example using the browser + + +**http://:/hars?alert_id=1** + +### Alert Slack Integration + +If you choose, Immunity can send Slack notifications for unusual traffic. Immunity needs a Slack webhook to post messages to a Slack workspace. In order to obtain a webhook URL, do the following: + + + +1. Create a new Slack app + +[**https://api.slack.com/apps?new_app=1**](https://api.slack.com/apps?new_app=1) + +Pick a name and the workspace where the app will run. + + +Enable incoming webhook in your app +After submitting the app creation form you are redirected to your newly created app’s page. In “Add features and functionality” click on “Incoming webhooks” to enable them. +Change the OFF switch to ON. That will make visible a button “Add new webhook to workspace”, click on it. + + +That will redirect you to a page where you can select the channel the webhook will post messages. Select the channel and click in authorize. + + +Configuring Slack Channels Immunity provides the endpoint /notifications/slack/config for adding, deleting, and viewing your slack configurations. + +#### Adding a Slack Configuration + +To add your first Slack configuration, copy the webhook URL that you just created with your app (when you finished the Slack app creation, you should have been directed to a page where you could copy the webhook URL). Then, simply create a POST request to /notifications/slack/config with an endpoint parameter equal to the webhook URL. Here's an example via curl: + +``` +`curl -d '{"endpoint":"www.your-slack-webhook.com"} \` +` -H "Content-Type: application/json" \` +` -X POST http://:/notifications/slack/config` +``` + +Now, you've successfully connected your Slack channel to Immunity and all alerts will notify you. + +#### Routing Different Alerts to Different Slack Channels + +Immunity will send alerts to all Slack channels you ask it too. You can even restrict the type of alerts that go to a channel with additional parameters in your POST request. To do so, the /notifications/slack/config endpoint takes these parameters on POST: + + +**endpoint**: The endpoint that you would like the current POST request rule you're setting to apply to. +**kong_entity**: Will restrict notifications set to the endpoint to only those arising from the service_id, route_id, or workspace name specified here. +**severity**: Will route only alerts with severity specified to the endpoint. Severity values can be one of "low", "medium", "high". +**alert_type**: Will route only alerts. +**enable**: When set to False, the rule in the POST request is disabled, meaning Immunity will ignore that configuration rule. When set to True, the rule in enabled and Immunity will route traffic according to the full request rule. This parameter is set to True by default in all POST requests. + + +When you send a POST request with only the endpoint parameter specified (like the one we did above), Immunity will route all traffic to that endpoint. Once a more specific POST request is made with more parameters filled, for example: + +``` +`curl -d '{"endpoint":"www.your-slack-webhook.com",` +`` ```` ``` "severity": "high"} \` +` -H "Content-Type: application/json" \` +` -X POST http://:/notifications/slack/config` +``` + +Immunity will no longer route all traffic to "[_www.your-slack-webhook.com_](http://www.your-slack-webhook.com/)", and only route alerts at high severity to "[_www.your-slack-webhook.com_](http://www.your-slack-webhook.com/)". + + +You can set multiple rules of varying specificity for the same endpoint. For example, let's say you want "[_www.your-slack-webhook.com_](http://www.your-slack-webhook.com/)" to show notifications on all alerts from service_id = "my-service-1-id" and only high-severity alerts on route_id = "my-route-1-id", you can do so with two post requests: + +``` +`curl -d '{"endpoint":"www.your-slack-webhook.com",` +`` ```` ``` "kong_entity": "my-service-1-id"} \` +` -H "Content-Type: application/json" \` +` -X POST http://:/notifications/slack/config` + + +`curl -d '{"endpoint":"www.your-slack-webhook.com",` +`` ```` ``` "severity": "high",` +`` ```` ``` "kong_entity": "my-route-1-id"} \` +` -H "Content-Type: application/json" \` +` -X POST http://:/notifications/slack/config` +``` + +Once one specific Slack configuration rule is created for a given Slack endpoint, Immunity considers all following configuration rules as "additive", meaning that each new rule will add more. + +#### Seeing your configured Rules + +Configured rules can get complicated. To see all the slack rules and slack urls you have configured, make a GET request to /notifications/slack/config like this: + +``` +`curl -X GET http://:/notifications/slack/config` +``` + +Which will return a json object where each key is an endpoint configured its value are the rules configured in a tree like structure with a boolean at the leaf of the tree indicating whether that rule is enabled or not. For the multi-config example we made above for [_www.your-slack-webhook.com_](http://www.your-slack-webhook.com/), the returned GET object will look like: + +``` +`{"www.your-slack-webhook.com": {"kong_entities": {"my-service-1-id": true,` +`` ```` ```` ```` ```` ```` ```` ```` ```` ```` ```` ```` ``` "my-route-1-id": {"severities": {"high": true}},` +`` ```` ```` ```` ```` ```` ```` ```` ```` ```` ```` ```` ``` },` +`` ```` ```` ```` ```` ```` ```` ``` }` +`}` +``` + +#### Disabling a Rule + +You might want to temporarily disable a rule you created. No problem, simply make the same POST request to /notifications/slack/config and add or change the enable parameter to false. Using the same example from above, let's set the configuration on [_www.your-slack-webhook.com_](http://www.your-slack-webhook.com/) on my-service-1-id to false. + +``` +`curl -d '{"endpoint":"www.your-slack-webhook.com",` +`` ```` ``` "kong_entity": "my-service-1-id",` +`` ```` ``` "enable": false} \` +` -H "Content-Type: application/json" \` +` -X POST http://:/notifications/slack/config` +``` + +It's important when disabling a rule to use the exact same specification parameter values (kong_entity, severity, and alert_type) that were used to create the rule. + +### Deleting a Rule + +Sometimes you want to delete a rule. Functionally this is the same as disabling a rule in the sense that notifications will no longer be sent as the deleted or disabled rule specified. To delete a configuration rule, send a DELETE request to /notifications/slack/config, and just like with disabling rules, make sure you're passing the correct values to the configuration specifying parameters (kong_entity, severity, and alert_type). With the same example from above that disabled the config rule for my-service-1-id, a DELETE would look like: + +``` +`curl -d '{"endpoint":"www.your-slack-webhook.com",` +`` ```` ``` "kong_entity": "my-service-1-id"} \` +` -H "Content-Type: application/json" \` +` -X DELETE http://:/notifications/slack/config` +``` + +Charts in Slack notifications + + +Some alerts include images to better describe the context in which the alert was created. We rely on Amazon S3 to store the images that are sent to Slack. In order to have notifications with images, please provide access information to an S3 bucket (with permission to add files), by setting the environment variables: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. + +### Clean-Up-the-Data + +Collector will clean the amount of HARs stored daily up to the max number of hars specified in the environment variable MAX_HARS_STORAGE and tables with extracted information to a max of two weeks of data. This means that at any day, the max number of HARs stored is the MAX_HARS_STORAGE + days_incoming_number_of_hars. If no MAX_HARS_STORAGE is specified, collector defaults to keeping 2 million hars in the database. + + +You can set your own value of MAX_HARS_STORAGE by setting the app environment variable through whatever means you've been deploying collector. + + +Additionally, collector provides an endpoint to delete the HARs data at /clean-hars. This endpoint accepts get and post and takes one parameter "max_hars_storage" which will delete all hars until only the value passed with max_hars_storage remains and contains the most recent HARs added to the database. If no value is passed to max_hars_storage, it will clean the database to the default value set with the environment variable MAX_HARS_STORAGE. An example of using this endpoint with curl looks like this: + +``` +`curl -d '{"max_hars_storage":10000} \` +` -H "Content-Type: application/json" \` +` -X POST http://:/clean-hars` +``` + +### Troubleshooting-Common-Setup-Pitfalls + +#### “I’m sending requests with strange parameters, but I’m not seeing any alerts related to it” + +There are a couple of things that can prevent the alerts you’re expecting from showing up. First, check your Collector instance again at http://: and make sure it’s returning HARS data. If you’re not seeing data, there are 2 possible explanations. First, its likely your Brain plugin setup is not correct. Retry setting up your Brain plugin, for example making sure that the host specified on config is the same as , until you see data coming in on http://:. Second, if the plugin setup is correct but your test request data is not coming through, then make sure that the url you are sending your test data through is correct. For data to reach Collector, it must be sent through the kong service or route configured. + +If you are seeing data, let’s examine the data that you’ve sent. The data given back are the last 100 requests Brain has. Click on one of them, and drill in until you get to queryString. Pro tip: if you don’t have random traffic coming into your system, and you know the last request you sent was the one with the strange parameters that you expected to trigger an alert, then the last entry in the list returned should correspond directly to that strange parameters request you sent. + + +On this view, check the contents of queryString. The queryString entry will list all parameters sent with the request your examining. If this entry is empty, then it indicates that no parameters were sent with this request, and properly sending parameters with your test request is the first step to seeing corresponding alerts. + + +If the queryString is looking good and you’re still not seeing alerts, then it might be that your models haven’t been built yet. When you first start Immunity, training is automatically scheduled to occur on the hour, every hour for the first week. This means that the first hour of immunityactivation will trigger no alerts because no models have been trained. You can check which endpoints have models by hitting http://:/monitoredendpoints and verify that the endpoint that you're testing with is included in the list of endpoints with models. + + +If you're not seeing any endpoints being returned with /monitoredendpoints, then it's likely training hasn't happened. If you haven’t triggered training via the http://:/trainer endpoint and it’s within the first hour of Brain activation, then it’s likely no model has been made. If you would like to trigger training and not wait for the auto-generated models, hit http://:/trainer with the start parameter set to yesterday, and the end parameter set to tomorrow. This will create models using all available data. + + +If you are seeing endpoints but not the endpoint you're testing, this likely means that not enough data for that endpoint is available for proper model training. If it's possible to test alert generation with another endpoint on the /monitoredendpoints list, then switching your testing endpoint is recommended. If not, please create normal traffic for your test endpoint and hit http://:/trainer again for full training. Then confirm that your test endpoint is listed in /monistorendpoints. + +### Still having problems? + +Email us at immunity@konghq.com with your bug report, please use the following format. + +``` +`Summary` +`Please include a description of what happened, and a description of what you expected to happen` +`Steps To Reproduce (With pictures if helpful)` +`1.` +`2.` +`3.` +`4.` +`Additional Details & Logs` +`* Immunity version (same as Brain version on Brain image name)` +`* Immunity logs (docker compose -f logs)` +`* Immunity configuration` +`* Deployment Method (docker deployment, bare metals, kubernetes ? etc)` +``` + +### Send us feature requests + +#### Send us a feature request to immunity@konghq.com! + +``` +`Summary of Proposed Feature` +`SUMMARY_GOES_HERE` +`User steps through feature (if applicable)` +`1.` +`2.` +`3.` +`4.` +``` \ No newline at end of file diff --git a/app/enterprise/1.3-x/brain-immunity/service-map.md b/app/enterprise/1.3-x/brain-immunity/service-map.md new file mode 100644 index 000000000000..95136c9e4333 --- /dev/null +++ b/app/enterprise/1.3-x/brain-immunity/service-map.md @@ -0,0 +1,43 @@ +--- +title: Using Kong's Service Map +--- + +### Introduction + +Get a high-level view of your architecture with Kong Enterprise’s real-time visual Service Map. Analyze inter-service dependencies across teams and platforms to improve governance and minimize risk. + +The Service Map gives a visual response of mapping the traffic flowing through your services. To view the Service Map, you must install and configure the Kong Collector plugin and enable Kong Brain. If you have Kong Immunity, you can automatically view Immunity alerts. + + + +### Prerequisites + +* Kong Enterprise installed and configured +* Kong Collector Plugin installed and configured +* Kong Brain enabled +* (Optional) Kong Immunity enabled to view Immunity alerts + + + +For more information, see the [Kong Brain and Kong Immunity Installation and Configuration Guide](/enterprise/{{page.kong_version}}/brain-immunity/install-configure). + +### Service Map Overview + +Kong’s Service Map provides a graphical representation of requests that flow through Kong Enterprise. + +* Kong Service Map is available from the Service Map tab. The Service Map populates with traffic as seen in Kong Brain. +* As traffic hits services running in Kong, the Service Map populates and maps those requests through hosts. The Service Map also displays protocol, timestamp, and other metadata associated with the routes and methods used for those requests. The Service Map can be filtered by hosts, as well as by Workspace. + + +* With Kong Immunity, you can view Immunity alerts within the Service Map and click through the Alerts dashboard for further investigation. + + +### Set up the Service Map + +The Kong Service Map uses **Kong Brain** and the **Kong Collector Plugin**. To populate the Service Map, configure the Kong Collector Plugin and enable Kong Brain. Once traffic starts flowing, the Service Map begins to populate with a visual representation of requests flowing through Kong, and traffic is updated in minute intervals. + + +If you have **Kong Immunity**, and the Kong Collector Plugin is configured, Kong Immunity is automatically enabled and Immunity alerts populate and display in the Service Map as they occur. + + +For more information, see the [Kong Brain and Kong Immunity Installation and Configuration Guide](/enterprise/{{page.kong_version}}/brain-immunity/install-configure). diff --git a/app/enterprise/1.3-x/cli.md b/app/enterprise/1.3-x/cli.md new file mode 100644 index 000000000000..7a37c0748565 --- /dev/null +++ b/app/enterprise/1.3-x/cli.md @@ -0,0 +1,334 @@ +--- +title: CLI Reference +--- + +## Introduction + +The provided CLI (*Command Line Interface*) allows you to start, stop, and +manage your Kong instances. The CLI manages your local node (as in, on the +current machine). + +If you haven't yet, we recommend you read the [configuration reference][configuration-reference]. + +## Global flags + +All commands take a set of special, optional flags as arguments: + +* `--help`: print the command's help message +* `--v`: enable verbose mode +* `--vv`: enable debug mode (noisy) + +[Back to TOC](#table-of-contents) + +## Available commands + + +### kong check + +``` +Usage: kong check + +Check the validity of a given Kong configuration file. + + (default /etc/kong/kong.conf) configuration file + +``` + +[Back to TOC](#table-of-contents) + +--- + + + +### kong config + +``` +Usage: kong config COMMAND [OPTIONS] + +Use declarative configuration files with Kong. + +The available commands are: + init Generate an example config file to + get you started. + + db_import Import a declarative config file into + the Kong database. + + db_export Export the Kong database into a + declarative config file. + + parse Parse a declarative config file (check + its syntax) but do not load it into Kong. + +Options: + -c,--conf (optional string) Configuration file. + -p,--prefix (optional string) Override prefix directory. + +``` + +[Back to TOC](#table-of-contents) + +--- + + +### kong health + +``` +Usage: kong health [OPTIONS] + +Check if the necessary services are running for this node. + +Options: + -p,--prefix (optional string) prefix at which Kong should be running + +``` + +[Back to TOC](#table-of-contents) + +--- + + +### kong migrations + +``` +Usage: kong migrations COMMAND [OPTIONS] + +Manage database schema migrations. + +The available commands are: + bootstrap Bootstrap the database and run all + migrations. + + up Run any new migrations. + + finish Finish running any pending migrations after + 'up'. + + list List executed migrations. + + reset Reset the database. + + migrate-apis Migrates API entities to Routes and + Services. + + migrate-community-to-enterprise Migrates Kong Community entities to Kong Enterprise in the default + workspace + +Options: + -y,--yes Assume "yes" to prompts and run + non-interactively. + + -q,--quiet Suppress all output. + + -f,--force Run migrations even if database reports + as already executed. + + --db-timeout (default 60) Timeout, in seconds, for all database + operations (including schema consensus for + Cassandra). + + --lock-timeout (default 60) Timeout, in seconds, for nodes waiting on + the leader node to finish running + migrations. + + -c,--conf (optional string) Configuration file. + + +``` + +[Back to TOC](#table-of-contents) + +--- + + +### kong prepare + +This command prepares the Kong prefix folder, with its sub-folders and files. + +``` +Usage: kong prepare [OPTIONS] + +Prepare the Kong prefix in the configured prefix directory. This command can +be used to start Kong from the nginx binary without using the 'kong start' +command. + +Example usage: + kong migrations up + kong prepare -p /usr/local/kong -c kong.conf + nginx -p /usr/local/kong -c /usr/local/kong/nginx.conf + +Options: + -c,--conf (optional string) configuration file + -p,--prefix (optional string) override prefix directory + --nginx-conf (optional string) custom Nginx configuration template + +``` + +[Back to TOC](#table-of-contents) + +--- + + +### kong quit + +``` +Usage: kong quit [OPTIONS] + +Gracefully quit a running Kong node (Nginx and other +configured services) in given prefix directory. + +This command sends a SIGQUIT signal to Nginx, meaning all +requests will finish processing before shutting down. +If the timeout delay is reached, the node will be forcefully +stopped (SIGTERM). + +Options: + -p,--prefix (optional string) prefix Kong is running at + -t,--timeout (default 10) timeout before forced shutdown + -w,--wait (default 0) wait time before initiating the shutdown + +``` + +[Back to TOC](#table-of-contents) + +--- + + +### kong reload + +``` +Usage: kong reload [OPTIONS] + +Reload a Kong node (and start other configured services +if necessary) in given prefix directory. + +This command sends a HUP signal to Nginx, which will spawn +new workers (taking configuration changes into account), +and stop the old ones when they have finished processing +current requests. + +Options: + -c,--conf (optional string) configuration file + -p,--prefix (optional string) prefix Kong is running at + --nginx-conf (optional string) custom Nginx configuration template + +``` + +[Back to TOC](#table-of-contents) + +--- + + +### kong restart + +``` +Usage: kong restart [OPTIONS] + +Restart a Kong node (and other configured services like Serf) +in the given prefix directory. + +This command is equivalent to doing both 'kong stop' and +'kong start'. + +Options: + -c,--conf (optional string) configuration file + -p,--prefix (optional string) prefix at which Kong should be running + --nginx-conf (optional string) custom Nginx configuration template + --run-migrations (optional boolean) optionally run migrations on the DB + --db-timeout (default 60) + --lock-timeout (default 60) + +``` + +[Back to TOC](#table-of-contents) + +--- + +### kong runner + +``` +Usage: kong runner [file] [args] + +Execute a lua file in a kong node. the `kong` variable is available to +reach the DAO, PDK, etc. The variable `args` can be used to access all +arguments (args[1] being the lua filename bein run). + +Example usage: + kong runner file.lua arg1 arg2 + echo 'print("foo")' | kong runner + +``` +[Back to TOC](#table-of-contents) + + +### kong start + +``` +Usage: kong start [OPTIONS] + +Start Kong (Nginx and other configured services) in the configured +prefix directory. + +Options: + -c,--conf (optional string) Configuration file. + + -p,--prefix (optional string) Override prefix directory. + + --nginx-conf (optional string) Custom Nginx configuration template. + + --run-migrations (optional boolean) Run migrations before starting. + + --db-timeout (default 60) Timeout, in seconds, for all database + operations (including schema consensus for + Cassandra). + + --lock-timeout (default 60) When --run-migrations is enabled, timeout, + in seconds, for nodes waiting on the + leader node to finish running migrations. + +``` + +[Back to TOC](#table-of-contents) + +--- + + +### kong stop + +``` +Usage: kong stop [OPTIONS] + +Stop a running Kong node (Nginx and other configured services) in given +prefix directory. + +This command sends a SIGTERM signal to Nginx. + +Options: + -p,--prefix (optional string) prefix Kong is running at + +``` + +[Back to TOC](#table-of-contents) + +--- + + +### kong version + +``` +Usage: kong version [OPTIONS] + +Print Kong's version. With the -a option, will print +the version of all underlying dependencies. + +Options: + -a,--all get version of all dependencies + +``` + +[Back to TOC](#table-of-contents) + +--- + + +[configuration-reference]: /enterprise/{{page.kong_version}}/property-reference/ diff --git a/app/enterprise/1.3-x/clustering.md b/app/enterprise/1.3-x/clustering.md new file mode 100644 index 000000000000..fcf427def903 --- /dev/null +++ b/app/enterprise/1.3-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/1.3-x/deployment/access-license.md b/app/enterprise/1.3-x/deployment/access-license.md new file mode 100644 index 000000000000..d6eaf0fb766b --- /dev/null +++ b/app/enterprise/1.3-x/deployment/access-license.md @@ -0,0 +1,38 @@ +--- +title: How to Access Your Kong Enterprise License +toc: false +--- + +Starting with Kong EE 0.29, Kong requires a license file to start. This guide +will walk you through how to access your license file. + +**Note:** The following guide only pertains to paid versions of Kong Enterprise. For free trial information, check the email received after signing up. + +Log into [https://bintray.com/login?forwardedFrom=%2Fkong%2F](https://bintray.com/login?forwardedFrom=%2Fkong%2F) +If you are unaware of your login credentials, reach out to your CSE and they'll +be able to assist you. + +You will notice that along with Kong Enterprise and Gelato, there is a new +repository that has the same name as your company. Click on that repo. + +In the repo, click on the file called **license**. + +![bintray-license](/assets/images/docs/ee/access-bintray-license.png) + +Click into the **Files** section + +![bintray-license-files](/assets/images/docs/ee/access-bintray-license-files.png) + +Click any file you would like to download. + +Alternatively, you can run this command in your terminal + +```bash +curl -L -u<$UserName>@kong<$API_KEY> "https://kong.bintray.com/<$repoName>/license.json" -o +``` + +> Note: Your UserName and key were emailed to you by your CSE. You will need to get the repo name from the GUI + + + + diff --git a/app/enterprise/1.3-x/deployment/installation/amazon-linux.md b/app/enterprise/1.3-x/deployment/installation/amazon-linux.md new file mode 100644 index 000000000000..74dd3f978a9f --- /dev/null +++ b/app/enterprise/1.3-x/deployment/installation/amazon-linux.md @@ -0,0 +1,87 @@ +--- +title: How to Install Kong Enterprise and PostgreSQL onto Amazon Linux +--- + +## Installation Steps + +```bash +$ sudo yum update +$ wget 'https://@bintray.com/kong/kong-enterprise-edition-aws/rpm' -O bintray-kong-kong-enterprise-edition-aws.repo --auth-no-challenge +$ sudo mv bintray-kong-kong-enterprise-edition-aws.repo /etc/yum.repos.d/ +$ sudo vi /etc/yum.repos.d/bintray-kong-kong-enterprise-edition-aws.repo +``` + +Ensure `baseurl` is correct + +```bash +baseurl=https://:@kong.bintray.com/kong-enterprise-edition-aws +``` + +```bash +$ sudo yum install kong-enterprise-edition +$ sudo yum install postgresql95 postgresql95-server +$ sudo service postgresql95 initdb +$ sudo service postgresql95 start +$ sudo -i -u postgres (puts you into new shell) +``` + +**Note**: `` is obtained from your access key, by appending a `%40kong` +to it (encoded form of `@kong`). For example, if your access key is `bob-company`, +your username will be `bob-company%40kong`. + +Create `kong` user + +```bash +$ psql +> CREATE USER kong; CREATE DATABASE kong OWNER kong; ALTER USER kong WITH password 'kong'; +> \q +``` + +```bash +# Change entries from ident to md5 +$ sudo vi /var/lib/pgsql95/data/pg_hba.conf +$ sudo service postgresql95 restart + +# add contents of license file +$ sudo vi /etc/kong/license.json + +# Uncomment and add 'kong' to pg_password line +$ sudo vi [/path/to/kong.conf] + +# Run migrations and start kong +$ kong migrations bootstrap [-c /path/to/kong.conf] +$ sudo /usr/local/bin/kong start [-c /path/to/kong.conf] +``` + +**Note:** You may use `kong.conf.default` or create [your own configuration](/0.13.x/configuration/#configuration-loading). + +## Install HTTPie to Make Commands more Easily + +```bash +$ sudo yum install python-pip +$ sudo pip install --upgrade pip setuptools +$ sudo pip install --upgrade httpie +``` + +## Verify Kong Installation + +```bash +$ http :8001/apis name=demo uris=/ upstream_url=http://httpbin.org +$ http :8000/ip +``` + +## Install Kong Manager + +```bash +# Get the local IP address +$ ifconfig + +# Uncomment the admin_listen setting, and update to something like this `admin_listen = 172.31.3.8:8001` +$ sudo vi [/path/to/kong.conf] + +# Restart kong +$ sudo /usr/local/bin/kong stop +$ sudo /usr/local/bin/kong start [-c /path/to/kong.conf] +``` + +In a browser, load your server on port `8002` diff --git a/app/enterprise/1.3-x/deployment/installation/centos.md b/app/enterprise/1.3-x/deployment/installation/centos.md new file mode 100644 index 000000000000..4e02f192eca3 --- /dev/null +++ b/app/enterprise/1.3-x/deployment/installation/centos.md @@ -0,0 +1,239 @@ +--- +title: How to Install Kong Enterprise on CentOS +--- + +## Introduction + +This guide walks through downloading, installing, and starting Kong Enterprise +using CentOS and PostgreSQL 9.5. The configuration shown in this guide is +intended only as an example -- you will want to modify and take additional +measures to secure your Kong Enterprise system before moving to a production +environment. + + +## Prerequisites + +To complete this guide you will need: + +- A CentOS 6 or 7 system with root equivalent access. +- The ability to SSH to the system. + + +## Step 1. Download Kong Enterprise + +1. Option 1. Download via **Packages** + + Log in to [Bintray](http://bintray.com) to download the latest Kong + Enterprise RPM for CentOS. Your **Sales** or **Support** contact will + email this credential to you. + + Copy the file to your home directory: + + ``` + $ scp kong-enterprise-edition-0.35-1.el7.noarch.rpm @:@kong.bintray.com/kong-enterprise-edition-rpm/centos/$releasever + ``` + Replace `` with your Bintray account information + + Set `$releasever` to the correct CentOS version (e.g. `6` or `7`) + +3. Obtain your Kong Enterprise license + + If you do not already have your license file, you can download it from your + account files in Bintray + `https://bintray.com/kong//license#files` + + Ensure your license file is in proper `JSON`: + + ```json + {"license":{"signature":"91e6dd9716d12ffsn4a5ckkb16a556dbebdbc4d0a66d9b2c53f8c8d717eb93dd2bdbe2cb3ef51c20806f14345128907da35","payload":{"customer":"Kong Inc","license_creation_date":"2019-05-07","product_subscription":"Kong Enterprise Edition","admin_seats":"5","support_plan":"None","license_expiration_date":"2021-04-01","license_key":"00Q1K00000zuUAwUAM_a1V1K000005kRhuUAE"},"version":1}} + ``` +4. Securely copy the license file to the CentOS system + + ``` + $ scp license.json @:~ + ``` + + +## Step 2. Install Kong Enterprise + +1. Install Kong Enterprise + + ``` + $ sudo yum install kong-enterprise-edition-0.35-1.el7.noarch.rpm + ``` + >Note: Your version may be different based on when you obtained the rpm + +2. Copy the license file to the `/etc/kong` directory + + ``` + $ sudo cp kong-se-license.json /etc/kong/license.json + ``` + Kong will look for a valid license in this location. + + +## Step 3. Setup PostgreSQL + +1. Install PostgreSQL + + ``` + $ sudo yum install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm + + $ sudo yum install postgresql95 postgresql95-server + ``` + +2. Initialize the PostgreSQL Database + + ``` + $ sudo /usr/pgsql-9.5/bin/postgresql95-setup initdb + ``` + +3. Start PostgreSQL and Enable Automatic Start + + ``` + $ sudo systemctl enable postgresql-9.5 + $ sudo systemctl start postgresql-9.5 + ``` + + +## Step 4. Create a Kong database and user + +1. Switch to PostgreSQL user + + ``` + $ sudo -i -u postgres + ``` + +2. Launch PostgreSQL + + ``` + $ psql + ``` + +3. Run the following command to: + + -- Create a Kong user and database + + -- Make Kong the owner of the database + + -- Set the password of the Kong user to 'kong' + + ``` + $ CREATE USER kong; CREATE DATABASE kong OWNER kong; ALTER USER kong WITH password 'kong'; + ``` + + >⚠️**Note**: Make sure the username and password for the Kong Database are + >kept safe. We have used a simple example for illustration purposes only. + +4. Exit from PostgreSQL + + ``` + $ \q + ``` + +5. Return to terminal + + ``` + $ exit + ``` + +6. Run the following command to access the PostgreSQL configuration file. + + ``` + $ sudo vi /var/lib/pgsql/9.5/data/pg_hba.conf + ``` + +7. Under IPv4 local connections replace `ident` with `md5` + + | TYPE | DATABASE | USER | ADDRESS | METHOD | + | # IPv4 local connections: | + | host | all | all | 127.0.0.1/32 | **md5**| + | # IPv6 local connections: | + | host | all | all | ::1/128 | ident | + +8. Restart PostgreSQL + + ``` + $ sudo systemctl restart postgresql-9.5 + ``` + + +## Step 5. Modify Kong's configuration file + +To use the newly provisioned PostgreSQL database, Kong's configuration file +must be modified to accept the correct PostgreSQL user and password. + +1. Make a copy of the default configuration file + + ``` + $ cp /etc/kong/kong.conf.default /etc/kong/kong.conf + ``` + +2. Uncomment and update the PostgreSQL database properties inside the Kong conf: + + ``` + $ sudo vi etc/kong/kong.conf + ``` + ``` + pg_user = kong + pg_password = kong + pg_database = kong + ``` + + +## Step 6. Seed the Super Admin _(optional)_ + +For the added security of Role-Based Access Control (RBAC), it is best to seed +the **Super Admin** before initial start-up. + +Create an environment variable with the desired **Super Admin** password: + + + $ export KONG_PASSWORD= + + +This will be used during migrations to seed the initial **Super Admin** +password within Kong. + + +## Step 7. Start Kong + +1. Run migrations to prepare the Kong database + + ``` + $ kong migrations bootstrap -c /etc/kong/kong.conf + ``` + +2. Start Kong + + ``` + $ sudo /usr/local/bin/kong start -c /etc/kong/kong.conf + ``` + +3. Verify Kong is working + + ``` + curl -i -X GET --url http://localhost:8001/services + ``` + + You should receive an HTTP/1.1 200 OK message. + +## Troubleshooting + +If you did not receive an HTTP/1.1 200 OK message, or need assistance completing +setup reach out to your **Support contact** or head over to the +[Support Portal](https://support.konghq.com/support/s/). + + +## Next Steps + +Work through Kong Enterprise's series of +[Getting Started](/enterprise/latest/getting-started) guides to get the most +out of Kong Enterprise. diff --git a/app/enterprise/1.3-x/deployment/installation/docker.md b/app/enterprise/1.3-x/deployment/installation/docker.md new file mode 100644 index 000000000000..1dec1a12d014 --- /dev/null +++ b/app/enterprise/1.3-x/deployment/installation/docker.md @@ -0,0 +1,180 @@ +--- +title: Installing Kong Enterprise Docker Image +--- + + + +## Installation Steps + +A guide to installing Kong Enterprise—and its license file—using +Docker. + +**Free trial users should skip directly to step 3**. + +1. Log in to bintray.com. Your Sales or Support +contact will email the credential to you. + +2. In the upper right corner, click "Edit Profile' to retrieve your API +key, which will be used in step 3. Alternatively, to retrieve it from +Bintray, click here. + +3. For **users with existing contracts**, add the Kong Docker repository and +pull the image: + + ``` + $ docker login -u -p kong-docker-kong-enterprise-edition-docker.bintray.io + $ docker pull kong-docker-kong-enterprise-edition-docker.bintray.io/kong-enterprise-edition + ``` + + For **trial users**, run the following, replacing `` +with the URL you received in your welcome email: + + ``` + curl -Lsv "" -o /tmp/kong-docker-ee.tar.gz + docker load -i /tmp/kong-docker-ee.tar.gz + ``` + +4. You should now have your Kong Enterprise image locally. Run +`docker images` to verify and find the image ID matching your repository. + +5. Tag the image ID for easier use in the commands that follow: + + ``` + docker tag kong-ee + ``` + + (Replace "IMAGE ID" with the one matching your repository, seen in step 4) + +6. Create a Docker network + + You will need to create a custom network to allow the containers to discover + and communicate with each other. In this example, `kong-ee-net` is the network name, + but you can use any name. + + ```bash + $ docker network create kong-ee-net + ``` + + +7. Start your database + + If using a Cassandra container: + + ```bash + $ docker run -d --name kong-ee-database \ + --network=kong-ee-net \ + -p 9042:9042 \ + cassandra:3 + ``` + + If using a PostgreSQL container: + + ```bash + $ docker run -d --name kong-ee-database \ + --network=kong-ee-net \ + -p 5432:5432 \ + -e "POSTGRES_USER=kong" \ + -e "POSTGRES_DB=kong" \ + postgres:9.6 + ``` + +8. To make the license data easier to handle, export it as a shell variable. +Please note that **your license contents will differ**! Users with Bintray +accounts should visit `https://bintray.com/kong//license#files` +to retrieve their license. Trial users should download their license from their +welcome email. Once you have your license, you can set it in an environment variable: + + ```sh + export KONG_LICENSE_DATA='{"license":{"signature":"LS0tLS1CRUdJTiBQR1AgTUVTU0FHRS0tLS0tClZlcnNpb246IEdudVBHIHYyCgpvd0did012TXdDSFdzMTVuUWw3dHhLK01wOTJTR0tLWVc3UU16WTBTVTVNc2toSVREWk1OTFEzVExJek1MY3dTCjA0ek1UVk1OREEwc2pRM04wOHpNalZKVHpOTE1EWk9TVTFLTXpRMVRVNHpTRXMzTjA0d056VXdUTytKWUdNUTQKR05oWW1VQ21NWEJ4Q3NDc3lMQmorTVBmOFhyWmZkNkNqVnJidmkyLzZ6THhzcitBclZtcFZWdnN1K1NiKzFhbgozcjNCeUxCZzdZOVdFL2FYQXJ0NG5lcmVpa2tZS1ozMlNlbGQvMm5iYkRzcmdlWFQzek1BQUE9PQo9b1VnSgotLS0tLUVORCBQR1AgTUVTU0FHRS0tLS0tCg=","payload":{"customer":"Test Company Inc","license_creation_date":"2017-11-08","product_subscription":"Kong Enterprise","admin_seats":"5","support_plan":"None","license_expiration_date":"2017-11-10","license_key":"00141000017ODj3AAG_a1V41000004wT0OEAU"},"version":1}}' + ``` + +9. Run Kong migrations: + + ``` + docker run --rm --network=kong-ee-net \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-ee-database" \ + -e "KONG_CASSANDRA_CONTACT_POINTS=kong-ee-database" \ + -e "KONG_LICENSE_DATA=$KONG_LICENSE_DATA" \ + kong-ee kong migrations bootstrap + ``` + **Docker on Windows users:** Instead of the `KONG_LICENSE_DATA` environment + variable, use the [volume bind](https://docs.docker.com/engine/reference/commandline/run/#options) option. + For example, assuming you've saved your `license.json` file into `C:\temp`, + use `--volume /c/temp/license.json:/etc/kong/license.json` to specify the + license file. + +10. Start Kong: + + ``` + docker run -d --name kong-ee --network=kong-ee-net \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-ee-database" \ + -e "KONG_CASSANDRA_CONTACT_POINTS=kong-ee-database" \ + -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ + -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ + -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_LISTEN=0.0.0.0:8001" \ + -e "KONG_PORTAL=on" \ + -e "KONG_LICENSE_DATA=$KONG_LICENSE_DATA" \ + -p 8000:8000 \ + -p 8443:8443 \ + -p 8001:8001 \ + -p 8444:8444 \ + -p 8002:8002 \ + -p 8445:8445 \ + -p 8003:8003 \ + -p 8004:8004 \ + kong-ee + ``` + **Docker on Windows users:** Instead of the `KONG_LICENSE_DATA` environment + variable, use the [volume bind](https://docs.docker.com/engine/reference/commandline/run/#options) option. + For example, assuming you've saved your `license.json` file into `C:\temp`, + use `--volume /c/temp/license.json:/etc/kong/license.json` to specify the + license file. + +11. Kong Enterprise should now be installed and running. Test +it by visiting Kong Manager at [http://localhost:8002](http://localhost:8002) +(replace `localhost` with your server IP or hostname when running Kong on a +remote system), or by visiting the Default Dev Portal at +[http://127.0.0.1:8003/default](http://127.0.0.1:8003/default) + +## FAQs + +The Admin API only listens on the local interface by default. This was done as a +security enhancement. Note that we are overriding that in the above example with +`KONG_ADMIN_LISTEN=0.0.0.0:8001` because Docker container networking benefits from +more open settings and enables Kong Manager and Dev Portal to talk with the Kong +Admin API. + +Without a license properly referenced, you’ll get errors running migrations: + + $ docker run -ti --rm ... kong migrations bootstrap + nginx: [alert] Error validating Kong license: license path environment variable not set + +Also, without a license, you will get no output if you do a `docker run` in +"daemon mode"—the `-d` flag to `docker run`: + + + $ docker run -d ... kong start + 26a995171e23e37f89a4263a10bb084120ab0dbed1aa11a71c888c8e0d74a0b6 + + +When you check the container, it won’t be running. Doing a `docker logs` will +show you: + + + $ docker logs + nginx: [alert] Error validating Kong license: license path environment variable not set + + +As awareness, another error that can occur due to the vagaries of the interactions +between text editors and copy & paste changing straight quotes (" or ') into curly +ones (“ or ” or ’ or ‘) is: + +​``` +nginx: [alert] Error validating Kong license: could not decode license json +​``` + +Your license data must contain only straight quotes to be considered valid JSON. diff --git a/app/enterprise/1.3-x/deployment/installation/index.md b/app/enterprise/1.3-x/deployment/installation/index.md new file mode 100644 index 000000000000..f1ad7cdd6429 --- /dev/null +++ b/app/enterprise/1.3-x/deployment/installation/index.md @@ -0,0 +1,3 @@ +--- +title: Install Kong Enterprise +--- \ No newline at end of file diff --git a/app/enterprise/1.3-x/deployment/installation/overview.md b/app/enterprise/1.3-x/deployment/installation/overview.md new file mode 100644 index 000000000000..f7998e263aa3 --- /dev/null +++ b/app/enterprise/1.3-x/deployment/installation/overview.md @@ -0,0 +1,44 @@ +--- +title: Installing Kong Enterprise +toc: false +--- + +
+ + + + + + + + + +
diff --git a/app/enterprise/1.3-x/deployment/installation/ubuntu.md b/app/enterprise/1.3-x/deployment/installation/ubuntu.md new file mode 100644 index 000000000000..8f205f617217 --- /dev/null +++ b/app/enterprise/1.3-x/deployment/installation/ubuntu.md @@ -0,0 +1,197 @@ +--- +title: How to Install Kong Enterprise on Ubuntu +--- + +## Introduction + +This guide walks through downloading, installing, and starting Kong Enterprise +using Ubuntu and PostgreSQL 9.5. The configuration shown in this guide is +intended only as an example -- you will want to modify and take additional +measures to secure your Kong Enterprise system before moving to a production +environment. + + +## Prerequisites + +To complete this guide you will need: + +- An Ubuntu system with root equivalent access. +- The ability to SSH to the system. + + +## Step 1. Download Kong Enterprise + +1. Download the .deb package + + Log in to [Bintray](http://bintray.com) to download the latest Kong + Enterprise .deb for the desired version of Ubuntu. Your **Sales** or + **Support** contact will email this credential to you. + + Copy the file to your home directory: + + ``` + $ scp kong-enterprise-edition-0.35.xxx.xxx.deb @/license#files` + + Ensure your license file is in proper `JSON`: + + ```json + {"license":{"signature":"91e6dd9716d12ffsn4a5ckkb16a556dbebdbc4d0a66d9b2c53f8c8d717eb93dd2bdbe2cb3ef51c20806f14345128907da35","payload":{"customer":"Kong Inc","license_creation_date":"2019-05-07","product_subscription":"Kong Enterprise Edition","admin_seats":"5","support_plan":"None","license_expiration_date":"2021-04-01","license_key":"00Q1K00000zuUAwUAM_a1V1K000005kRhuUAE"},"version":1}} + ``` + +3. Securely copy the license file to the Ubuntu system + + ``` + $ scp license.json @:~ + ``` + + +## Step 2. Install Kong Enterprise + +1. Install Kong Enterprise + + ``` + $ sudo apt-get update + $ sudo apt-get install openssl libpcre3 procps perl + $ sudo dpkg -i kong-enterprise-edition-0.35.xxx.xxx.deb + ``` + >Note: Your version may be different based on when you obtained the package + +2. Copy the license file to the `/etc/kong` directory + + ``` + $ sudo cp license.json /etc/kong/license.json + ``` + Kong will look for a valid license in this location. + + +## Step 3. Install PostgreSQL + +1. Install PostgreSQL + + ``` + $ sudo apt-get install postgresql-9.5 postgresql-contrib + ``` + + +## Step 4. Create a Kong database and user + +1. Switch to PostgreSQL user + + ``` + $ sudo -i -u postgres + ``` + +2. Launch PostgreSQL + + ``` + $ psql + ``` + +3. Run the following command to: + + -- Create a Kong user and database + + -- Make Kong the owner of the database + + -- Set the password of the Kong user to 'kong' + + ``` + $ CREATE USER kong; CREATE DATABASE kong OWNER kong; ALTER USER kong WITH password 'kong'; + ``` + + >⚠️**Note**: Make sure the username and password for the Kong Database are + >kept safe. We have used a simple example for illustration purposes only. + +4. Exit from PostgreSQL + + ``` + $ \q + ``` + +5. Return to terminal + + ``` + $ exit + ``` + + +## Step 5. Modify Kong's configuration file + +To use the newly provisioned PostgreSQL database, Kong's configuration file +must be modified to accept the correct PostgreSQL user and password. + +1. Make a copy of the default configuration file + + ``` + $ sudo cp /etc/kong/kong.conf.default /etc/kong/kong.conf + ``` + +2. Uncomment and update the PostgreSQL database properties inside the Kong conf: + + ``` + $ sudo vi /etc/kong/kong.conf + ``` + ``` + pg_user = kong + pg_password = kong + pg_database = kong + ``` + + +## Step 6. Seed the Super Admin _(optional)_ + +For the added security of Role-Based Access Control (RBAC), it is best to seed +the **Super Admin** before initial start-up. + +Create an environment variable with the desired **Super Admin** password: + + + $ export KONG_PASSWORD= + + +This will be used during migrations to seed the initial **Super Admin** +password within Kong. + + +## Step 7. Start Kong + +1. Run migrations to prepare the Kong database + + ``` + $ kong migrations bootstrap -c /etc/kong/kong.conf + ``` + +2. Start Kong + + ``` + $ sudo /usr/local/bin/kong start -c /etc/kong/kong.conf + ``` + +3. Verify Kong is working + + ``` + curl -i -X GET --url http://localhost:8001/services + ``` + + You should receive an HTTP/1.1 200 OK message. + + +## Troubleshooting + +If you did not receive an HTTP/1.1 200 OK message, or need assistance completing +setup reach out to your **Support contact** or head over to the +[Support Portal](https://support.konghq.com/support/s/). + + +## Next Steps + +Work through Kong Enterprise's series of +[Getting Started](/enterprise/latest/getting-started) guides to get the most +out of Kong Enterprise. diff --git a/app/enterprise/1.3-x/deployment/licensing.md b/app/enterprise/1.3-x/deployment/licensing.md new file mode 100644 index 000000000000..92a637e484d4 --- /dev/null +++ b/app/enterprise/1.3-x/deployment/licensing.md @@ -0,0 +1,49 @@ +--- +title: Kong Enterprise Licensing +--- + +## Overview +Kong Enterprise enforces the presence and validity of a license file. + +License files must be deployed to each node running Kong Enterprise. License file checking is done independently by each node as the Kong process starts; no network connectivity is necessary to execute the license validation process. + +## Deploying the License File +There are three possible ways to configure a license file on a Kong node. These are defined below, in the order in which they are checked by Kong: + +1. If present, the contents of the environmental variable `KONG_LICENSE_DATA` are used. +2. Kong will search in the default location `/etc/kong/license.json` +3. If present, the contents of the file defined by the environment variable `KONG_LICENSE_PATH` is used. + +In this manner, the license file can be deployed either as a file on the node filesystem, or as an environmental variable. + +Note that unlike most other `KONG_*` environmental variables, the `KONG_LICENSE_DATA` and `KONG_LICENSE_PATH` cannot be defined in-line as part of any `kong` CLI commands. The reason for this is that the `kong` CLI tool is a wrapper script to generate an Nginx config and launch the Nginx process via the existing shell. That is, the Nginx process that accepts proxy traffic is spawned as a child of the shell in which the `kong` CLI process is run, not as a child of the `kong` CLI process itself, and thus in-line environmental variables are not made available to the Nginx process. Thus, license file environmental variables must be exported to the shell in which the Nginx process will run, ahead of the `kong` CLI tool. + +## Examining the License Data on a Kong Node +License data is displayed as part of the root (`"/"`) Admin API endpoint, under the `license` JSON key. It is also visible in the Admin GUI. + +## Troubleshooting +When a valid license file is properly deployed, license file validation is a transparent operation; no additional output or logging data is written or provided. If an error occurs when attempting to validate the license, or the license data is not valid, an error message will be written to the console and logged to the Kong error log, followed by the process quitting. Below are possible error messages and troubleshooting steps to take: + +- "license path environment variable not set" + - Neither the `KONG_LICENSE_DATA` nor the `KONG_LICENSE_PATH` environmental variables were defined, and no license file could be opened at the default license location (`/etc/kong/license.json`) +- "internal error" + - An internal error has occurred while attempting to validate the license. Such cases are extremely unlikely; contact Kong support to further troubleshoot. +- "error opening license file" + - The license file defined either in the default location, or via the `KONG_LICENSE_PATH` env variable, could not be opened. Check that the user executing the Nginx process (e.g., the user executing the Kong CLI utility) has permissions to read this file. +- "error reading license file" + - The license file defined either in the default location, or via the `KONG_LICENSE_PATH` env variable, could be opened, but an error occurred while reading. Confirm that the file is not corrupt, that there are no kernel error messages reported (e.g., out of memory conditions, etc). This is a generic error and is extremely unlikely to occur if the file could be opened. +- "could not decode license json" + - The license file data could not be decoded as valid JSON. Confirm that the file is not corrupt and has not been altered since you received it from Kong Inc. Try re-downloading and installing your license file from Kong Inc. + - if you still receive this error, contact Kong support. +- "invalid license format" + - The license file data is missing one or more key/value pairs. Confirm that the file is not corrupt and has not been altered since you received it from Kong Inc. Try re-downloading and installing your license file from Kong Inc. + - if you still receive this error, contact Kong support. +- "validation failed" + - The attempt to verify the payload of the license with the license's signature failed. Confirm that the file is not corrupt and has not been altered since you received it from Kong Inc. Try re-downloading and installing your license file from Kong Inc. + - if you still receive this error, contact Kong support. +- "license expired" + - The system time is past the license's license_expiration_date. Note that Kong Enterprise provides 1-2 days worth of slack time past the license expiration date before failing to validate with this error, to account for timezone discrepancies, human error, etc. +- "invalid license expiration date" + - The data in the license_expiration_date field is incorrectly formatted. Try re-downloading and installing your license file from Kong Inc. + - if you still receive this error, contact Kong support. +- License expiration logs: Kong will start logging the license expiration date once a day—with a WARN log—90 days before the expiry; 30 days before, the log severity increases to ERR, and after expiration, it to CRIT. diff --git a/app/enterprise/1.3-x/deployment/migrations.md b/app/enterprise/1.3-x/deployment/migrations.md new file mode 100644 index 000000000000..1f53c8e3083a --- /dev/null +++ b/app/enterprise/1.3-x/deployment/migrations.md @@ -0,0 +1,81 @@ +--- +title: Migrating to 1.3-α +--- + +### Prerequisites for Migrating to 1.3-α + +* If running a version of **Kong Enterprise** earlier than 0.35, [migrate to 0.35](/enterprise/0.35-x/deployment/migrations/) first. +* If running a version of **Kong** earlier than 1.2, [upgrade to Kong 1.2](/1.2.x/upgrading/) before upgrading to Kong Enterprise 1.3-α. + +### Changes and Configuration to Consider before Upgrading + +* If using RBAC with Kong Manager, it will be necessary to manually add the [Session Plugin configuration values](/enterprise/{{page.kong_version}}/kong-manager/authentication/sessions/#configuration-to-use-the-sessions-plugin-with-kong-manager). +* Kong Manager and the Admin API must share the same domain in order to use the SameSite directive. If they are on separate domains, `cookie_samesite` must be set to `“off”`. Learn more in [Session Security](/enterprise/{{page.kong_version}}/kong-manager/authentication/sessions/#configuration-to-use-the-sessions-plugin-with-kong-manager) +* Kong Manager must be served over HTTPS in order for the Secure directive to work. If using Kong Manager with only HTTP, e.g. on `localhost`, then `cookie_secure` must be set to `false`. Learn more in [Session Security](/enterprise/{{page.kong_version}}/kong-manager/authentication/sessions/#session-security) +* 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/*' +'/portal/developers/*' => '/developers/*' +'/portal/developers/*/*' => '/developers/*/*' +'/portal/developers/*/email' => '/developers/*/email' +'/portal/developers/*/meta' => '/developers/*/meta' +'/portal/developers/*/password' => '/developers/*/password' +'/portal/invite' => '/developers/invite' +``` +* As a result of the switch to server-side rendering, a few portal template files need to be updated or replaced to regain full functionality: + 1. Replace contents of partial `spec/index-vue` with contents of: + [https://raw.githubusercontent.com/Kong/kong-portal-templates/master/themes/default-ie11/partials/spec/index-vue.hbs](https://raw.githubusercontent.com/Kong/kong-portal-templates/master/themes/default-ie11/partials/spec/index-vue.hbs) + 2. Replace contents of partial `search/widget-vue` with contents of: + [https://raw.githubusercontent.com/Kong/kong-portal-templates/master/themes/default-ie11/partials/search/widget-vue.hbs](https://raw.githubusercontent.com/Kong/kong-portal-templates/master/themes/default-ie11/partials/search/widget-vue.hbs) + 3. Create or update partial `unauthenticated/assets/icons/search-header` with contents of: + [https://raw.githubusercontent.com/Kong/kong-portal-templates/master/themes/default-ie11/partials/unauthenticated/assets/icons/search-header.hbs](https://raw.githubusercontent.com/Kong/kong-portal-templates/master/themes/default-ie11/partials/unauthenticated/assets/icons/search-header.hbs) + 4. Create or update partial `unauthenticated/assets/icons/loading` with contents of: + [https://raw.githubusercontent.com/Kong/kong-portal-templates/master/themes/default-ie11/partials/unauthenticated/assets/icons/loading.hbs](https://raw.githubusercontent.com/Kong/kong-portal-templates/master/themes/default-ie11/partials/unauthenticated/assets/icons/loading.hbs) + 5. Create or update partial `unauthenticated/assets/icons/search-widget` with contents of: + [https://raw.githubusercontent.com/Kong/kong-portal-templates/master/themes/default-ie11/partials/unauthenticated/assets/icons/search-widget.hbs](https://raw.githubusercontent.com/Kong/kong-portal-templates/master/themes/default-ie11/partials/unauthenticated/assets/icons/search-widget.hbs) + +### Migration Steps from 0.35 to 1.3-α + +For a no-downtime migration from a 0.35 cluster to a 1.3-α cluster: + +1. Download 1.3-α, and configure it to point to the same datastore as your 0.35 cluster. +2. Run `kong migrations up`. Both 0.35 and 1.3-α nodes can now run simultaneously on the same datastore. +3. Start provisioning 1.3-α nodes. +4. Gradually divert traffic away from your 0.35 nodes, and into your 1.3-α cluster. Monitor your traffic to make sure everything is going smoothly. +5. When your traffic is fully migrated to the 0.35 cluster, decommission your 0.35 nodes. +6. From your 1.3-α cluster, run `kong migrations finish`. From this point on, it will not be possible to start 0.35 nodes pointing to the same datastore anymore. Only run this command when you are confident that your migration was successful. From now on, you can safely make Admin API requests to your 1.3-α nodes. + +At any step of the way, you may run `kong migrations list` to get a report of the state of migrations. It will list whether there are missing migrations, if there are pending migrations (which have already started in the `kong migrations up` step and later need to finish in the `kong migrations finish` step) or if there are new migrations available. The status code of the process will also change accordingly: + +* `0` - migrations are up-to-date +* `1` - failed inspecting the state of migrations (e.g. database is down) +* `3` - database needs bootstrapping: you should run `kong migrations bootstrap` to install on a fresh datastore. +* `4` - there are pending migrations: once your old cluster is decommissioned you should run `kong migrations finish` (step 5 above). +* `5` - there are new migrations: you should start a migration sequence (beginning from step 1 above). + +### Migration Steps from Kong 1.2 to Kong Enterprise 1.3-α + +
+ Note: This action is irreversible, therefore it is highly recommended to have a backup of production data. +
+ +Kong Enterprise 1.3-α includes a command to migrate all Kong entities to Kong Enterprise. The following steps will guide you through the migration process. + +First download Kong Enterprise 1.3-α, and configure it to point to the same datastore as your Kong 1.2 node. The migration command expects the datastore to be up to date on any pending migration: + +```shell +$ kong migrations up [-c config] +$ kong migrations finish [-c config] +``` + +Once all Kong Enterprise migrations are up to date, the migration command can be run as: + +```shell +$ kong migrations migrate-community-to-enterprise [-c config] [-f] [-y] +``` + +Confirm now that all the entities are now available on your Kong Enterprise 0.35 node. diff --git a/app/enterprise/1.3-x/developer-portal/administration/developer-permissions.md b/app/enterprise/1.3-x/developer-portal/administration/developer-permissions.md new file mode 100644 index 000000000000..d3c309bafc5c --- /dev/null +++ b/app/enterprise/1.3-x/developer-portal/administration/developer-permissions.md @@ -0,0 +1,56 @@ +--- +title: Developer Roles and Content Permissions +--- + +## Introduction + +Access to the Developer Portal can be fine-tuned with the use of Developer Roles and Content Permissions, managed through the Dev Portal Permissions page of Kong Manager. This page can be found by clicking on the **Permissions** link under **Dev Portal** in the Kong Manager side navigation. + +## Roles + +The Roles Tab contains a list of available developer roles as well as the ability to create and edit roles. + +Selecting "Create Role" will allow us to enter the unique role name, as well as a comment to provide context for the nature of the role. We can assign the role to existing developers from within the role creation page. Clicking "Create" will save the role and return us to the Roles List view. Here we can see our newly created role as well as any other previously defined roles. + +Clicking "View" will show us the Role Details page with a list of developers assigned. + +From the Role Details page, we can click the "Edit" button to make changes to the role. We can also access this page from the Roles List "Edit" button. Here we can change the name and comment of the role, assign or remove developers, or delete the role. + +Deleting a role will remove it from any developers assigned the role and remove the role restriction from any content files it is applied to. + +## Content + +The Content Tab shows the list of content files used by the Dev Portal. Here we can apply roles to our content files, restricting access to developers who posess certain roles. Selecting an individual content file displays a dropdown of availabled developer roles. Here we can choose which role has accese to the file. Unchecking all availabled roles will leave the file unauthenticated. + +An additional option is preset in the list: the `*` role. This predefined role behaves differently from other roles. When a content file has the `*` role attached to it, any developer may view the page as long as they are authenticated. Additionally, the `*` role may not be used in conjunction with other user defined roles and will deselect these roles when `*` is selected + +⚠️**Important:** `dashboard.txt` and `settings.txt` content files are assigned the `*` role by default. All other content files have no roles by default. This means that until a role is added, the file is unauthenticated even if Dev Portal Authentication is enabled. Content Permissions are ignored when Dev Portal Authentication is disabled. For more information visit the Dev Portal Authentication section. + +## readable_by attribute + +When a role is applied to a content file via the Content Tab, a special attribute `readable_by` is added to the headmatter of the file. + +``` +--- +readable_by: + - role_name + - another_role_name +--- +``` + + In the case of spec files, `readable_by` is applied under the key `x-headmatter` or `X-headmatter`. + +``` +x-headmatter: + readable_by: + - role_name + - another_role_name +``` + +The value of `readable_by` is an array of string role names that have access to view the content file. The exception is when the `*` role is applied to the file. In this case, the value of `readable_by` is no longer an array, but the single string character `*`. + +``` +readable_by: "*" +``` + +⚠️**Important:** Please note that if you manually remove or edit the `readable_by` attribute, it will modify the permissions of the file. Attempting to save a content file with a `readable_by` array containing an nonexistent role name will result in an error. Additionally, if you make changes to permissions in the Content Tab or via the Portal Editor, be sure to sync any local files so that permissions are not overwritten next time you push changes. diff --git a/app/enterprise/1.3-x/developer-portal/administration/index.md b/app/enterprise/1.3-x/developer-portal/administration/index.md new file mode 100644 index 000000000000..87dc44d98542 --- /dev/null +++ b/app/enterprise/1.3-x/developer-portal/administration/index.md @@ -0,0 +1,20 @@ +--- +title: Dev Portal Administration +--- + +
+
+

+ Managing Developers

+

Inviting, Approving, Rejecting, and Revoking Developers

+ + Learn More → +
+
+

+ Developer Roles and Content Permissions

+

Control access to your Dev Portal with Developer Roles and Content Permissions

+ + Learn More → +
+
diff --git a/app/enterprise/1.3-x/developer-portal/administration/managing-developers.md b/app/enterprise/1.3-x/developer-portal/administration/managing-developers.md new file mode 100644 index 000000000000..1c8b02ec82f1 --- /dev/null +++ b/app/enterprise/1.3-x/developer-portal/administration/managing-developers.md @@ -0,0 +1,144 @@ +--- +title: Managing Developers +--- + +### Developer Status + +A status represents the state of a developer and the access they have to the Dev + Portal and APIs. + +* **Approved** + * A Developer who can access the Dev Portal. Approved Developers can create + credentials & access **all** APIs that allow those credentials. +* **Requested** + * A Developer who has requested access but has not yet been Approved. +* **Rejected** + * A Developer who has had their request denied by a Kong Admin. +* **Revoked** + * A Developer who once had access to the Dev Portal but has since had access + Revoked. + + +![Managing Developers](https://konghq.com/wp-content/uploads/2018/05/gui-developer-tabs.png) + +### Approving Developers + +Developers who have requested access to a Dev Portal will appear under the +**Requested Access** tab. From this tab you can choose to *Accept* or *Reject* +the developer from the actions in the table row. After selecting an action the +corresponding tab will update. + + +### Viewing Approved Developers + +To view all currently approved developers choose the **Approved** tab. From here you can choose to *Revoke* or *Delete* a particular developer. Additionally you can use this view to send an email to a developer with the **Email Developer** `mailto` link. See [Emailing Developers](#emailing-developers) for more info. + + +### Viewing Revoked Developers + +To view all currently revoked developers choose the **Revoked** tab. From here you can choose to *Re-approve* or *Delete* a developer. + + +### Viewing Rejected Developers + +To view all currently rejected developers choose the **Rejected** tab. Rejected developers completed the registration flow on your Dev Portal but were rejected from the **Request Access** tab. You may *Approve* or *Delete* a developer from this tab. + + +### Emailing Developers + +#### Inviting Developers to Register + +To invite a single or set of developers... + +1. Click the **Invite Developers** button from the top right corner above the tabs +2. Use the popup modal to enter email addresses separated by commas +3. After all emails have been added click **Invite**. This will open a pre-filled message in your default email client with a link to the registration page for your Dev Portal + +Each developer is bcc'd by default for privacy. You may choose to edit the message or send as is. + +![Invite Developers](https://konghq.com/wp-content/uploads/2018/05/invite-developers.png) + + +### Developer Management Property Reference + + +#### portal_auto_approve + +**Default:** `off` + +**Description:** +Dev Portal Auto Approve Access. + +When set to `on`, a developer will automatically be marked as `approved` after +completing Dev Portal registration. Access can still be revoked through +Kong Manager or API. + +When set to `off`, a Kong Admin will have to manually approve the Developer via +the Kong Manager or API. + + +#### portal_invite_email + +**Default:** `on` + +**Description:** +When enabled, Admins will be able to invite Developers to a Dev Portal by using + the "Invite" button in the Kong Manager. + + +#### portal_access_request_email + +**Default:** `on` + +**Description:** +When enabled, Kong Admins specified by `smtp_admin_emails` will receive an email + when a Developer requests access to a Dev Portal. + +When disabled, Kong Admins will have to manually check the Kong Manager to view +any requests. + + +#### portal_approved_email + +**Default:** `on` + +**Description:** +When enabled, Developers will receive an email when access to a Dev Portal has +been approved. + +When disabled, Developers will receive no indication that they have been +approved. It is suggested to only disable this feature if`portal_auto_approve` +is enabled. + + +#### portal_reset_email + +**Default:** `on` + +**Description:** +When enabled, Developers will be able to use the "Reset Password" flow on a Dev +Portal and will receive an email with password reset instructions. + +When disabled, Developers will *not* be able to reset their account passwords. +Kong Admins will have to manually create new credentials for the Developer in +the Kong Manager. + +#### portal_token_exp + +**Default:** `21600` + +**Description:** +Duration in seconds for the expiration of the Dev Portal reset password token. +Default `21600` is six hours. + + +#### portal_reset_success_email + +**Default:** `on` + +**Description:** +When enabled, Developers will receive an email after successfully resetting their + Dev Portal account password. + +When disabled, Developers will still be able to reset their account passwords, +but will not receive a confirmation email. diff --git a/app/enterprise/1.3-x/developer-portal/configuration/authentication/adding-registration-fields.md b/app/enterprise/1.3-x/developer-portal/configuration/authentication/adding-registration-fields.md new file mode 100644 index 000000000000..8f3a4592ce0a --- /dev/null +++ b/app/enterprise/1.3-x/developer-portal/configuration/authentication/adding-registration-fields.md @@ -0,0 +1,32 @@ +--- +title: Adding New Dev Portal Registration Fields +toc: false +--- + + +### Introduction + +By default, when authentication is enabled for a Dev Portal the only required +fields are **full name**, **email**, and **password**. However, additional fields can be added +to this form. + + +### Adding Additional Registration Fields + +1. In Kong Manager, navigate to the desired Workspace's Dev Portal **Settings** page. + +2. Click the **Developer Meta Fields** tab on the **Settings Page** + +3. Click **+ Add Field** to add a new field object to the form. + +4. Give the new field a label, field name, and select the type of input + +5. Select the checkbox **Required** to require this field for registration + +6. Click the **Save Changes** button a the bottom of the form. + + +Once saved, the new field will automatically be added to the registration form. + +> **WARNING** Adding new required fields to registration will block existing +> developers from logging in. They will need to be removed and re-registered. \ No newline at end of file diff --git a/app/enterprise/1.3-x/developer-portal/configuration/authentication/basic-auth.md b/app/enterprise/1.3-x/developer-portal/configuration/authentication/basic-auth.md new file mode 100644 index 000000000000..2149ea3ab7d0 --- /dev/null +++ b/app/enterprise/1.3-x/developer-portal/configuration/authentication/basic-auth.md @@ -0,0 +1,65 @@ +--- +title: How to Enable Basic Auth in the Dev Portal +--- + +### Introduction + +The Kong Developer Portal can be fully or partially authenticated using HTTP protocol's Basic Authentication scheme. Requests will be sent with the Authorization header that +contains the word `Basic` followed by the base64-encoded `username:password` string. + +Basic Authentication for the Dev Portal can be enabled in three ways: + +- via the [Kong Manager](#enable-basic-auth-via-kong-manager) +- via the [the command line](#enable-basic-auth-via-the-command-line) +- via the [the Kong configuration file](#enable-basic-auth-via-the-kong-conf) + +>**Warning** Enabling authentication in the Dev Portal requires use of the +> Sessions plugin. Developers will not be able to login if this is not set +> properly. More information about [Sessions in the Dev Portal](/enterprise/{{page.kong_version}}/developer-portal/configuration/authentication/sessions) + +### Enable Portal Session Config + +In the the Kong configuration file set the `portal_session_conf` property: + +``` +portal_session_conf={ "cookie_name": "portal_session", "secret": "CHANGE_THIS", "storage": "kong" } +``` + +If using HTTP while testing, include `"cookie_secure": false` in the config: + +``` +portal_session_conf={ "cookie_name": "portal_session", "secret": "CHANGE_THIS", "storage": "kong", "cookie_secure": false } +``` + +### Enable Basic Auth via Kong Manager + +1. Navigate to the Dev Portal's **Settings** page +2. Find **Authentication plugin** under the **Authentication** tab +3. Select **Basic Authentication** from the drop down +4. Click the **Save Changes** button at the bottom of the form + +>**Warning** When Dev Portal Authentication is enabled, content files will remain unauthenticated until a role is applied to them. The exception to this is `settings.txt` and `dashboard.txt` which begin with the `*` role. Please visit the Developer Roles and Content Permissions section for more info. + +### Enable Basic Auth via the Command Line + +To patch a Dev Portal's authentication property directly run: + +``` +curl -X PATCH http://localhost:8001/workspaces/ \ + --data "config.portal_auth=basic-auth" +``` + +>**Warning** When Dev Portal Authentication is enabled, content files will remain unauthenticated until a role is applied to them. The exception to this is `settings.txt` and `dashboard.txt` which begin with the `*` role. Please visit the Developer Roles and Content Permissions section for more info. + +### Enable Basic Auth via the Kong.conf + +Kong allows for a `default authentication plugin` to be set in the Kong +configuration file with the `portal_auth` property. + +In your `kong.conf` file set the property as follows: + +``` +portal_auth="basic-auth" +``` + +This will set all Dev Portals to use Basic Authentication by default when initialized. diff --git a/app/enterprise/1.3-x/developer-portal/configuration/authentication/index.md b/app/enterprise/1.3-x/developer-portal/configuration/authentication/index.md new file mode 100644 index 000000000000..39d59a6a0d1c --- /dev/null +++ b/app/enterprise/1.3-x/developer-portal/configuration/authentication/index.md @@ -0,0 +1,45 @@ +--- +title: Dev Portal Authentication +toc: false +--- + + diff --git a/app/enterprise/1.3-x/developer-portal/configuration/authentication/key-auth.md b/app/enterprise/1.3-x/developer-portal/configuration/authentication/key-auth.md new file mode 100644 index 000000000000..d0c2d2a3f452 --- /dev/null +++ b/app/enterprise/1.3-x/developer-portal/configuration/authentication/key-auth.md @@ -0,0 +1,65 @@ +--- +title: How to Enable Key Auth in the Dev Portal +--- + +### Introduction + +The Kong Developer Portal can be fully or partially authenticated using API keys or **Key +Authentication**. Users provide a unique key upon registering and use this key +to log into the Dev Portal. + +Key Authentication for the Dev Portal can be enabled in three ways: + +- via the [Kong Manager](#enable-key-auth-via-kong-manager) +- via the [the command line](#enable-key-auth-via-the-command-line) +- via the [the Kong configuration file](#enable-key-auth-via-the-kong-conf) + +>**Warning** Enabling authentication in the Dev Portal requires use of the +> Sessions plugin. Developers will not be able to login if this is not set +> properly. More information about [Sessions in the Dev Portal](/enterprise/{{page.kong_version}}/developer-portal/configuration/authentication/sessions) + +### Enable Portal Session Config + +``` +portal_session_conf={ "cookie_name": "portal_session", "secret": "CHANGE_THIS", "storage": "kong" } +``` + +If using HTTP while testing, include `"cookie_secure": false` in the config: + +``` +portal_session_conf={ "cookie_name": "portal_session", "secret": "CHANGE_THIS", "storage": "kong", "cookie_secure": false } +``` + +### Enable Key Auth via Kong Manager + +1. Navigate to the Dev Portal's **Settings** page +2. Find **Authentication plugin** under the **Authentication** tab +3. Select **Key Authentication** from the drop down +4. Click the **Save Changes** button at the bottom of the form + +>**Warning** When Dev Portal Authentication is enabled, content files will remain unauthenticated until a role is applied to them. The exception to this is `settings.txt` and `dashboard.txt` which begin with the `*` role. Please visit the Developer Roles and Content Permissions section for more info. + +### Enable Key Auth via the Command Line + +To patch a Dev Portal's authentication property directly run: + +``` +curl -X PATCH http://localhost:8001/workspaces/ \ + --data "config.portal_auth=key-auth" +``` + +>**Warning** When Dev Portal Authentication is enabled, content files will remain unauthenticated until a role is applied to them. The exception to this is `settings.txt` and `dashboard.txt` which begin with the `*` role. Please visit the Developer Roles and Content Permissions section for more info. + +### Enable Key Auth via the Kong.conf + +Kong allows for a `default authentication plugin` to be set in the Kong +configuration file with the `portal_auth` property. + +In your `kong.conf` file set the property as follows: + +``` +portal_auth="key-auth" +``` + +This will set every Dev Portal to use Key Authentication by default when +initialized, regardless of Workspace. diff --git a/app/enterprise/1.3-x/developer-portal/configuration/authentication/oidc.md b/app/enterprise/1.3-x/developer-portal/configuration/authentication/oidc.md new file mode 100644 index 000000000000..96d1e37a1c37 --- /dev/null +++ b/app/enterprise/1.3-x/developer-portal/configuration/authentication/oidc.md @@ -0,0 +1,131 @@ +--- +title: How to Enable OpenId Connect in the Dev Portal +--- + +### Introduction + +The [OpenID Connect Plugin](/hub/kong-inc/openid-connect/) (OIDC) +allows the Kong Developer Portal to hook into existing authentication setups using third-party +*Identity Providers* (IdP) such as Google, Yahoo, Microsoft Azure AD, etc. + +[OIDC](/hub/kong-inc/openid-connect/) must be used with +the `session` method, utilizing cookies for Dev Portal File API requests. + +In addition, a configuration object is required to enable OIDC, please refer to the +[Sample Configuration Object](#/sample-configuration-object) section of this +document for more information. + +OIDC for the Dev Portal can be enabled in three ways: + +- via the [Kong Manager](#enable-oidc-via-kong-manager) +- via the [the command line](#enable-oidc-via-the-command-line) +- via the [the Kong configuration file](#enable-oidc-via-the-kongconf) + + +### Portal Session Plugin Config + +Session Plugin Config does not apply when using OpenID Connect. + +### Sample Configuration Object + +Below is a sample configuration JSON object for using *Google* as the Identity +Provder: + +``` +{ + "consumer_by": ["username","custom_id","id"], + "leeway": 1000, + "scopes": ["openid","profile","email","offline_access"], + "logout_query_arg": "logout", + "client_id": [""], + "login_action": "redirect", + "logout_redirect_uri": ["http://localhost:8003 (http://localhost:8003/)"], + "ssl_verify": false, + "consumer_claim": ["email"], + "forbidden_redirect_uri": ["http://localhost:8003/unauthorized"], + "client_secret": [""], + "issuer": "https://accounts.google.com/", + "logout_methods": ["GET"], + "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. + +Example: + +``` +{ + "consumer_by": ["username","custom_id","id"], + "leeway": 1000, + "scopes": ["openid","profile","email","offline_access"], + "logout_query_arg": "logout", + "client_id": [""], + "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"], + "session_cookie_domain": ".portal.com", + "forbidden_redirect_uri": ["https://example.portal.com/unauthorized"], + "client_secret": ["**Warning** When Dev Portal Authentication is enabled, content files will remain unauthenticated until a role is applied to them. The exception to this is `settings.txt` and `dashboard.txt` which begin with the `*` role. Please visit the Developer Roles and Content Permissions section for more info. + +### Enable OIDC via the Command Line + +To patch a Dev Portal's authentication property directly run: + +``` +curl -X PATCH http://localhost:8001/workspaces/ \ + --data "config.portal_auth=openid-connect" + "config.portal_auth_conf= +``` + +>**Warning** When Dev Portal Authentication is enabled, content files will remain unauthenticated until a role is applied to them. The exception to this is `settings.txt` and `dashboard.txt` which begin with the `*` role. Please visit the Developer Roles and Content Permissions section for more info. + +### Enable OIDC via the Kong.conf + +Kong allows for a `default authentication plugin` to be set in the Kong +configuration file with the `portal_auth` property. + +In your `kong.conf` file set the property as follows: + +``` +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 +initialized, regardless of Workspace. diff --git a/app/enterprise/1.3-x/developer-portal/configuration/authentication/sessions.md b/app/enterprise/1.3-x/developer-portal/configuration/authentication/sessions.md new file mode 100644 index 000000000000..3b3ada132439 --- /dev/null +++ b/app/enterprise/1.3-x/developer-portal/configuration/authentication/sessions.md @@ -0,0 +1,84 @@ +--- +title: Sessions in the Dev Portal +--- + +⚠️**Important:** Portal Session Configuration does not apply when using [OpenID Connect](/hub/kong-inc/openid-connect) for Dev Portal authentication. The following information assumes that the Dev Portal is configured with `portal_auth` other than `openid-connect`, for example `key-auth` or `basic-auth`. + +## How does the Sessions Plugin work in the Dev Portal? + +When a user logs in to the Dev Portal with their credentials, the Sessions Plugin will create a session cookie. The cookie is used for all subsequent requests and is valid to authenticate the user. The session has a limited duration and renews at a configurable interval, which helps prevent an attacker from obtaining and using a stale cookie after the session has ended. + +The Session configuration is secure by default, which may [require alteration](#session-security) if using HTTP or different domains for [portal_api_url](/enterprise/{{page.kong_version}}/developer-portal/networking/#portal_api_url) and [portal_gui_host](/enterprise/{{page.kong_version}}/developer-portal/networking/#portal_gui_host). Even if an attacker were to obtain a stale cookie, it would not benefit them since the cookie is encrypted. The encrypted session data may be stored either in Kong or the cookie itself. + +## Configuration to Use the Sessions Plugin with the Dev Portal + +To enable sessions authentication, configure the following: + +``` +portal_auth = +portal_session_conf = { + "secret":"", + "cookie_name":"", + "storage":"kong", + "cookie_lifetime":, + "cookie_renew": + "cookie_secure": + "cookie_samesite":"" +} +``` + +* `"cookie_name":""`: The name of the cookie + * For example, `"cookie_name":"portal_cookie"` +* `"secret":""`: The secret used in keyed HMAC generation. Although + the **Session Plugin's** default is a random string, the `secret` _must_ be + manually set for use with the Dev Portal since it must be the same across all + Kong workers/nodes. +* `"storage":"kong"`: Where session data is stored. This value _must_ be set to `kong` for use with the Dev Portal. +* `"cookie_lifetime":`: The duration (in seconds) that the session will remain open; 3600 by default. +* `"cookie_renew":`: The duration (in seconds) of a session remaining at which point + the Plugin renews the session; 600 by default. +* `"cookie_secure":`: `true` by default. See [Session Security](#session-security) for + exceptions. +* `"cookie_samesite":""`: `"Strict"` by default. See [Session Security](#session-security) for + exceptions. + +⚠️**Important:** +*The following properties must not be altered from default for use with the Dev Portal:* +* `logout_methods` +* `logout_query_arg` +* `logout_post_arg` + +For detailed descriptions of each configuration property, learn more in the [Session Plugin documentation](/enterprise/{{page.kong_version}}/plugins/session). + +## Session Security + +The Session configuration is secure by default, so the cookie uses the [Secure, HttpOnly](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Secure_and_HttpOnly_cookies), and [SameSite](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#SameSite_cookies) directives. + +⚠️**Important:** The following properties must be altered depending on the protocol and domains in use: +* If using HTTP instead of HTTPS: `"cookie_secure": false` +* If using different domains for [portal_api_url](/enterprise/{{page.kong_version}}/developer-portal/networking/#portal_api_url) and [portal_gui_host](/enterprise/{{page.kong_version}}/developer-portal/networking/#portal_gui_host): `"cookie_samesite": "off"` + +## Example Configurations + +If using HTTPS and hosting Dev Portal API and the Dev Portal GUI from the same domain, the following configuration could be used for Basic Auth: + +``` +portal_auth = basic-auth +portal_session_conf = { + "cookie_name":"$4m04$" + "secret":"change-this-secret" + "storage":"kong" +} +``` + +In testing, if using HTTP, the following configuration could be used instead: + +``` +portal_auth = basic-auth +portal_session_conf = { + "cookie_name":"04tm34l" + "secret":"change-this-secret" + "storage":"kong" + "cookie_secure":false +} +``` diff --git a/app/enterprise/1.3-x/developer-portal/configuration/index.md b/app/enterprise/1.3-x/developer-portal/configuration/index.md new file mode 100644 index 000000000000..fef2e041c151 --- /dev/null +++ b/app/enterprise/1.3-x/developer-portal/configuration/index.md @@ -0,0 +1,62 @@ +--- +title: Dev Portal Configuration +--- + + + +
+
+

+ SMTP

+

Configure the Dev Portal to send emails

+ + Learn More → +
+
+

+ Workspaces

+

Run multiple Dev Portals with Workspaces

+ + Learn More → +
+
diff --git a/app/enterprise/1.3-x/developer-portal/configuration/smtp.md b/app/enterprise/1.3-x/developer-portal/configuration/smtp.md new file mode 100644 index 000000000000..846e9c1fe871 --- /dev/null +++ b/app/enterprise/1.3-x/developer-portal/configuration/smtp.md @@ -0,0 +1,149 @@ +--- +title: Dev Portal SMTP Configuration +--- + +### Introduction + +The following property reference outlines each email and email variable used by the Dev Portal to send emails to Kong Admins and Developers. + +These settings can be modified in the `Kong Manager` under the Dev Portal `Settings / Email` tab. Or by running the following command: + +``` +curl http://localhost:8001/workspaces/ \ + --data "config.=off" +``` + +If they are not modified manually, the Dev Portal will use the default value defined in the Kong Configuration file. + + +### portal_invite_email + +**Default:** `on` + +**Description:** +When enabled, Kong Admins will be able to invite Developers to a Dev Portal by using the "Invite" button in the Kong Manager. + +**Email:** +``` +Subject: Invite to access Developer Portal + +Hello Developer! + +You have been invited to create a Developer Portal account at %s. +Please visit `` to create your account. +``` + + +### portal_email_verification + +**Default:** `off` + +**Description:** +When enabled Developers will receive an email upon registration to verify their account. Developers will not be able to use the Dev Portal until their account is verified, even if auto-approve is enabled. + + +### portal_access_request_email + +**Default:** `on` + +**Description:** +When enabled, Kong Admins specified by `smtp_admin_emails` will receive an email when a Developer requests access to a Dev Portal. + +``` +Subject: Request to access Developer Portal + +Hello Admin! + + has requested Developer Portal access for . +Please visit to review this request. +``` + + +### portal_approved_email + +**Default:** `on` + +**Description:** +When enabled, Developers will receive an email when access to a Dev Portal has been approved. + +``` +Subject: Developer Portal access approved + +Hello Developer! +You have been approved to access . +Please visit to login. + +``` + +### portal_reset_email + +**Default:** `on` + +**Description:** +When enabled, Developers will be able to use the "Reset Password" flow on a Dev Portal and will receive an email with password reset instructions. + +When disabled, Developers will *not* be able to reset their account passwords. + +``` +Subject: Password Reset Instructions for Developer Portal . + +Hello Developer, + +Please click the link below to reset your Developer Portal password. + + + +This link will expire in + +If you didn't make this request, keep your account secure by clicking +the link above to change your password. +``` + +### portal_reset_success_email + +**Default:** `on` + +**Description:** +When enabled, Developers will receive an email after successfully reseting their Dev Portal account password. + +When disabled, Developers will still be able to reset their account passwords, but will not recieve a confirmation email. + +``` +Subject: Developer Portal password change success + +Hello Developer, +We are emailing you to let you know that your Developer Portal password at has been changed. + +Click the link below to sign in with your new credentials. + + +``` + + +### portal_emails_from + +**Default:** `nil` + +**Description:** +The name and email address for the 'From' header included in all Dev Portal emails. + +**Example :** + +``` +portal_emails_from = Your Name +``` + + +### portal_emails_reply_to + +**Default:** `nil` + +**Description:** +The email address for the 'Reply-To' header included in all Dev Portal emails. + + +**Example :** + +``` +portal_emails_reply_to: noreply@example.com +``` diff --git a/app/enterprise/1.3-x/developer-portal/configuration/workspaces.md b/app/enterprise/1.3-x/developer-portal/configuration/workspaces.md new file mode 100644 index 000000000000..dc22eb8cdaea --- /dev/null +++ b/app/enterprise/1.3-x/developer-portal/configuration/workspaces.md @@ -0,0 +1,79 @@ +--- +title: Running Multiple Dev Portals with Workspaces +--- + +### Introduction + +Kong supports running multiple instances of the Dev Portal with the use of +[**Workspaces**](/enterprise/{{page.kong_version}}/admin-api/workspaces/reference). This allows each Workspace to enable +and maintain separate Dev Portals (complete with separate files, settings, and +authorization) from a within a single instance of Kong. + +### Managing Multiple Dev Portals within Kong Manager + +A snapshot of every Dev Portal within an instance of Kong can be viewed via +the Kong Manager's **Dev Portals** top navigation tab. + +This overview page details: + +- Whether a Dev Portal in a given Workspace is enabled or disabled +- A link to set up the Dev Portal if it is not enabled +- A link to each Dev Portal's homepage +- A link to each Dev Portal's individual overview page within Kong Manager +- Whether or not each Dev Portal is authenticated (indicated by a lock icon +in the upper right corner of each card) + +![Dev Portals Overview Page](https://konghq.com/wp-content/uploads/2018/11/devportals-overview.png) + + +### Enabling a Workspace's Dev Portal + +When a Workspace other than **default** is created, that Workspace's Dev Portal +will remain `disabled` until it is manually enabled. + +This can be done from the Kong Manager by clicking the **Set up Dev Portal** +button located on the **Dev Portals** Overview page, or by navigating directly +to a Workspace's **Dev Portal Settings** page via the sidebar and toggling the +`Dev Portal Switch`, or by sending the following cURL request: + +``` +curl -X PATCH http://localhost:8001/workspaces/ \ + --data "config.portal=true" +``` + +On intialization, Kong will populate the new Dev Portal with the [**Default Settings**](#defining-dev-portals-default-settings) defined in Kong's configuration file. + +>*Note* A Workspace can only enable a Dev Portal if the Dev Portal feature has been enabled in Kong's configuration. + + +### Defining the Dev Portal's URL structure + +The URL of each Dev Portal is automatically configured upon initialization and +is determined by four properties: + +1. The `portal_gui_protocol` property +2. The `portal_gui_host` property +3. Whether the `portal_gui_use_subdomains` property is enabled or disabled +4. The `name` of the Workspace + +Example URL with subdomains disabled: `http://localhost:8003/example-workspace` + +Example URL with subdomains enabled: `http://example-workspace.localhost:8003` + +The first three properties are controlled by Kong's configuration file and +cannot be edited via the Kong Manager. + +### Overriding Default Settings + +On initialization, the Dev Portal will be configured using the [**Default Portal Settings**] defined in Kong's configuration file. + +These settings can be manually overridden in the Dev Portals **Settings** tab +in the Kong Manager or by patching the setting directly. + +### Workspace Files + +On initialization of a Workspace's Dev Portal a copy of the **default** Dev Portal files will be made and inserted into the new Dev Portal. This allows for the easy transference of a customized Dev Portal theme and allows **default** to act as a 'master template' -- however the Dev Portal will not continue to sync changes from the **default** Dev Portal after it is first enabled. + +### Developer Access + +Access is not synced between Dev Portals. If an Admin or Developer would like access to multiple Dev Portals, they must sign up for each Dev Portal individually. diff --git a/app/enterprise/1.3-x/developer-portal/helpers/cli.md b/app/enterprise/1.3-x/developer-portal/helpers/cli.md new file mode 100644 index 000000000000..4fcef50eb86f --- /dev/null +++ b/app/enterprise/1.3-x/developer-portal/helpers/cli.md @@ -0,0 +1,62 @@ +--- +title: Developer Portal CLI +--- + + +### Introduction + +The Kong Developer Portal CLI is used to manage your Developer Portals from the +command line. It is built using [clipanion][clipanion]. + + +### Overview + +This is the next generation TypeScript based Developer Portal CLI. The goal of +this project is to make a higher quality CLI tool over the initial sync script. + +This project is built for Kong Enterprise `>= 1.3`. + +For Kong Enterprise `<= 0.36`, or for `legacy mode` on Kong Enterprise `>= 1.3` [use the legacy sync script][sync-script]. + + +### Install + +``` +> npm install -g kong-portal-cli +``` + + + +### Usage + +The easiest way to start is by cloning the [portal-templates repo][templates] dev-master branch locally. + +Then edit `workspaces/default/cli.conf.yaml` to set workspace `name` and `rbac_token` to match your setup. + +Make sure Kong is running and portal is on: + +Now from root folder of the templates repo you can run: + +```portal [-h,--help] [--config PATH] [-v,--verbose] ``` + +Where `` is one of: + +* `config` Output or change configuration of the portal on the given +* `workspace`, locally. +* `deploy` Deploy changes made locally under the given workspace upstream. +* `disable` Enable the portal on the given workspace. +* `enable` Enable the portal on the given workspace. +* `fetch` Fetches content and themes from the given workspace. +* `serve` Run the portal of a given workspace locally. +* `wipe` Deletes all content and themes from upstream workspace + +Add `--watch` to make changes reactive + + +[clipanion]: https://github.com/arcanis/clipanion +[sync-script]: https://github.com/Kong/kong-portal-templates/blob/81382f2c7887cf57bb040a6af5ca716b83cc74f3/bin/sync.js +[cli-support]: https://github.com/Kong/kong-portal-cli/issues/new +[cli-license]: https://github.com/Kong/kong-portal-cli/blob/master/LICENSE +[cli-contributors]: (https://github.com/Kong/kong-portal-cli/contributors) +[kong-support]: https://support.konghq.com/support/s/ +[templates]: https://github.com/Kong/kong-portal-templates diff --git a/app/enterprise/1.3-x/developer-portal/index.md b/app/enterprise/1.3-x/developer-portal/index.md new file mode 100644 index 000000000000..007f4ee36298 --- /dev/null +++ b/app/enterprise/1.3-x/developer-portal/index.md @@ -0,0 +1,26 @@ +--- +title: Kong Developer Portal +toc: false +book: developer-portal +chapter: 1 +--- + +![Dev Portal](https://doc-assets.konghq.com/1.3/dev-portal/dev-portal-homepage.png) + +The Kong Developer Portal provides a single source of truth for all developers +to locate, access and consume services. With intuitive content management for +documentation, streamlined developer onboarding, and roles based access controls +(RBAC), Kong’s Developer Portal provides a comprehensive solution for creating +and customizing a unified developer experience. + +The following series of documentation, guides, and references will show you how +to setup, extend, and customize your Kong Developer Portal. + +
+
+

+ + Get Started → +

+
+
\ No newline at end of file diff --git a/app/enterprise/1.3-x/developer-portal/introduction.md b/app/enterprise/1.3-x/developer-portal/introduction.md new file mode 100644 index 000000000000..67aeb7fa87ec --- /dev/null +++ b/app/enterprise/1.3-x/developer-portal/introduction.md @@ -0,0 +1,3 @@ +--- +redirect_to: /enterprise/1.3-x/developer-portal +--- \ No newline at end of file diff --git a/app/enterprise/1.3-x/developer-portal/legacy-migration.md b/app/enterprise/1.3-x/developer-portal/legacy-migration.md new file mode 100644 index 000000000000..9ed0a6b77cd4 --- /dev/null +++ b/app/enterprise/1.3-x/developer-portal/legacy-migration.md @@ -0,0 +1,49 @@ +--- +title: Migrating from the Legacy Developer Portal +book: developer-portal +chapter: 3 +--- + +### Introduction + +Starting in Kong Enterprise 1.3, the Kong Developer Portal supports a new +templating and file system. Because of these changes, existing Developer Portals +on 0.36 or earlier are no longer compatible and must me manually migrated to the +new file system. + +To learn more about the changes to the Developer Portal check out the +[What's new in 1.3](/enterprise/1.3-x/developer-portal/overview/#whats-new-in-1.3) +section in the Developer Portal [Overview](/enterprise/1.3-x/developer-portal/overview) +and the Kong Enterprise [Changelog](/enterprise/changelog). + + +### Enabling Legacy Mode + +When upgrading to Kong Enterprise 1.3 from 0.36, existing Portal files will be +saved and can be accessed with **Legacy Mode** enabled. This will allow the +Portal to function similarly to 0.36, but some features will be unavailable. To +access these new features, the new Portal must be enabled, and the files must +be manually ported over. + +To enable **Legacy Mode** set the following property in the Kong Configuration +file to `on`: + +``` +portal_is_legacy = on +``` + +### Migrating Spec Files + +Spec files must be manually recreated in the new Developer Portal, this can +be done by creating a new file in **Editor Mode** and copy and pasting the spec +file into the newly created file. This is the same process as the previous +version of the Developer Portal but will create the files in a different file +path, and therefore must be done manually. + +### Migrating Theme Customization + +The Kong Developer Portal version 1.3 uses a new templating engine, and therefore +existing theme files are not compatible. Themes customizations must be manually +redone to use the new templating system. Checkout the guide +[Working with Templates](/enterprise/{{page.kong_version}}/developer-portal/working-with-templates) to how to create pages and edit the new theme files. + diff --git a/app/enterprise/1.3-x/developer-portal/networking.md b/app/enterprise/1.3-x/developer-portal/networking.md new file mode 100644 index 000000000000..a0bfb6d23adf --- /dev/null +++ b/app/enterprise/1.3-x/developer-portal/networking.md @@ -0,0 +1,3 @@ +--- +redirect_to: /enterprise/1.3-x/property-reference/#dev-portal +--- \ No newline at end of file diff --git a/app/enterprise/1.3-x/developer-portal/overview.md b/app/enterprise/1.3-x/developer-portal/overview.md new file mode 100644 index 000000000000..674ff57cc01b --- /dev/null +++ b/app/enterprise/1.3-x/developer-portal/overview.md @@ -0,0 +1,199 @@ +--- +title: Getting Started with the Kong Developer Portal +toc: false +book: developer-portal +chapter: 2 +--- + +## What's new in 1.3 + +The Kong Developer Portal version 1.3 introduces a new templating engine and +file structure which should feel familiar to anyone who has used projects such +as Jekyll and Vuepress. If you are moving from the legacy portal to the newest +version the biggest changes are as follows: + +- **Files Database Structure** + - The files schema is simplified and now consists of only 2 fields, `path` and + `contents`. You can read more about these fields in the + [Structure and File Types](/enterprise/{{page.kong_version}}/developer-portal/structure-and-file-types) guide. +- **Templating language/structure** + - The templates have received a complete overhaul to take advantage of the new + Openresty native server-side/templating system. Content is now separate for + html templates, allowing for a more extensible, upgradable, and manageable system. + Check out the [Working with Templates](/enterprise/{{page.kong_version}}/developer-portal/working-with-templates) + guide to learn more. +- **Portal CLI** + - The Portal CLI tool is available to be used in conjunction with the + templates repo, allowing for easy a simplified push/pull/watch process to and + from your local machine and Kong. Checkout the [Dev Portal CLI](/enterprise/{{page.kong_version}}/developer-portal/helpers/cli) + reference to learn more. +- **Permissions** + - Developer Permissions make their debut in this version of the Portal, + allowing admins to categorize developers and determine what pages/content they + can or cannot see in each Developer Portal (think RBAC for Developers). Read the + [Developer Permissions](/enterprise/{{page.kong_version}}/developer-portal/administration/developer-permissions) + guide to learn more. + +### Breaking Changes + +The new Developer Portal is not compatible with previous Developer Portal +versions and templates. The legacy Developer Portal will supported through the +next few releases allowing current users to make the switch over before deprecation. +The release will include the functionality needed to support legacy deployments, +but will not be available via the demo build. + +Existing files will need to be manually migrated to the new Developer Portal, +learn more in the [Migrating from Legacy](/enterprise/1.3-x/developer-portal/legacy-migration) +guide. + +Read the full Kong Enterprise 1.3 Changelog [here](/enterprise/changelog). + + + + + + + + + + + + + diff --git a/app/enterprise/1.3-x/developer-portal/structure-and-file-types.md b/app/enterprise/1.3-x/developer-portal/structure-and-file-types.md new file mode 100644 index 000000000000..78472e4d8382 --- /dev/null +++ b/app/enterprise/1.3-x/developer-portal/structure-and-file-types.md @@ -0,0 +1,231 @@ +--- +title: Developer Portal Structure and File Types +book: developer-portal +chapter: 4 +--- + +### Introduction + +The Kong Portal templates have been completely revamped to allow for easier customization, clearer separation of concerns between content and layouts, and more powerful hooks into Kong lifecycle/data. Under the hood we have implemented a flat file CMS built on top of the `https://github.com/bungle/lua-resty-template` library. This system should feel familiar for anyone who has worked with projects like `jekyll`, `kirby cms`, or `vuepress` in the past. + +>Note: To follow along with this guide, it is best you clone down the [portal-tempalates-repo](https://github.com/Kong/kong-portal-templates) and checkout the `dev-master` branch. This guide will make the assumption that you are working within a single workspace (the templates repo can host many different sets of portal files per workspace). Navigate to the `workspaces/default` directory from root to view the default workspaces portal files. + + +### Directory Structure + +Navigate to `workspaces/default` from the kong-portal-templates root directory to access the default portals template files. The relative file structure in this directory will directly map to the file `path` schema attribute. (`content/homepage.txt` here will map to `content/homepage.txt` in Kong). + +From `workspaces/default` we can see the different elements that make up a single instance of the kong developer portal: +- **content** + - The content directory contains files that determine both site structure of the Kong Dev Portal as well as the dynamic content that will be rendered within each page. +- **specs** + - Specs are similar to content in that they contain the data needed to render dynamic content on the page. In the case of `specs` the files contain valid OAS or Swagger to be rendered as a spec. +- **themes** + - The theme directory contains different themes to be applied to the content of the portal. Each theme contains html templates, assets, and a config file which sets global styles available to the theme. +- **portal.conf.yaml** + - This config file determines which theme the portal uses to render, the name of the portal, as well configuration for special behavior such as redirect paths for user actions like login/logout. + + +#### `portal.conf.yaml` + +The `portal.conf.yaml` file determines which theme the portal uses to render, the name of the portal, as well configuration for special behavior such as redirect paths for user actions like login/logout. It is required in the root of every portal. + +Example: +``` +name: Kong Portal +theme: + name: light-theme +redirect: + unauthenticated: login + unauthorized: unauthorized + login: dashboard + logout: '' + pending_approval: '' + pending_email_verification: '' +``` + +- ###### `name`: + - **required**: true + - **type**: `string` + - **description**: The name attribute is used for meta information, such as setting a title for your portal in the browser tab. + - **example**: `Kong Portal` +- ###### `theme` + - **required**: true + - **type**: `object` + - **description**: The theme object is used for declaring which theme you would like your portal to render, as well as theme style overrides. While the overrides are not required, declaring which theme you would like to use is. +- ###### `redirect` + - **required**: true + - **type**: `object` + - **description**: The redirect object informs kong how to redirect the user after certain actions. If one of these values is not set, Kong will serve a default template based off of the action. + +#### `content/` +Content files establish portal site structure, as well as provide its accompanying html template with metadata and dynamic content at time of render. Below is an example of a basic content file: + +##### path +`content/homepage.txt` + +The path of a piece of content determines not only how a file is parsed, but the route in which it will render in the portal site structure. Below are examples of file paths and how they will be rendered in the portal: + - `content/index.txt` -> `/` + - `content/homepage.txt` -> `/homepage` + - `content/guides/index.txt` -> `/guides` + - `content/guides/howtocode.txt` -> `/guides/howtocode` + + +##### contents +``` +--- +title: homepage +layout: homepage.html +readable_by: [red, blue] +--- + +Welcome to the homepage! +``` + +Content can be broken down into two parts: + +##### headmatter + +The first thing you will notice in the example files contents are the two sets of `---` delimeters at the start. The text contained within these markers is called `headmatter` and will always be parsed and validated as valid `yaml`. `headmatter` contains information necessary for a file to render successfully, as well as any information you would like to access within a template. Any valid `yaml` key value pair will be parsed by Kong and made available within the contends coinciding html template. There are a few reserved attributes that have special meaning to Kong at time of render. They are as follows: + +- ###### `title`: + - **required**: false + - **type**: `string` + - **description**: The title attribute is not necessary but is recommended. When set this will set the title of a page in the browser tab. + - **example**: `homepage` +- ###### `layout` + - **required**: true + - **type**: `string` + - **description**: The layout attribute is required for each piece of content, and determines what html layout to use in order to render the page. This attribute assumes a root of the current themes layout directory (`themes//layouts`). + - **example**: `bio.html` or `team/about.html` +- ###### `readable_by` + - **required**: false + - **type**: `array` (multiple), `string` (singular) + - **description**: The optional readable_by attribute determines which developers can access a piece of content. In the case of the example above, only developers with rbac roles of "red" or "blue" may access the `/homepage` route. + - **example**: `[red, blue]` (multiple), `red` (singular) + +- ###### `route` + - **required**: false + - **type**: `string` + - **description**: This optional attribute overrides the generated route Kong assigns to content, and replaces it with the route included here. + - **example**: `route: /example/dog` will render the example page above at `/example/dog` instead of the auto generated `/homepage` route. +- ###### `output` + - **required**: false + - **type**: `boolean` + - **default**: `true` + - **description**: This optional attribute is `true` by default and determines whether a piece of content should be rendered. (no route or page will be created when set to `false`) +- ###### `stub` + - **required**: false + - **type**: `string` + - **description**: Used by `collection` config to determine custom routing. You can read more about Collections in the collections section of this guide. + +##### body +The information located under headmatter represents the content body. Body content is freeform and will be parsed as by the file extension included in the file path. In the case of the example above, the file is `.txt` and will be available in the template as such. + +#### `specs/` +Specs are similar to `content` files in that they provide the dynamic data needed to render a page, as well as any metadata a user wishes to provide as `headmatter`. The format in which these are provided to the Portal differs from `content` files, which can be seen in the example below: + +#### path +`specs/myfirstspec.yaml` + +Pathing for specs is very simple, it is recommended to keep spec folder structure flat. Spec files must be valid OAS or Swagger `.yaml` or `.json` files. + +#### contents +``` +swagger: "2.0" +layout: system/spec-renderer.html +info: + version: 1.0.0 + title: Swagger Petstore + license: + name: MIT +host: petstore.swagger.io +basePath: /v1 +x-headmatter + - key1: val1 + - key2: val2 +... +``` + +Spec file contents themselves should be valid OAS or Swagger specifications. If you would like to inject headmatter to the specification, you can do so by including an `x-headmatter` key to the root of the spec object. This may be useful if you wanted to for example provide your own renderer template via `headmatter.layout` or override the specs default route via `headmatter.route`. + +Example: +``` +swagger: "2.0" +layout: system/spec-renderer.html +info: + version: 1.0.0 + title: Swagger Petstore + license: + name: MIT +host: petstore.swagger.io +basePath: /v1 +x-headmatter: + layout: custom/my-spec-renderer.html <- Custom Layout + route: my-special-route/myfirstspec <- Custom Route +... +``` + +Specs are a collection meaning their `layout` and `route` are determined by portal configuration and not the file itself. Specs are rendered with the `system/spec-renderer.html` layout, under the route pattern `/documentation/:name` where name is the name of the particular spec file. So a spec with a path of `specs/myfirstspec.json` will render in the portal as `/documentation/myfirstspec`. If you would like to overwrite the hard coded spec collection config, you can do so by including your own in `portal.conf.yaml`. + + +#### `themes//...` +The theme directory contains different instances of portal themes, each one of which determines the look and feel of the developer portal via html/css/js. Which theme is used at time of render is determined by setting `theme.name` within `portal.conf.yaml`. (setting `theme.name` to `best-theme` will cause the portal to load theme files under `themes/best-theme/**`). + +Each theme file is compromised of a few different folders: +- **assets/** + - The assets directory contains static assets that layouts/partials will reference at time of render. Includes CSS, JS, font, and image files. +- **layouts/** + - The layouts directory contains html page templates that `content` reference via the `layout` attribute in headmatter (see `content` section). +- **partials/** + - The partials directory contains html partials to be referenced by layouts. Can be compared to how layouts and partials interacted in the legacy portal. +- **theme.conf.yaml** + - This config file sets color and font defaults available to templates for reference as css variables. It also determines what options are available in the Kong Manager Appearance page. + +#### assets +The asset folder contains css/js/fonts/images for your templates to reference. To access asset files from your templates, keep in mind that Kong assumes a path from the root of your selected theme. + +- Examples: + - `themes/light-theme/assets/images/image1.jpeg` -> `` + - `themes/light-theme/assets/js/my-script.js` -> `` + - `themes/light-theme/assets/styles/my-styles.css` -> `` + +#### layouts +Layouts act as the html skeleton of the page you wish to render. Each file within the layouts directory must have an `html` filetype. They can exist as vanilla `html`, or can reference partials and parent layouts via the portals templating syntax. Layouts also have access to the `headmatter` and `body` attributes set in `content`. + +The example below shows what a typical layout could look like. + +``` +
+ {(partials/header.html)} <- syntax for calling a partial within a template +
+
+

{{page.title}}

<- 'title' retrieved from page headmatter +
+
+

{{page.body}}

<- 'body' retrieved from page body +
+
+ {(partials/footer.html)} +
+``` + +To learn more about the templating syntax used in this example check out the `templating` section. + +#### partials +Partials are very similar to layouts: they share the same syntax, can call other partials within themselves, and have access to the same data/helpers at time of render. The thing that differentiates partials from layouts it that layouts call on partials to build the page, but partials cannot call on layouts. + +The example below shows the `header.html` partial referenced from the example above: + +``` +
+
+
<- can access the same page data the parent layout +
+
+ {(partials/header_nav.html)} <- partials can call other partials +
+
+
+``` diff --git a/app/enterprise/1.3-x/developer-portal/theme-customization/easy-theme-editing.md b/app/enterprise/1.3-x/developer-portal/theme-customization/easy-theme-editing.md new file mode 100644 index 000000000000..c88f8dc23659 --- /dev/null +++ b/app/enterprise/1.3-x/developer-portal/theme-customization/easy-theme-editing.md @@ -0,0 +1,34 @@ +--- +title: Easy Theme Editing in Kong Manager +--- + +### Introduction + +The Kong Developer Portal ships with a default theme, including preset images, background colors, fonts, and button styles. These settings can be edited quickly and easily from within Kong Manager, without the need to edit code. + +### Prerequisites + +* Kong Enterprise 1.3 or later +* Access to Kong Manager +* The Developer Portal is enabled and running + +### The Appearance Tab + +From the **Workspace** dashboard in **Kong Manager**, click on the **Appearance** tab under **Dev Portal** on the left side bar. +This will open the Developer Portals theme editor. From this page the header logo, background colors, font colors, and button styles can be edited using the color picker interface. + +![Appearance Tab](https://doc-assets.konghq.com/1.3/dev-portal/easy-themes/devportal-appearance-tab.png) + +The predefined variables refer to the following elements: + +![Appearance Tab - Variables](https://doc-assets.konghq.com/1.3/dev-portal/easy-themes/devportal-appearance-arrows.png) + +Hovering over an element will show a color picker, as well as a list of predefined colors. These colors are defined by the current template and can be edited in the [theme.conf.yaml](#editing-theme-files-with-the-editor) file + +![Appearance Tab - Color Picker](https://doc-assets.konghq.com/1.3/dev-portal/easy-themes/devportal-appearance-tab-variable-hover.png) + +## Editing Theme Files with the Editor + +The Dev Portal Editor within Kong Manager exposes the default Dev Portal theme files. The theme files can be found at the bottom of the file list under *Themes*. The variables exposed in the *Appearance* tab can be edited in the theme.conf.yaml file. See [Using the Editor](/enterprise/{{page.kong_version}}/developer-portal/using-the-editor) for more information on how to edit, preview, and save files in the Editor. + +![Theme File in Editor](https://doc-assets.konghq.com/1.3/dev-portal/easy-themes/devportal-theme-conf-yaml.png) \ No newline at end of file diff --git a/app/enterprise/1.3-x/developer-portal/using-the-editor.md b/app/enterprise/1.3-x/developer-portal/using-the-editor.md new file mode 100644 index 000000000000..fc97260a475f --- /dev/null +++ b/app/enterprise/1.3-x/developer-portal/using-the-editor.md @@ -0,0 +1,76 @@ +--- +title: Using the Editor +--- + +### Introduction + +Kong Manager offers a robust file editor for editing the template files of the Dev Portal from within the browser. + +![Dev Portal Editor](https://doc-assets.konghq.com/1.3/dev-portal/editor/devportal-editor-homepage.png) + +### Prerequisites + +* Kong Enterprise 1.3 or later +* Access to Kong Manager +* The Kong Developer Portal is **enabled** and **running** + +>NOTE: Editor Mode is *not* available when running the Dev Portal in **legacy** mode + +### Enter Editor Mode + +From the **Kong Manager** dashboard of your **Workspace**, click “Editor” under “Dev Portal” in the sidebar. + +![Launch Editor Mode](https://doc-assets.konghq.com/1.3/dev-portal/editor/devportal-editor-sidebar-button.png) + + +This will launch the **Editor Mode**: + +![Editor Mode](https://doc-assets.konghq.com/1.3/dev-portal/editor/devportal-editor-mode-launch.png) + + +>Note: Editor Mode is a *live* editor - once Saved, changes to files will propagate to the Dev Portal *immediately*. + + +### Navigating the Editor + +When enabled, the Dev Portal is pre-populated with Kong's default theme. The file editor exposes these files to the UI, allowing them to be edited quickly and easily from inside the browser. When you first open the editor you will be presented with a list of files on the left, and a blank editing form. + +1. Create new files for the Dev Portal right from the Editor by clicking `New File+` +2. List of all exposed template files in the Dev Portal, separated by Content / Spec / Themes +3. Code View - Select a file from the sidebar to show the code here +4. Portal Preview - a live preview of the selected Dev Portal file +5. Toggle View - Choose between three different views, full screen code, a split view, and full screen preview mode + +![Dev Portal with Numbers](https://doc-assets.konghq.com/1.3/dev-portal/editor/devportal-editor-numbers.png) + +### Editing Files + +Select a file from the sidebar to open it for editing - this will expose the file to the Code View and show a live update in the Portal Preview. Clicking “Save” in the top right corner will save the updates to the database and update the file on the Dev Portal. + +![Editing a File](https://doc-assets.konghq.com/1.3/dev-portal/editor/devportal-editor-edit-file.png) + + + +### Adding new files + +Clicking the `New File +` button will open the New File Dialog. + +![Add New File](https://doc-assets.konghq.com/1.3/dev-portal/editor/devportal-editor-new-file.png) + +Once created, files will immediately be available from within the Editor. + + +### Authenticating Files + +Authentication is handled by readable_by value on content pages (for gui view go to permissions page) + - set readable_by: '*' to equal old authenticated + - to restrict access to certain roles, set readably to an array of accepted roles (must create roles first on permissions page) + - on specs readable_by is set inside "x-headmatter" object + + +### Deleting files + +To delete a file from within the Editor, right click on the file name and select `Delete` from the pop-up menu. +**NOTE** This action cannot be undone. + +![Deleting Files](https://doc-assets.konghq.com/1.3/dev-portal/editor/devportal-editor-delete-file.png) \ No newline at end of file diff --git a/app/enterprise/1.3-x/developer-portal/working-with-templates.md b/app/enterprise/1.3-x/developer-portal/working-with-templates.md new file mode 100644 index 000000000000..df02bff23c9f --- /dev/null +++ b/app/enterprise/1.3-x/developer-portal/working-with-templates.md @@ -0,0 +1,209 @@ +--- +title: Working with Templates +--- + +### Introduction + +Kong Portal 1.3 is built on top of the `lua-resty-template` templating library which can be viewed here: https://github.com/bungle/lua-resty-template. Basic usage of the library will be described below, reference the source documentation for a more in-depth look at what it can accomplish. + +### Syntax +***(excerpt from lua-resty-templates documentation)*** + +You may use the following tags in templates: +{% raw %} +* `{{expression}}`, writes result of expression - html escaped +* `{*expression*}`, writes result of expression +* `{% lua code %}`, executes Lua code +* `{(path-to-partial)}`, include `partial` file by path, you may also supply context for the file `{(partials/header.html, { message = "Hello, World" } )}` + +* `{-block-}...{-block-}`, wraps inside of a `{-block-}` to a value stored in a `blocks` table with a key `block` (in this case), see [using blocks](https://github.com/bungle/lua-resty-template#using-blocks). Don't use predefined block names `verbatim` and `raw`. +* `{-verbatim-}...{-verbatim-}` and `{-raw-}...{-raw-}` are predefined blocks whose inside is not processed by the `lua-resty-template` but the content is outputted as is. +* `{# comments #}` everything between `{#` and `#}` is considered to be commented out (i.e. not outputted or executed) +{% endraw %} + +### Using Partials + +Partials are snippets of html that layouts can reference. Partials have access to all the same data that its layout does, and can even call other partials. Breaking your code into partials can help organize large pages, as well as allow different layouts share common page elements. + +##### content/index.txt + +{% raw %} +``` +--- +layout: index.html +title: Partials +header_logo: assets/images/example.jpeg +header_nav_items: + about: + href: /about + guides: + href: /guides +hero_title: Partials Info +hero_description: Partials are wicked sick! +--- +``` +{% endraw %} + +##### layouts/index.html + +{% raw %} +```html +{(partials/header.html)} +
+ {(partials/hero.html)} +
+{(partials/footer.html)} +``` +{% endraw %} + +##### partials/header.html + +{% raw %} +```html +
+
+ +
+
+ {(partials/header_nav.html)} +
+
+``` +{% endraw %} + +##### partials/header_nav.html + +{% raw %} +``` html +
    + {% for title, href in each(page.header_nav_items) do %} +
  • {{title}}
  • + {% end %} +
+``` +{% endraw %} + +##### partials/hero.html + +{% raw %} +``` html +

{{page.hero_title}}

+

{{page.hero_description}}

+``` +{% endraw %} + + +##### partials/hero.html + +{% raw %} +``` html +
+

footer

+
+``` +{% endraw %} + + +##### Output + +{% raw %} +```html +
+
+ +
+
+ +
+
+

Partials Info

+

Partials are wicked sick!

+
+

footer

+
+``` +{% endraw %} + +### Using Blocks + +Blocks can be used to embed a view or partial into another template. Blocks are particularly useful when you would like different templates to share a common wrapper. + +In the example below notice that the content file is referencing `index.html`, and not `wrapper.html`. + +##### content/index.txt + +{% raw %} +```markdown +--- +layout: index.html +title: Blocks +description: Blocks are the future! +--- +``` +{% endraw %} + + +##### layouts/index.html + +{% raw %} +```html +{% layout = "layouts/wrapper.html" %} <- syntax declaring where to find the block + +{-main-} <- delimiter describing what content renders in block +
+

{{page.title}}

+

{{page.description}}

+

+{-main-} +``` +{% endraw %} + +##### layouts/wrapper.html + +{% raw %} +```html + + + + Testing lua-resty-template blocks + + +
+

header

+
+ {*main*} <- syntax indicating where to place the block +
+

footer

+
+ + +``` +{% endraw %} + +##### Output + +{% raw %} +```html + + + + Testing lua-resty-template blocks + + +
+

header

+
+
+

Blocks

+

Blocks are the future!

+

+
+

footer

+
+ + +``` +{% endraw %} \ No newline at end of file diff --git a/app/enterprise/1.3-x/getting-started/add-admin.md b/app/enterprise/1.3-x/getting-started/add-admin.md new file mode 100644 index 000000000000..d39e0175510c --- /dev/null +++ b/app/enterprise/1.3-x/getting-started/add-admin.md @@ -0,0 +1,68 @@ +--- +title: How to Add an Admin +toc: false +--- +#### Table of Contents + +- [Introduction](#introduction) +- [Prerequisites](#prerequisites) +- [Video Walkthrough](#video-walkthrough) +- [Step 1](#step-1) +- [Step 2](#step-2) +- [Step 3](#step-3) +- [Step 4](#step-4) +- [Step 5](#step-5) +- [Step 6](#step-6) + +### Introduction + +An **Admin** is any user in Kong Manager. They may access +Kong entities within their assigned **Workspaces** based +on the **Permissions** of their **Roles**. + +This guide describes how to invite an **Admin** in Kong +Manager. As an alternative, if a **Super Admin** wants to +invite an **Admin** with the Admin API, it is possible to +do so using +[`/admins`](/enterprise/{{page.kong_version}}/admin-api/admins/reference/#invite-an-admin). + +### Prerequisites + +* [`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** +* SMTP must be configured to [send invitation emails](/enterprise/{{page.kong_version}}/kong-manager/networking/email/), +but to simply test this workflow without actually sending +an email, leave [`smtp_mock = on`](/enterprise/{{page.kong_version}}/property-reference/#smtp_mock). See +[How to Copy and Send a Registration Link](/enterprise/{{page.kong_version}}/kong-manager/administration/admins/invite/#how-to-copy-and-send-a-registration-link) +for details on how to +copy a registration link instead of sending an email. + +## Step 1 + +On the **Admins** page, to invite a new **Admin**, click the +**Create New Admin** button. + +## Step 2 + +Assign the appropriate **Role** and click "Invite Admin" to send +the invitation. + +**Note:** When a new **Admin** receives an invitation, they will +only be able to log in with that email address. + +![Create New Admin](https://konghq.com/wp-content/uploads/2018/11/km-name-admin.png) + +## Step 3 + +On the **Admin** page, the new invitee will appear on the list with +the **invited** status. Once they accept the invitation, their +status will change to **accepted**. + +![Invited Admins](https://konghq.com/wp-content/uploads/2018/11/km-invited-admins.png) + +## Step 4 + +The newly invited **Admin** will have the ability to set a password. +If the **Admin** forgets the password, it is possible to reset it +through a recovery email. diff --git a/app/enterprise/1.3-x/getting-started/add-consumer.md b/app/enterprise/1.3-x/getting-started/add-consumer.md new file mode 100644 index 000000000000..78a1e3cf29a3 --- /dev/null +++ b/app/enterprise/1.3-x/getting-started/add-consumer.md @@ -0,0 +1,71 @@ +--- +title: How to Add a Consumer +--- + +## 1. Create a Consumer + +If you'd like to use the Admin API, issue the following cURL request to +create your first Consumer, named `Aladdin`: + +```bash +$ curl -i -X POST \ + --url http://localhost:8001/consumers/ \ + --data "username=Aladdin" +``` + +You should see a response similar to the one below: + +```http +HTTP/1.1 201 Created +Content-Type: application/json +Connection: keep-alive + +{ + "username": "Aladdin", + "created_at": 1428555626000, + "id": "bbdf1c48-19dc-4ab7-cae0-ff4f59d87dc9" +} +``` +Or, add your first Consumer via Kong Manager: + + + +Congratulations! You've just added your first Consumer to Kong. + +**Note:** Kong also accepts a `custom_id` parameter when +[creating Consumers][API-consumers] to associate a Consumer with your existing +user database. + +## 2. Provision Credentials for Your Consumer + +Now, we can create credentials for our recently created Consumer `Aladdin` by +issuing the following request: + +```bash +$ curl -i -X POST \ + --url http://localhost:8001/consumers/Aladdin/basic-auth/ \ + --data "username=Aladdin" \ + --data "password=OpenSesame" +``` + +## 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. + +Then the Authorization (or Proxy-Authorization) header must appear as: + +``` +Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l +``` + +To verify our new Consumer has access, make a request with the header: + +```bash +$ curl http://kong:8000/{path matching a configured Route} \ + -H 'Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l' +``` diff --git a/app/enterprise/1.3-x/getting-started/add-role.md b/app/enterprise/1.3-x/getting-started/add-role.md new file mode 100644 index 000000000000..f0b0f6ff0572 --- /dev/null +++ b/app/enterprise/1.3-x/getting-started/add-role.md @@ -0,0 +1,91 @@ +--- +title: How to Add a Role and Permissions +toc: false +--- +#### Table of Contents + +- [Introduction](#introduction) +- [Prerequisites](#prerequisites) +- [Video Walkthrough](#video-walkthrough) +- [Step 1](#step-1) +- [Step 2](#step-2) +- [Step 3](#step-3) +- [Step 4](#step-4) +- [Step 5](#step-5) +- [Step 6](#step-6) + +### Introduction + +**Roles** make it easy to logically group and apply the same +set of **Permissions** to **Admins**. **Permissions** may be +customized in detail, down to individual actions and endpoints. + +Kong Enterprise includes default **Roles** for standard +use cases, e.g. inviting additional **Super Admins**, +inviting **Admins** that may only `read` endpoints. + +This guide describes how to create a custom **Role** in Kong +Manager for a unique use case. As an alternative, if a +**Super Admin** wants to create a **Role** with the Admin API, +it is possible to do so using +[`/rbac/roles`](/enterprise/{{page.kong_version}}/admin-api/rbac/reference/#add-a-role). +To add **Permissions** to the new **Role**, use +[`/rbac/roles/{name_or_id}/endpoints`](/enterprise/{{page.kong_version}}/admin-api/rbac/reference/#add-a-role-endpoint-permission) +for endpoints or +[`/rbac/roles/{name_or_id}/entities`](/enterprise/{{page.kong_version}}/admin-api/rbac/reference/#add-a-role-entity-permission) +for specific entities. + +### Prerequisites + +* [`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** + +## Video Walkthrough + + + +## Step 1 + +On the **Admins** page, to create a new **Role**, click the +**Add Role** button at the top right of the list of **Roles**. + +## Step 2 + +On the **Add Role** form, name the **Role** according to the +**Permissions** you want to grant. + +![New Role naming](https://konghq.com/wp-content/uploads/2018/11/km-new-role.png) + +**Note:** It may be helpful for future reference to include +a brief comment describing the reason for the **Permissions** or +a summary of the **Role**. + +## Step 3 + +Click the **Add Permissions** button and fill out the form. Add the endpoint **Permissions** by marking the appropriate checkbox. + +![New Role permissions](https://konghq.com/wp-content/uploads/2018/11/km-perms.png) + +## Step 4 + +Click **Add Permission to Role** to see the permissions listed on the form. + +![New Role permissions list](https://konghq.com/wp-content/uploads/2018/11/km-perms-list.png) + +## Step 5 + +To forbid access to certain endpoints, click **Add Permission** +again and use the **negative** checkbox. + +![Negative permissions](https://konghq.com/wp-content/uploads/2018/11/km-negative-perms.png) + +## Step 6 + +Submit the form and see the new **Role** appear on the +**Admins** page. + +![Roles list](https://konghq.com/wp-content/uploads/2018/11/km-roles-list.png) diff --git a/app/enterprise/1.3-x/getting-started/add-service.md b/app/enterprise/1.3-x/getting-started/add-service.md new file mode 100644 index 000000000000..f18372ac4a41 --- /dev/null +++ b/app/enterprise/1.3-x/getting-started/add-service.md @@ -0,0 +1,109 @@ +--- +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/). + +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 +the requester as responses. This visibility is helpful for learning how Kong proxies API +requests. + +Kong exposes the RESTful **Admin API** on port `:8001`. Kong’s configuration, +including adding **Services and Routes**, is made via requests on to the +**Admin API**. + +### 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** + +### Step 1 - Create a New Service + +1. Chose the desired **Workspace** in **Kong Manager** and navigate to the +**Services** tab under **API Gateway**. + + ![Service Page](https://doc-assets.konghq.com/0.35/getting-started/add-a-service/01-service-page.png) + +2. Click the **Create a New Service** button to open the **Create Service** form. +Fill in a **name** and a **URL** for the **Service**.

For example, set the +name to `test-service` with the URL `http://mockbin.org`. + + ![Create Service Form](https://doc-assets.konghq.com/0.35/getting-started/add-a-service/02-service-name.png) +

Kong Manager also allows **Services** to be configured using **Protocol**, +**Host**, **Path**, and **Port** (optional). To configure the **Service** using +this method, click the **Add using Protocol, Host, and Path** option. + + ![Configure Using Protocol](https://doc-assets.konghq.com/0.35/getting-started/add-a-service/03-service-protocol.png) +
In addition, Kong Manager exposes several **Advanced Fields** +and their default configuration values:
`Retries: 5`
+`Connect Timeout: 60000` (in ms)
`Write Timeout: 60000` (in ms)
+`Read Timeout: 60000` (in ms)

Adjusting these values is optional and can be +edited later. + + ![Advanced Fields](https://doc-assets.konghq.com/0.35/getting-started/add-a-service/04-service-advanced-fields.png) + + +3. Create the **Service** by clicking the **Create Service** button at the bottom of +the form.

If successful, you will be automatically redirected to the +**Service's Overview** page.

The **Service Overview** page displays +information and **Activity** on the **Service**, as well as any **Routes** or +**Plugins** that have been connected to the **Service**. + + ![Service Overview](https://doc-assets.konghq.com/0.35/getting-started/add-a-service/05-service-overview.png) + + +### Step 2 - Create a New Route attached to the Service + +1. From the **Service Overview** page accessed in +[Step 1](#step-1---create-a-new-service), click the **Create New Route** button +located in the **Routes** tab at the bottom of the page. + + ![Create Route Service ID](https://doc-assets.konghq.com0.35/getting-started/add-a-service/06-service-route-object.png) + +2. To create a **Route** you must provide the **Service** `name` and `id`, this +will be automatically filled out if the form was accessed via the +**Service Overview** page. + + ![Step 7](https://doc-assets.konghq.com/0.35/getting-started/add-a-service/07-route-service-id.png) +

If this field is not automatically filled, the **Service Id** can be +found via the **Services Overview** page, accessed by clicking on the **Services** +tab on the side navigation and then clicking the **clipboard** icon next to the +desired **Service's Id** field. + +3. The **Route** will also need a name, and at least one of the following fields: +**Host**, **Methods**, or **Paths**
To continue with the Mockbin example, +name the **Route** `test-route` with the **Host** `example.com`. Once completed, +click the **Create Route** button at the bottom of the form. + + ![Create Route Form](https://doc-assets.konghq.com/0.35/getting-started/add-a-service/08-route-form-example.png) + +4. If created successfully, the page will be automatically redirected back to +the **Service Overview** page, and the new **Route** will now appear under the +**Routes** tab. + + ![Completed Route](https://doc-assets.konghq.com/0.35/getting-started/add-a-service/10-completed-route.png) + +### Step 3 - Test the new Service and Route + +Issue the following cURL request to verify that Kong is properly forwarding +requests to the Service. Note that by default Kong handles proxy requests on +port `:8000`: + +``` + $ curl -i -X GET \ + --url http://localhost:8000/ \ + --header 'Host: example.com' +``` + +A successful response means Kong is now forwarding requests made to +http://localhost:8000 to the **Service URL** configured in +[Step 1](#step-1---create-a-new-service), and is forwarding the response back. +Kong knows to do this through the header defined in the above cURL request. diff --git a/app/enterprise/1.3-x/getting-started/add-workspace.md b/app/enterprise/1.3-x/getting-started/add-workspace.md new file mode 100644 index 000000000000..25638fc26371 --- /dev/null +++ b/app/enterprise/1.3-x/getting-started/add-workspace.md @@ -0,0 +1,109 @@ +--- +title: How to Add a Workspace +toc: false +--- +#### Table of Contents + +- [Introduction](#introduction) +- [Prerequisites](#prerequisites) +- [Video Walkthrough](#video-walkthrough) +- [Step 1](#step-1) +- [Step 2](#step-2) +- [Step 3](#step-3) +- [Step 4](#step-4) +- [Step 5](#step-5) +- [Next Steps](#next-steps) + +### Introduction + +Although an organization's teams share the same Kong cluster, +it is possible to divide the cluster into logical groups with +limited access. These **Workspaces** provide clearer +segmentation of traffic and entities. Each team's +access may be restricted to their own **Workspace**, supporting +the principle of least privilege. + +The guide below describes how to create **Workspaces** in Kong +Manager. As an alternative, if a **Super Admin** wants to create +a **Workspace** with the Admin API, it is possible to do so +using the [`/workspaces/` route](/enterprise/{{page.kong_version}}/admin-api/workspaces/reference/#add-workspace). + +### Prerequisites + +* [`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** + +## Video Walkthrough + + + +## Step 1 + +On the **Workspaces** page, click the **New Workspace** +button at the top right to open the **Create Workspace** form. + +![New Workspace Form](https://konghq.com/wp-content/uploads/2018/11/km-new-workspace.png) + +## Step 2 + +Name the new **Workspace**. + +![Name the New Workspace](https://konghq.com/wp-content/uploads/2018/11/km-name-ws.png) + +⚠️ **WARNING**: Each **Workspace** name should be unique, +regardless of letter case. For example, naming one +**Workspace** "Payments" and another one "payments" will +create two different workspaces that appear identical. + +⚠️ **WARNING**: Do not name Workspaces the same as these major +routes in Kong Manager: + +* Admins +* APIs +* Certificates +* Consumers +* Plugins +* Portal +* Routes +* Services +* SNIs +* Upstreams +* Vitals + +## Step 3 + +Select a color or avatar to make each **Workspace** easier +to distinguish, or accept the default color. + +![Select Workspace Color](https://konghq.com/wp-content/uploads/2018/11/km-color-ws.png) + +## Step 4 + +Click the **Create New Workspace** button. + +![New Dashboard](https://konghq.com/wp-content/uploads/2018/11/km-new-dashboard.png) + +Upon creation, the **Workspace**'s **Dashboard** page will +appear. + +## Step 5 + +On the left sidebar, click the **Admins** link in the +**Security** section. (If the sidebar is collapsed, hover over +the **security badge icon** at the bottom and click the +**Admins** link.) + +![Admins Hover Over](https://konghq.com/wp-content/uploads/2018/11/admins-section.png) + +### Next Steps + +The **Admins** page displays a list of current **Admins** and +**Roles**. Four default **Roles** specific to the new +**Workspace** are already visible, and new **Roles** specific +to the **Workspace** can be assigned from this page. + +![New Workspace Admins](https://konghq.com/wp-content/uploads/2018/11/km-ws-admins.png) diff --git a/app/enterprise/1.3-x/getting-started/configuring-a-grpc-service.md b/app/enterprise/1.3-x/getting-started/configuring-a-grpc-service.md new file mode 100644 index 000000000000..c477288a1aa9 --- /dev/null +++ b/app/enterprise/1.3-x/getting-started/configuring-a-grpc-service.md @@ -0,0 +1,275 @@ +--- +title: Configuring a gRPC Service +--- + +Note: this guide assumes familiarity with gRPC; for learning how to set up +Kong with an upstream REST API, check out the [Configuring a Service guide][conf-service]. + +Starting with Kong Enterprise 1.3, gRPC proxying is natively supported in Kong. In this +section, you'll learn how to configure Kong to manage your gRPC services. For the +purpose of this guide, we'll use [grpcurl][grpcurl] and [grpcbin][grpcbin] - they +provide a gRPC client and gRPC services, respectively. + +We will describe two setups: Single gRPC Service and Route and single gRPC Service +with multiple Routes. In the former, a single catch-all Route is configured, which +proxies all matching gRPC traffic to an upstream gRPC service; the latter demonstrates +how to use a Route per gRPC method. + +In Kong Enterprise 1.3, gRPC support assumes gRPC over HTTP/2 framing. As such, make sure +you have at least one HTTP/2 proxy listener (check out the [Configuration Reference][configuration-rerefence] +for how to). In this guide, we will assume Kong is listening for HTTP/2 proxy +requests on port 9080. + +## 1. Single gRPC Service and Route + +Issue the following request to create a gRPC Service (assuming your gRPC +server is listening in localhost, port 15002): + +```bash +$ curl -XPOST localhost:8001/services \ + --data name=grpc \ + --data protocol=grpc \ + --data host=localhost \ + --data port=15002 +``` + +Issue the following request to create a gRPC route: + +```bash +$ curl -XPOST localhost:8001/services/grpc/routes \ + --data protocols=grpc \ + --data name=catch-all \ + --data paths=/ +``` + +Using the [grpcurl][grpcurl] command line client, issue the following gRPC +request: + +```bash +$ grpcurl -v -d '{"greeting": "Kong 1.3!"}' \ + -plaintext localhost:9080 hello.HelloService.SayHello +``` + +The response should resemble the following: + +``` +Resolved method descriptor: +rpc SayHello ( .hello.HelloRequest ) returns ( .hello.HelloResponse ); + +Request metadata to send: +(empty) + +Response headers received: +content-type: application/grpc +date: Tue, 16 Jul 2019 21:37:36 GMT +server: openresty/1.15.8.1 +via: kong/1.2.1 +x-kong-proxy-latency: 0 +x-kong-upstream-latency: 0 + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response trailers received: +(empty) +Sent 1 request and received 1 response +``` + +Notice that Kong response headers, such as `via` and `x-kong-proxy-latency`, were +inserted in the response. + +## 2. Single gRPC Service with Multiple Routes + +Building on top of the previous example, let's create a few more routes, for +individual gRPC methods. + +The gRPC "HelloService" service being used in this example exposes a few different +methods, as can be seen in [its protobuf file][protobuf]. We will create individual +routes for its "SayHello" and LotsOfReplies methods. + +Create a Route for "SayHello": + +```bash +$ curl -XPOST localhost:8001/services/grpc/routes \ + --data protocols=grpc \ + --data paths=/hello.HelloService/SayHello \ + --data name=say-hello +``` + +Create a Route for "LotsOfReplies": + +```bash +$ curl -XPOST localhost:8001/services/grpc/routes \ + --data protocols=grpc \ + --data paths=/hello.HelloService/LotsOfReplies \ + --data name=lots-of-replies +``` + +With this setup, gRPC requests to the "SayHello" method will match the first +Route, while requests to "LotsOfReplies" will be routed to the latter. + +Issue a gRPC request to the "SayHello" method: + +```bash +$ grpcurl -v -d '{"greeting": "Kong 1.3!"}' \ + -H 'kong-debug: 1' -plaintext \ + localhost:9080 hello.HelloService.SayHello +``` + +(Notice we are sending a header `kong-debug`, which causes Kong to insert +debugging information in response headers.) + +The response should look like: + +``` +Resolved method descriptor: +rpc SayHello ( .hello.HelloRequest ) returns ( .hello.HelloResponse ); + +Request metadata to send: +kong-debug: 1 + +Response headers received: +content-type: application/grpc +date: Tue, 16 Jul 2019 21:57:00 GMT +kong-route-id: 390ef3d1-d092-4401-99ca-0b4e42453d97 +kong-service-id: d82736b7-a4fd-4530-b575-c68d94c3493a +kong-service-name: s1 +server: openresty/1.15.8.1 +via: kong/1.2.1 +x-kong-proxy-latency: 0 +x-kong-upstream-latency: 0 + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response trailers received: +(empty) +Sent 1 request and received 1 response +``` + +Notice the Route ID should refer to the first route we created. + +Similarly, let's issue a request to the "LotsOfReplies" gRPC method: + +```bash +$ grpcurl -v -d '{"greeting": "Kong 1.3!"}' \ + -H 'kong-debug: 1' -plaintext \ + localhost:9080 hello.HelloService.LotsOfReplies +``` + +The response should look like the following: + +``` +Resolved method descriptor: +rpc LotsOfReplies ( .hello.HelloRequest ) returns ( stream .hello.HelloResponse ); + +Request metadata to send: +kong-debug: 1 + +Response headers received: +content-type: application/grpc +date: Tue, 30 Jul 2019 22:21:40 GMT +kong-route-id: 133659bb-7e88-4ac5-b177-bc04b3974c87 +kong-service-id: 31a87674-f984-4f75-8abc-85da478e204f +kong-service-name: grpc +server: openresty/1.15.8.1 +via: kong/1.2.1 +x-kong-proxy-latency: 14 +x-kong-upstream-latency: 0 + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response trailers received: +(empty) +Sent 1 request and received 10 responses +``` + +Notice that the `kong-route-id` response header now carries a different value +and refers to the second Route created in this page. + +**Note:** +[gRPC reflection requests](https://github.com/grpc/grpc/blob/master/doc/server_reflection_tutorial.md) +will still be routed to the first route we created (the "catch-all" route), since +the request matches neither `SayHello` nor `LotsOfReplies` routes. + +## 3. Enabling Plugins + +Kong 1.3 gRPC support is compatible with Logging and Observability plugins; for +example, let's try out the [File Log][file-log] plugin with gRPC. + +Issue the following request to enable File Log on the "SayHello" route: + +```bash +$ curl -X POST localhost:8001/routes/say-hello/plugins \ + --data name=file-log \ + --data config.path=grpc-say-hello.log +``` + +Follow the output of the log as gRPC requests are made to "SayHello": + +``` +$ tail -f grpc-say-hello.log +{"latencies":{"request":8,"kong":5,"proxy":3},"service":{"host":"localhost","created_at":1564527408,"connect_timeout":60000,"id":"74a95d95-fbe4-4ddb-a448-b8faf07ece4c","protocol":"grpc","name":"grpc","read_timeout":60000,"port":15002,"updated_at":1564527408,"write_timeout":60000,"retries":5},"request":{"querystring":{},"size":"46","uri":"\/hello.HelloService\/SayHello","url":"http:\/\/localhost:9080\/hello.HelloService\/SayHello","headers":{"host":"localhost:9080","content-type":"application\/grpc","kong-debug":"1","user-agent":"grpc-go\/1.20.0-dev","te":"trailers"},"method":"POST"},"client_ip":"127.0.0.1","tries":[{"balancer_latency":0,"port":15002,"balancer_start":1564527732522,"ip":"127.0.0.1"}],"response":{"headers":{"kong-route-id":"e49f2df9-3e8e-4bdb-8ce6-2c505eac4ab6","content-type":"application\/grpc","connection":"close","kong-service-name":"grpc","kong-service-id":"74a95d95-fbe4-4ddb-a448-b8faf07ece4c","kong-route-name":"say-hello","via":"kong\/1.2.1","x-kong-proxy-latency":"5","x-kong-upstream-latency":"3"},"status":200,"size":"298"},"route":{"id":"e49f2df9-3e8e-4bdb-8ce6-2c505eac4ab6","updated_at":1564527431,"protocols":["grpc"],"created_at":1564527431,"service":{"id":"74a95d95-fbe4-4ddb-a448-b8faf07ece4c"},"name":"say-hello","preserve_host":false,"regex_priority":0,"strip_path":false,"paths":["\/hello.HelloService\/SayHello"],"https_redirect_status_code":426},"started_at":1564527732516} +{"latencies":{"request":3,"kong":1,"proxy":1},"service":{"host":"localhost","created_at":1564527408,"connect_timeout":60000,"id":"74a95d95-fbe4-4ddb-a448-b8faf07ece4c","protocol":"grpc","name":"grpc","read_timeout":60000,"port":15002,"updated_at":1564527408,"write_timeout":60000,"retries":5},"request":{"querystring":{},"size":"46","uri":"\/hello.HelloService\/SayHello","url":"http:\/\/localhost:9080\/hello.HelloService\/SayHello","headers":{"host":"localhost:9080","content-type":"application\/grpc","kong-debug":"1","user-agent":"grpc-go\/1.20.0-dev","te":"trailers"},"method":"POST"},"client_ip":"127.0.0.1","tries":[{"balancer_latency":0,"port":15002,"balancer_start":1564527733555,"ip":"127.0.0.1"}],"response":{"headers":{"kong-route-id":"e49f2df9-3e8e-4bdb-8ce6-2c505eac4ab6","content-type":"application\/grpc","connection":"close","kong-service-name":"grpc","kong-service-id":"74a95d95-fbe4-4ddb-a448-b8faf07ece4c","kong-route-name":"say-hello","via":"kong\/1.2.1","x-kong-proxy-latency":"1","x-kong-upstream-latency":"1"},"status":200,"size":"298"},"route":{"id":"e49f2df9-3e8e-4bdb-8ce6-2c505eac4ab6","updated_at":1564527431,"protocols":["grpc"],"created_at":1564527431,"service":{"id":"74a95d95-fbe4-4ddb-a448-b8faf07ece4c"},"name":"say-hello","preserve_host":false,"regex_priority":0,"strip_path":false,"paths":["\/hello.HelloService\/SayHello"],"https_redirect_status_code":426},"started_at":1564527733554} +``` + +[enabling-plugins]: /enterprise//{{page.kong_version}}/getting-started/enable-plugin +[conf-service]: /enterprise//{{page.kong_version}}/getting-started/add-service +[configuration-reference]: /enterprise/{{page.kong_version}}/property-reference +[grpcbin]: https://github.com/moul/grpcbin +[grpcurl]: https://github.com/fullstorydev/grpcurl +[protobuf]: https://raw.githubusercontent.com/moul/pb/master/hello/hello.proto +[file-log]: /plugins/file-log +[zipkin]: /plugins/zipkin diff --git a/app/enterprise/1.3-x/getting-started/enable-dev-portal.md b/app/enterprise/1.3-x/getting-started/enable-dev-portal.md new file mode 100644 index 000000000000..d86d60b1af00 --- /dev/null +++ b/app/enterprise/1.3-x/getting-started/enable-dev-portal.md @@ -0,0 +1,39 @@ +--- +title: How To Enable the Dev Portal +toc: false +--- + +### Step 1 - Enable Dev Portal in the Kong Configuration + +To enable the Dev Portal, the following properties must be set in the Kong +configuration file (`kong.conf`): + +``` +portal = on +``` + +Kong Enterprise must be **restarted** for this value to take effect. + +### Step 2 - Enable the default Workspace Dev Portal + + +To enable the default Workspace's Dev Portal via Kong Manager: + +1. Navigate to the default Workspace in Kong Manager +2. Click the **Settings** link under **Dev Portal** +3. Toggle the **Dev Portal Switch** + +It may take a few seconds for the Settings page to populate. + +![Dev Portal Settings](https://konghq.com/wp-content/uploads/2019/05/Screen-Shot-2019-05-17-at-12.27.56-PM.png) + + +To enable the default Workspace's Dev portal via the command line: + +``` +curl -X PATCH http://localhost:8001/workspaces/default --data "config.portal=true" +``` + +- This will expose the **default Dev Portal** at [http://localhost:8003/default](http://localhost:8003/default) +- The **Dev Portal Files endpoint** can be accessed at `:8001/files` +- The **Public Dev Portal Files API** can be accessed at `:8004/files` diff --git a/app/enterprise/1.3-x/getting-started/enable-plugin.md b/app/enterprise/1.3-x/getting-started/enable-plugin.md new file mode 100644 index 000000000000..b927c6a426b9 --- /dev/null +++ b/app/enterprise/1.3-x/getting-started/enable-plugin.md @@ -0,0 +1,77 @@ +--- +title: How to Enable a Plugin +--- + +### Introduction + +This guide walks through enabling a **Plugin** on **Kong Enterprise** via +**Kong Manager**, by showing an example configuration of the +[**Rate Limiting Advanced**](/hub/kong-inc/rate-limiting-advanced) Plugin, the +**Kong Enterprise** version of the popular **Kong Rate Limiting** Plugin. To +learn more about **Rate Limiting Advanced**, or see how to configure this +Plugin via the command line, checkout the +[**Rate Limiting Advanced**](/hub/kong-inc/rate-limiting-advanced) documentation. + + +### 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 + +### How to Enable a Plugin in Kong Manager + +1. Choose the desired **Workspace** in **Kong Manager** and navigate to the +**Plugins** tab under **API Gateway**. + + ![Plugins Tab](https://doc-assets.konghq.com/0.35/getting-started/add-a-plugin/01-plugin-tab.png) + +2. Click the **Add New Plugin** button to open the **Plugins** page, which lists +all the **Kong Enterprise** bundled **Plugins** available. +

Scroll to the **Traffic Control** section and select **Rate Limiting EE**. + + ![Rate Limiting EE](https://doc-assets.konghq.com/0.35/getting-started/add-a-plugin/02-rate-limiting.png) +

This will open the **Plugin Configuration** form for **Rate Limiting EE**. + + ![Configuration Form](https://doc-assets.konghq.com/0.35/getting-started/add-a-plugin/03-plugin-form.png) +
Note that the **Plugin** will automatically be enabled when the form is +submitted. Toggle the **This plugin is Enabled** button at the top of the form +to configure the **Plugin** without enabling it. + + ![Toggle Enable](https://doc-assets.konghq.com/0.35/getting-started/add-a-plugin/04-toggle-enable.png) + +3. Define the **Plugin** as *global* or *scoped*. +

*Global* will apply the **Plugin** to *every* **Service** and +**Route** in the **Workspace**. +
*Scoped* will apply the **Plugin** to one **Service**, **Route**, and/or +**Consumer**. +

To use this option, select the **Scoped** radio button and select the +desired **Service**, **Route**, or **Consumer** from the dropdown. + + ![Connect test-service](https://doc-assets.konghq.com/0.35/getting-started/add-a-plugin/05-global-scoped.png) + + +4. Fill out the **configuration** form.

For **Rate Limiting EE** the +following fields are *required*:
-`config.limit`
-`config.sync_rate`
+-`config.window_size`
More information on these fields can be found in the +[**Rate Limiting Advanced** documentation](/hub/kong-inc/rate-limiting-advanced/#parameters) +

For this example set the required fields to the following: + ``` + config.limit = 10 + config.sync_rate = 10 + config.window_size = 60 + ``` + +5. Click the **Create** button at the bottom of the form to save and +enable the **Plugin**. If it is successful, the page will automatically +redirect to the **Plugin Overview**, with the **Rate Limiting** Plugin +listed. + + ![Plugin Overview](https://doc-assets.konghq.com/0.35/getting-started/add-a-plugin/06-plugin-overview.png) +

If the **Plugin** is *scoped* to a **Service**, **Route**, or +**Consumer**, the **Plugin** will also be listed on that object's **Overview** +page. + + ![Service Overview](https://doc-assets.konghq.com/0.35/getting-started/add-a-plugin/07-service-plugin-table.png) diff --git a/app/enterprise/1.3-x/getting-started/index.md b/app/enterprise/1.3-x/getting-started/index.md new file mode 100644 index 000000000000..4e7c76ec73d2 --- /dev/null +++ b/app/enterprise/1.3-x/getting-started/index.md @@ -0,0 +1,125 @@ +--- +title: Getting Started with Kong Enterprise +toc: false +--- + +### Introduction + +Thank you for installing Kong Enterprise! The following series of Getting Started +guides is designed to help you familiarize yourself with Kong Enterprise's features +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/). + + If you have any issues or further questions, please +[contact Support](https://support.konghq.com/support/s/) and they will be happy + to help. + +### Key Concepts + +The following concepts have a special meaning in Kong Enterprise: + +* **Plugin**: a plugin executing actions inside Kong before or after a request + has been proxied to the upstream API. + +* **Workspace**: a private, segmented part of a shared Kong cluster that allows +a particular team to access its own Admin API entities separately from other teams. + +* **Admin**: a Kong Enterprise user capable of accessing Admin API entities based + on a set of **Permissions**. + +* **Permission**: an ability to create, read, update, or destroy an Admin API + entity defined by endpoints. + +* **Role**: a set of **Permissions** that may be reused and assigned to **Admins**. + +* **Super Admin**: an **Admin** whose **Role** has the **Permission** to: + * invite and disable other **Admin** accounts + * assign and revoke **Roles** + * create new **Roles** with custom **Permissions** + * create new **Workspaces** + +* **Service**: the Admin API entity representing an external _upstream_ API or + microservice. + +* **Route**: the Admin API entity representing a way to map downstream requests + to upstream services. + +* **Consumer**: the Admin API entity representing a developer or machine using + the API. When using Kong, a Consumer only communicates with Kong which proxies + every call to the said upstream API. + +## Get Started + +
+
+

+ + Start Kong Enterprise +

+

Learn to start Kong Enterprise securely with RBAC

+ + Start Kong Enterprise → + +
+ +
+

+ + Add a Workspace +

+

Create groups within your organization with Workspaces.

+ + Add a Workspace → + +
+ +
+

+ + Add a Role and Permissions +

+

Create sets to quickly assign multiple Admins the same permissions.

+ Add a Role and Permissions → +
+ +
+

+ + Add an Admin +

+

Authorize Admins with default and custom Roles and Permissions.

+ Add an Admin → +
+ +
+

+ + Add a Service and Route +

+

Start forwarding requests through Kong Enterprise

+ Add a Service and Route → +
+ +
+

+ + Enable a Plugin +

+

Expand Kong Enterprise with plugins

+ Enable a Plugin → +
+ +
+

+ + Enable the Dev Portal +

+

Publish API docs, onboard and manage developers

+ Enable the Dev Portal → +
+ +
diff --git a/app/enterprise/1.3-x/getting-started/start-kong.md b/app/enterprise/1.3-x/getting-started/start-kong.md new file mode 100644 index 000000000000..0fe368704b15 --- /dev/null +++ b/app/enterprise/1.3-x/getting-started/start-kong.md @@ -0,0 +1,130 @@ +--- +title: How to Start Kong Enterprise Securely +toc: false +--- +#### Table of Contents + +- [Introduction](#introduction) +- [Prerequisites](#prerequisites) +- [Step 1](#step-1) +- [Step 2](#step-2) +- [Step 3](#step-3) +- [Step 4](#step-4) +- [Default Ports](#default-ports) +- [Next Steps](#next-steps) + +### Introduction + +To secure the Admin API or Kong Manager, a **Super Admin** account is +required. + +The **Super Admin** has the ability to invite other **Admins** and +restrict their access based on **Permissions** of **Roles** within +**Workspaces**. + +The first **Super Admin** account is created during database migrations +following the guide below. It may only be added once. + +### Prerequisites + +After [installing Kong Enterprise](/enterprise/{{page.kong_version}}/deployment/installation/overview/), +either modify the configuration file or set environment variables for +the following properties: + +* `enforce_rbac` will force all Admin API requests to require a +`Kong-Admin-Token`. The **Admin** associated with the `Kong-Admin-Token` +must have adequate **Permissions** in order for the request to succeed. + +* If using Kong Manager, select the type of authentication that **Admins** +should use to log in. For the purpose of this guide, `admin_gui_auth` +may be set to `basic-auth`. See +[Securing Kong Manager](/enterprise/{{page.kong_version}}/kong-manager/security) for other types +of authentication. + +For a simple configuration to use for the subsequent Getting +Started guides: + +``` +enforce_rbac = on +admin_gui_auth = basic-auth +admin_gui_session_conf = { "secret":"set-your-string-here" } +``` + +⚠️**Important:** the **Sessions Plugin** requries a secret and is configured securely by default. +* Under all circumstances, the `secret` must be manually set to a string. +* If using HTTP instead of HTTPS, `cookie_secure` must be manually set to `false`. +* If using different domains for the Admin API and Kong Manager, `cookie_samesite` must be set to `off`. +Learn more about these properties in [Session Security in Kong Manager](/enterprise/{{page.kong_version}}/kong-manager/authentication/sessions/#session-security), and see [example configurations](/enterprise/{{page.kong_version}}/kong-manager/authentication/sessions/#example-configurations). + +## Step 1 + +Set a password for the **Super Admin**. This environment variable must +be present in the environment where database migrations will run. + +``` +$ export KONG_PASSWORD= +``` + +This automatically creates a user, `kong_admin`, and a password that +can be used to log in to Kong Manager. This password may also be +used as a `Kong-Admin-Token` to make Admin API requests. + +**Note:** only one **Super Admin** may be created using this method, and only +on a fresh installation with an empty database. If one is not created during migrations, +follow [this guide](/enterprise/{{page.kong_version}}/kong-manager/authentication/super-admin/#how-to-create-your-first-super-admin-account-post-installation) to remediate. + +Future migrations will not update the password or create additional **Super Admins**. +To add additional **Super Admins** it is necessary to +[invite a new user as a **Super Admin** in Kong Manager](/enterprise/{{page.kong_version}}/kong-manager/administration/admins/invite/#how-to-invite-a-new-admin-from-the-organization-page). + +## Step 2 + +Issue the following command to prepare your datastore by running the Kong migrations: + +``` +$ kong migrations bootstrap [-c /path/to/kong.conf] +``` + +## Step 3 + +Start Kong: + +``` +$ 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). + +## Step 4 + +To test that Kong Enterprise has successfully started with a **Super Admin**, +visit Kong Manager's URL. By [default](#default-ports), it is on port `:8002`. + +The username is `kong_admin` and the password is the one set in +[Step 1](#step-1). + +### Default Ports + +By default, Kong Enterprise listens on the following ports: + +- [`:8000`](/enterprise/{{page.kong_version}}/property-reference/#proxy_listen): incoming HTTP traffic from **Consumers**, and forwarded to upstream + **Services**. +- [`:8443`](/enterprise/{{page.kong_version}}/property-reference/#proxy_listen): incoming HTTPS traffic. This port behaves similarly to the `:8000` + port, except that it expects HTTPS traffic only. +- [`:8003`](/enterprise/{{page.kong_version}}/property-reference/#portal_gui_listen): Dev Portal listens for HTTP traffic, assuming Dev Portal is **enabled**. +- [`:8446`](/enterprise/{{page.kong_version}}/property-reference/#portal_gui_listen): Dev Portal listens for HTTPS traffic, assuming Dev Portal is **enabled**. +- [`:8004`](/enterprise/{{page.kong_version}}/property-reference/#portal_api_listen): Dev Portal **`/files`** traffic over HTTP, assuming the Dev Portal is **enabled**. +- [`:8447`](/enterprise/{{page.kong_version}}/property-reference/#portal_api_listen): Dev Portal **`/files`** traffic over HTTPS, assuming the Dev Portal is **enabled**. +- [`:8001`](/enterprise/{{page.kong_version}}/property-reference/#admin_api_uri): Admin API listens for HTTP traffic. +- [`:8444`](/enterprise/{{page.kong_version}}/property-reference/#admin_api_uri): Admin API listens for HTTPS traffic. +- [`:8002`](/enterprise/{{page.kong_version}}/property-reference/#admin_gui_listen): Kong Manager listens for HTTP traffic. +- [`:8445`](/enterprise/{{page.kong_version}}/property-reference/#admin_gui_listen): Kong Manager listens for HTTPS traffic. + +### Next Steps + +With Kong Enterprise started and the **Super Admin** logged in, it is now +possible to create any entity in Kong. + +Next, see how to segment the Kong cluster into +[**Workspaces**](/enterprise/{{page.kong_version}}/getting-started/add-workspace). diff --git a/app/enterprise/1.3-x/health-checks-circuit-breakers.md b/app/enterprise/1.3-x/health-checks-circuit-breakers.md new file mode 100644 index 000000000000..42d16e52217b --- /dev/null +++ b/app/enterprise/1.3-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/1.3-x/index.md b/app/enterprise/1.3-x/index.md new file mode 100644 index 000000000000..a69f523d1dbc --- /dev/null +++ b/app/enterprise/1.3-x/index.md @@ -0,0 +1,61 @@ +--- +title: Kong Enterprise Documentation +--- + +
+ +
+

Install Kong Enterprise

+

Learn how to install Kong Enterprise with your chosen deployment method.

+ Choose Deployment Method → +
+ +
+

Changelog

+

Review the details of the changes made to each version of Kong Enterprise.

+ See changelog → +
+ +
+

Migration Guide

+

Migrate to the latest version of Kong Enterprise.

+ See Guide → +
+ +
+

Getting Started

+

Learn key concepts and get started with Kong Enterprise's features.

+ Get Started → +
+ +
+

Admin API

+

Harness Kong Enterprise's features with the Admin API.

+ Learn more → +
+ +
+

Kong Manager

+

Utilize Kong Manager to configure and manage Kong Enterprise.

+ Learn more → +
+ +
+

Kong Dev Portal

+

Explore how to enable, configure, and customize the Kong Dev Portal.

+ Learn more → +
+ +
+

Kong Brain & Kong Immunity

+

Install and Configure Kong Brain and Kong Immunity.

+ Learn more → +
+ +
+

APIs and Plugins

+

Expand Kong Enterprise's capabilities with additional APIs and Plugins.

+ Learn More → +
+ +
diff --git a/app/enterprise/1.3-x/kong-manager/administration/admins/admins.md b/app/enterprise/1.3-x/kong-manager/administration/admins/admins.md new file mode 100644 index 000000000000..52b922f7279b --- /dev/null +++ b/app/enterprise/1.3-x/kong-manager/administration/admins/admins.md @@ -0,0 +1,13 @@ +--- +title: Admins in Kong Manager +book: admin_gui +--- + +## Using the Organization Page to Manage Users + +To view all of the current **Workspaces** and **Roles**, click +the **Organization** link on the top navigation bar. + +From this page, it is possible to update each **Admin's** **Role** across +any **Workspace**. From the **Roles**"** tab, it is also possible to +update the **Permissions** assigned to each **Role**. \ No newline at end of file diff --git a/app/enterprise/1.3-x/kong-manager/administration/admins/invite.md b/app/enterprise/1.3-x/kong-manager/administration/admins/invite.md new file mode 100644 index 000000000000..de5ff527cb52 --- /dev/null +++ b/app/enterprise/1.3-x/kong-manager/administration/admins/invite.md @@ -0,0 +1,134 @@ +--- +title: How to Invite an Admin +book: admin_gui +--- + +## Using the Organization Page to Manage Users + +To view all of the current **Workspaces** and **Roles**, click +the **Organization** link on the top navigation bar. + +From this page, it is possible to update each **Admin's** **Role** across +any **Workspace**. From the **Roles** tab, it is also possible to +update the **Permissions** assigned to each **Role**. + +## How to Invite a New Admin from the Organization Page + +Inviting a new **Admin** through the **Organization** page is similar to inviting an +[**Admin** within a **Workspace**](#how-to-invite-a-new-admin-in-a-workspace). However, +from the **Organization** page, **Roles** can be assigned to a new **Admin** for multiple +**Workspaces** at once. The **Super Admin** can also view global roles across **Workspaces** +from this page. + +1. On the **Organization** page, to invite a new **Admin**, click the **Invite User** +button. + +2. Fill out the username and email address. When a new **Admin** receives an +invitation, they will only be able to log in with that email address. Assign +the appropriate **Role** and click **Invite User** to send the invitation. + + ⚠️ **IMPORTANT**: **Super Admins** can invite users to multiple **Workspaces**, and + assign them any **Role** available within **Workspaces**, including **Roles** that exist + by default (e.g. `super-admin`, `read-only`) and **Roles** with customized + permissions. + + ⚠️ **IMPORTANT**: The **Super Admin** can see all available roles across + **Workspaces** on the **Roles** tab of the **Organization** page. + + ![Role List](https://konghq.com/wp-content/uploads/2018/12/org2.png) + +3. On the **Organization** page, the new invitee will appear on the list with the +**Invited** status. Once they accept the invitation, the user will be listed in +the main **Users** list. + + ![User List](https://konghq.com/wp-content/uploads/2018/12/org3-1.png) + +4. The newly invited **Admin** will have the ability to set a password. If the +**Admin** ever forgets the password, it is possible for them to reset it through a +recovery email. + + + +## How to Invite a New Admin in a Workspace + +![Create an Admin in Kong Manager](https://konghq.com/wp-content/uploads/2018/07/admins2.png) + +1. On the "Admins" page, to invite a new admin, click the "Create New Admin" +button. + +2. When a new Admin receives an invitation, they will only be able to log in + with that email address. Assign the appropriate Role and click "Invite Admin" + to send the invitation. + + ![Create New Admin](https://konghq.com/wp-content/uploads/2018/11/km-name-admin.png) + +3. On the "Admins" page, the new invitee will appear on the list with the + "invited" status. Once they accept the invitation, their status will + change to "accepted". + + ![Invited Admins](https://konghq.com/wp-content/uploads/2018/11/km-invited-admins.png) + +4. The newly invited Admin will have the ability to set a password. If the + **Admin** forgets the password, it is possible to reset it through a recovery + email. + +⚠️ **IMPORTANT**: By default, the registration link will expire after 259,200 + seconds (3 days). This timeframe can be configured with the `kong.conf` + file in `admin_invitation_expiry`. + +⚠️ **IMPORTANT**: If an email fails to send, either due to an incorrect email + address or an external error, it will be possible to resend an invitation. + +⚠️ **IMPORTANT**: If SMTP is not enabled or the invitation email fails to send, + it is possible for the Super Admin to copy and provide a registration link + directly. See the next section. + +## How to Copy and Send a Registration Link + +If a mail server is not yet set up, it is still possible to invite Admins to +register and log in. + +1. Invite an Admin as described in the section above. + +2. If the "View" link is clicked next to the invited Admin's name, a + `register_url` is displayed on the invitee's details page. + + ![Registration URL](https://konghq.com/wp-content/uploads/2018/11/km-registration-url.png) + +3. Copy and directly send this link to the invited Admin so that they may set + up their credentials and log in. + +⚠️ **IMPORTANT**: If `admin_gui_auth` is `ldap-auth-advanced`, credentials are +not stored in Kong, and the Admin will be directed to Login. + +## How to Grant an Admin Access with LDAP + +1. Pick a user in the LDAP Directory that will be the Super Admin. + +2. Change the Super Admin’s username in Kong by making a `PATCH` request to +`admins/kong_admin` and setting the value of `username` to the corresponding +LDAP `attribute`. + +For example, if the LDAP user's attribute is `einstein`, +the `PATCH` to `/admins/kong_admin` should have a `username` set to `einstein`. + +3. Log in to Kong Manager using the LDAP credentials associated with the Super +Admin. + +4. Invite Admins from the "Admins" page in Kong Manager, ensuring that the +`username` of each Admin is mapped to the `attribute` value set in the LDAP +directory. + + ⚠️ **IMPORTANT**: To enable the Admins to log in, it is still necessary + to assign a Role to them. + +5. Once an Admin has logged in successfully and accesses the Admin API using +their LDAP credentials, they will be marked as “approved” on the "Admins" list +in Kong Manager + + ⚠️ **IMPORTANT**: The new Admins will still receive an email, but all + credentials will be handled through the LDAP server, not Kong Manager + or the Admin API. diff --git a/app/enterprise/1.3-x/kong-manager/administration/rbac/add-user.md b/app/enterprise/1.3-x/kong-manager/administration/rbac/add-user.md new file mode 100644 index 000000000000..3255fefc6f48 --- /dev/null +++ b/app/enterprise/1.3-x/kong-manager/administration/rbac/add-user.md @@ -0,0 +1,63 @@ +--- +title: How to Create an RBAC User +book: admin_gui +toc: true +--- + +#### Admins vs. RBAC Users + +| | Admin API | Kong Manager | +|------------|-----------|--------------| +| Admins | ✔️ | ✔️ | +| RBAC Users | ✔️ | X | + + +An RBAC User has the ability to access the Kong Enterprise Admin API. The Permissions assigned to their Role will define the types of actions they can perform with various Admin API objects. + +An [Admin](/enterprise/{{page.kong_version}}/kong-manager/security/#what-can-admins-do-in-kong-manager), like an RBAC User, has the ability to access the Kong Enterprise Admin API. The Admin also has the ability log in to Kong Manager. Like an RBAC User, an Admin’s Role will determine the types of actions it can perform—except that they will also have the ability to benefit from Kong Manager’s interface and visualizations. + +If creating a *service account* for Kong Enterprise, e.g., for a machine as part of an automated process, then an RBAC User is adequate. + +If creating a *personal account* for Kong Enterprise, then Admin may be preferable since it also has access to Kong Manager. + +#### Prerequisites + +* Authentication and RBAC are enabled, following the +[Getting Started](/enterprise/{{page.kong_version}}/getting-started/start-kong/#prerequisites) +guide +* [Logged in as the Super Admin](/enterprise/{{page.kong_version}}/getting-started/start-kong/#step-4) +or a user that has `/admins` and `/rbac` read and write access. + +## How to Add an RBAC User in Kong Manager + +1. From the dashboard, click the **Teams** tab in the top navigation menu. + +2. On the **Teams** page, click the **RBAC Users** tab. + +3. Using the dropdown menu, select which **Workspace** the new user has access to. + + >Note: The **Default Workspace** is global, meaning the RBAC User with access to default has access to entities across all other Workspaces. This Workspace assignment is useful for administrative and auditing accounts, but not for members of specific teams. + +4. Click the **Add New User** button to the right of the dropdown menu to open the registration form. + +5. In the **Add New User** registration form provide a Name, User Token, Comment, and Enablement + + The name of the RBAC User must be globally unique, even if two users are in different Workspaces, and it cannot have the same as an Admin account. + + These naming conventions are important if using OIDC, LDAP, or another external method of identity and access management. + + The RBAC User account is enabled by default, if you want the RBAC User account to start in a disabled state and enable it later, uncheck the box. + +6. Click the **Add User Roles** button in the **Role(s) per workspace** section. Select the Role (or Roles) desired for the new RBAC User. + + If the RBAC User has no Roles assigned, it will not have permission to access any objects. + + An RBAC User’s Role assignments may be altered later if needed. + + The Roles can only belong to one Workspace, as selected in Step 3. + + To provide an RBAC User with access to objects in multiple Workspaces, see Step 3. + +7. Click **Create User** to complete the user registration. + + The page will automatically redirect back to the **Teams** page, where the new user is listed. diff --git a/app/enterprise/1.3-x/kong-manager/administration/rbac/new-role.md b/app/enterprise/1.3-x/kong-manager/administration/rbac/new-role.md new file mode 100644 index 000000000000..f013f42d0d0e --- /dev/null +++ b/app/enterprise/1.3-x/kong-manager/administration/rbac/new-role.md @@ -0,0 +1,51 @@ +--- +title: How to Create a New Role with Custom Permissions +book: admin_gui +toc: false +--- +#### Prerequisites + +* Authentication and RBAC are enabled, following the +[Getting Started](/enterprise/{{page.kong_version}}/getting-started/start-kong/#prerequisites) +guide +* [Logged in as the Super Admin](/enterprise/{{page.kong_version}}/getting-started/start-kong/#step-4) +or a user that has `/admins` and `/rbac` read and write access. + +## Create a New Role with Custom Permissions + +1. On the **Admins** page, to create a new **Role**, click the **Add Role** button at +the top right of the list of Roles. + +2. On the **Add Role** form, name the **Role** according to the **Permissions** you want +to grant. Write a brief comment describing the **Permissions** of the **Role**. + + ![New Role naming](https://konghq.com/wp-content/uploads/2018/11/km-new-role.png) + +3. Click the **Add Permissions** button and fill out the form. Add the endpoint +**Permissions** by marking the appropriate checkbox. + + ![New Role permissions](https://konghq.com/wp-content/uploads/2018/11/km-perms.png) + +4. Click **Add Permission to Role** to see the **Permissions** listed on the form. + + ![New Role permissions list](https://konghq.com/wp-content/uploads/2018/11/km-perms-list.png) + +5. To forbid access to certain endpoints, click **Add Permission** again and use +the **negative** checkbox. + + ![Negative permissions](https://konghq.com/wp-content/uploads/2018/11/km-negative-perms.png) + +6. See the new **Role** appear on the **Admins** page + + ![Roles list](https://konghq.com/wp-content/uploads/2018/11/km-roles-list.png) + +⚠️ **IMPORTANT**: Every **Admin** who needs access to Kong Manager will need at +least `read` access to the home "`/`" endpoint. + +⚠️ **IMPORTANT**: A negative **Permission** will always take precedence over a +positive one. + + diff --git a/app/enterprise/1.3-x/kong-manager/administration/rbac/rbac.md b/app/enterprise/1.3-x/kong-manager/administration/rbac/rbac.md new file mode 100644 index 000000000000..cb6f508d4bd3 --- /dev/null +++ b/app/enterprise/1.3-x/kong-manager/administration/rbac/rbac.md @@ -0,0 +1,55 @@ +--- +title: RBAC in Kong Manager +book: admin_gui +--- + +### Introduction to RBAC in Kong Manager + +In addition to authenticating **Admins** and segmenting **Workspaces**, +Kong Enterprise has the ability to enforce Role-Based Access Control +(RBAC) for all resources with the use of **Roles** assigned to **Admins**. + +As the **Super Admin** (or any **Role** with **read** and **write** +access to the `/admins` and `/rbac` endpoints), it is possible to +create new **Roles** and customize **Permissions**. + +In Kong Manager, RBAC affects how **Admins** are able to navigate +through the application. + +### Default Roles + +Kong includes Role-Based Access Control (RBAC). Every **Admin** using Kong Manager +will need an assigned **Role** based on the resources they have **Permission** to access. + +When a **Super Admin** starts Kong for the first time, the `default` **Workspace** will +include three default **Roles**: `read-only`, `admin`, and `super-admin`. The three +**Roles** have **Permissions** related to every **Workspace** in the cluster. + +Similarly, if a **Role** is confined to certain **Workspaces**, the **Admin** assigned to it +will not be able to see either the overview or links to other **Workspaces**. + +⚠️ **IMPORTANT**: Although a default **Admin** has full permissions with every +endpoint in Kong, only a **Super Admin** has the ability to assign and modify RBAC +**Permissions**. An **Admin** is not able to modify their own **Permissions** or delimit a +**Super Admin's** **Permissions**. + +⚠️ **IMPORTANT**: If a **Role** does not have **Permission** to access entire endpoints, +the **Admin** assigned to the **Role** will not be able to see the related navigation links. + +### RBAC in Workspaces + +RBAC **Roles** and **Permissions** will be specific to a **Workspace** if they are assigned +from within one. For example, if there are two **Workspaces**, **Payments** and +**Deliveries**, an **Admin** created in **Payments** will not have access to any +endpoints in **Deliveries**. + +When a **Super Admin** creates a new **Workspace**, there are three default **Roles** that +mirror the cluster-level **Roles**, and a fourth unique to each **Workspace**: +`workspace-read-only`, `workspace-admin`, `workspace-super-admin`, and +`workspace-portal-admin`. + +![Default Roles in New Workspaces](https://konghq.com/wp-content/uploads/2018/11/km-workspace-roles.png) + +⚠️ **IMPORTANT**: Any Role assigned in the **Default Workspace** will have +**Permissions** applied to all subsequently created **Workspaces**. A **Super Admin** in +in `default` has RBAC **Permissions** across all **Workspaces**. diff --git a/app/enterprise/1.3-x/kong-manager/administration/workspaces/create-workspace.md b/app/enterprise/1.3-x/kong-manager/administration/workspaces/create-workspace.md new file mode 100644 index 000000000000..12a5bc0998bd --- /dev/null +++ b/app/enterprise/1.3-x/kong-manager/administration/workspaces/create-workspace.md @@ -0,0 +1,63 @@ +--- +title: How to Create a New Workspace in Kong Manager +book: admin_gui +toc: false +--- + +1. Log in as the **Super Admin**. On the **Workspaces** page, click the **New Workspace** +button at the top right to see the **Create Workspace** form. + + ![New Workspace Form](https://konghq.com/wp-content/uploads/2018/11/km-new-workspace.png) + +2. Name the new Workspace. + + ![Name the New Workspace](https://konghq.com/wp-content/uploads/2018/11/km-name-ws.png) + + ⚠️ **WARNING**: Each Workspace name should be unique, regardless of letter + case. For example, naming one Workspace "Payments" and another one + "payments" will create two different workspaces that look identical. + + ⚠️ **WARNING**: Do not name Workspaces the same as these major routes in Kong + Manager: + + ``` + • Admins + • APIs + • Certificates + • Consumers + • Plugins + • Portal + • Routes + • Services + • SNIs + • Upstreams + • Vitals + ``` + +3. Select a color or avatar to make each **Workspace** easier to distinguish, or +accept the default color. + + ![Select Workspace Color](https://konghq.com/wp-content/uploads/2018/11/km-color-ws.png) + +4. Click the "Create New Workspace" button. Upon creation, the application will +navigate to the new Workspace's "Dashboard" page. + + ![New Dashboard](https://konghq.com/wp-content/uploads/2018/11/km-new-dashboard.png) + +5. On the left sidebar, click the "Admins" link in the "Security" section. If +the sidebar is collapsed, hover over the security badge icon at the bottom and +click the "Admins" link. + + ![Admins Hover Over](https://konghq.com/wp-content/uploads/2018/11/admins-section.png) + +6. The "Admins" page displays a list of current Admins and Roles. Four default +Roles specific to the new Workspace are already visible, and new Roles specific +to the Workspace can be assigned from this page. + + ![New Workspace Admins](https://konghq.com/wp-content/uploads/2018/11/km-ws-admins.png) + + + diff --git a/app/enterprise/1.3-x/kong-manager/administration/workspaces/update-workspace.md b/app/enterprise/1.3-x/kong-manager/administration/workspaces/update-workspace.md new file mode 100644 index 000000000000..8796758b590a --- /dev/null +++ b/app/enterprise/1.3-x/kong-manager/administration/workspaces/update-workspace.md @@ -0,0 +1,22 @@ +--- +title: How to Update or Delete a Workspace +book: admin_gui +toc: false +--- + +⚠️ **IMPORTANT**: In order to delete a Workspace, everything inside the +Workspace must be deleted first. This includes default Roles on the "Admins" +page. + +1. Within the Workspace, navigate to the "Dashboard" page. + + ![Workspace Dashboard](https://konghq.com/wp-content/uploads/2018/11/km-dashboard.png) + +2. At the top right, click the "Settings" button. + +3. Edit or delete the Workspace. + + \ No newline at end of file diff --git a/app/enterprise/1.3-x/kong-manager/administration/workspaces/workspaces.md b/app/enterprise/1.3-x/kong-manager/administration/workspaces/workspaces.md new file mode 100644 index 000000000000..0a39c028ba3a --- /dev/null +++ b/app/enterprise/1.3-x/kong-manager/administration/workspaces/workspaces.md @@ -0,0 +1,42 @@ +--- +title: Workspaces in Kong Manager +book: admin_gui +--- + +**Workspaces** enable an organization to segment traffic so that +teams of **Admins** sharing the same Kong cluster are only able to +interact with entities from their groups. Within a **Workspace**, +it is possible to invite **Admins** to a particular team and to +enforce **RBAC** with **Roles** and **Permissions** that further +delimit the types of actions and entities available to an **Admin**. + +## Default Workspace + +When the first **Super Admin** logs in, they begin in the **Workspace** +named **default**. From here, they may invite **Admins** who are +intended to be able to manage all other **Workspaces**, as well as +the **Workspaces** themselves. + +## Creating Additional Workspaces + +To create a new **Workspace**, follow the guide, How to Create a New +Workspace in Kong Manager. + +## Navigating across Workspaces in Kong Manager + +To navigate between Workspaces from the **Overview** page, click on any +Workspace displayed beneath the **Vitals** chart. + +The list of **Workspaces** may be rendered as cards or a table, +depending on preference. + +![Workspace List](https://konghq.com/wp-content/uploads/2018/11/km-ws-list.png) + +## Workspace Access + +If a **Role** does not have permission to access entire endpoints within +a **Workspace**, the **Admin** assigned to that **Role** will not be +able to see the related navigation links. + +For more information about **Admins** and **Roles**, see +[RBAC in Kong Manager](/enterprise/{{page.kong_version}}/kong-manager/administration/rbac/rbac). diff --git a/app/enterprise/1.3-x/kong-manager/authentication/basic.md b/app/enterprise/1.3-x/kong-manager/authentication/basic.md new file mode 100644 index 000000000000..52a0fcb16772 --- /dev/null +++ b/app/enterprise/1.3-x/kong-manager/authentication/basic.md @@ -0,0 +1,46 @@ +--- +title: How to Enable Basic Auth for Kong Manager +book: admin_gui +toc: false +--- + +#### Table of Contents: +- [Prerequisites](#prerequisites) +- [Step 1](#step-1) +- [Step 2](#step-2) + +### Prerequisites + +To enable Basic Authentication, configure Kong with the following properties: + +``` +enforce_rbac = on +admin_gui_auth = basic-auth +admin_gui_session_conf = { "secret":"set-your-string-here" } +``` + +⚠️**Important:** the **Sessions Plugin** requries a secret and is configured securely by default. +* Under all circumstances, the `secret` must be manually set to a string. +* If using HTTP instead of HTTPS, `cookie_secure` must be manually set to `false`. +* If using different domains for the Admin API and Kong Manager, `cookie_samesite` must be set to `off`. +Learn more about these properties in [Session Security in Kong Manager](/enterprise/{{page.kong_version}}/kong-manager/authentication/sessions/#session-security), and see [example configurations](/enterprise/{{page.kong_version}}/kong-manager/authentication/sessions/#example-configurations). + +## Step 1 + +Start Kong: + +``` +$ kong start [-c /path/to/kong/conf] +``` + +## Step 2 + +If you created a **Super Admin** via database migration, log in to Kong +Manager with the username `kong_admin` and the password +set in the environment variable. + +If you created a Super Admin via the Kong Manager "Organization" tab +as described in +[How to Create a Super Admin](/enterprise/{{page.kong_version}}/kong-manager/authentication/super-admin), +log in with the credentials you created after accepting the email +invitation. diff --git a/app/enterprise/1.3-x/kong-manager/authentication/ldap.md b/app/enterprise/1.3-x/kong-manager/authentication/ldap.md new file mode 100644 index 000000000000..7db8f3ad7e1d --- /dev/null +++ b/app/enterprise/1.3-x/kong-manager/authentication/ldap.md @@ -0,0 +1,62 @@ +--- +title: How to Enable LDAP for Kong Manager +book: admin_gui +toc: false +--- + +Kong Enterprise offers the ability to bind authentication for Kong Manager +*Admins* to a company's Active Directory using the +[LDAP Authentication Advanced plugin](/enterprise/{{page.kong_version}}/plugins/ldap-authentication-advanced). + +⚠️ **IMPORTANT**: by using the configuration below, it is unnecessary to +manually apply the **Plugin**; the configuration alone will enable LDAP +Authentication for Kong Manager. + +Ensure Kong is configured with the following properties either in the +configuration file or using environment variables: + +``` +admin_gui_auth = ldap-auth-advanced +enforce_rbac = on +admin_gui_session_conf = { "secret":"set-your-string-here" } +admin_gui_auth_conf = { + "anonymous":"", \ + "attribute":"", \ + "bind_dn":"", \ + "base_dn":"", \ + "cache_ttl": 2, \ + "header_type":"Basic", \ + "keepalive":60000, \ + "ldap_host":"", \ + "ldap_password":"", \ + "ldap_port":389, \ + "start_tls":false, \ + "timeout":10000, \ + "verify_ldap_host":true \ + "consumer_by":["username", "custom_id"], \ +} +``` + +* `"attribute":""`: The attribute used to identify LDAP users + * For example, to map LDAP users to admins by their username, `"attribute":"uid"` +* `"bind_dn":""`: LDAP Bind DN (Distinguished Name) + * Used to perform LDAP search of user. This bind_dn should have permissions to search + for the user being authenticated. + * For example, `uid=einstein,ou=scientists,dc=ldap,dc=com` +* `"base_dn":""`: LDAP Base DN (Distinguished Name) + * For example, `ou=scientists,dc=ldap,dc=com` +* `"ldap_host":""`: LDAP host domain + * For example, `"ec2-XX-XXX-XX-XXX.compute-1.amazonaws.com"` +* `"ldap_password":""`: LDAP password + * *Note*: As with any configuration property, sensitive information may be set as an + environment variable instead of being written directly in the configuration file. + +⚠️**Important:** the **Sessions Plugin** requries a secret and is configured securely by default. +* Under all circumstances, the `secret` must be manually set to a string. +* If using HTTP instead of HTTPS, `cookie_secure` must be manually set to `false`. +* If using different domains for the Admin API and Kong Manager, `cookie_samesite` must be set to `off`. +Learn more about these properties in [Session Security in Kong Manager](/enterprise/{{page.kong_version}}/kong-manager/authentication/sessions/#session-security), and see [example configurations](/enterprise/{{page.kong_version}}/kong-manager/authentication/sessions/#example-configurations). + +After starting Kong with the desired configuration, you can create new *Admins* +whose usernames match those in the AD. Those users will then be able to accept +invitations to join Kong Manager and log in with their LDAP credentials. diff --git a/app/enterprise/1.3-x/kong-manager/authentication/oidc.md b/app/enterprise/1.3-x/kong-manager/authentication/oidc.md new file mode 100644 index 000000000000..23f5a33144db --- /dev/null +++ b/app/enterprise/1.3-x/kong-manager/authentication/oidc.md @@ -0,0 +1,95 @@ +--- +title: How to Enable OIDC for Kong Manager +book: admin_gui +toc: false +--- +#### Table of Contents + +- [Introduction](#introduction) +- [Prerequisites](#prerequisites) +- [Step 1](#step-1) +- [Step 2](#step-2) + +### Introduction + +Kong Enterprise offers the ability to bind authentication for Kong +Manager **Admins** to an organization's OpenID Connect Identity +Provider using the +**[OpenID Connect Plugin](/hub/kong-inc/openid-connect/)**. + +**Note**: by using the configuration below, it is unnecessary to +manually enable the **Plugin**; the configuration alone will enable +**OIDC** for Kong Manager. + +### Prerequisites + +The following is an example using Google as the IdP and serving Kong Manager +from its default URL, `http://127.0.0.1:8002`. + +(The `admin_gui_auth_config` value must be valid JSON.) + +``` +enforce_rbac = on +admin_gui_auth=openid-connect +admin_gui_session_conf = { "secret":"set-your-string-here" } +admin_gui_auth_conf={ \ + "issuer": "https://accounts.google.com/", \ + "client_id": [""], \ + "client_secret": [""], \ + "consumer_by": ["username","custom_id"], \ + "ssl_verify": false, \ + "consumer_claim": ["email"], \ + "leeway": 60, \ + "redirect_uri": ["http://localhost:8002"], \ + "login_redirect_uri": ["http://localhost:8002"], \ + "logout_methods": ["GET", "DELETE"], \ + "logout_query_arg": "logout", \ + "logout_redirect_uri": ["http://localhost:8002"], \ + "scopes": ["openid","profile","email","offline_access"], \ + "auth_methods": ["authorization_code"] \ +} +``` + +⚠️**Important:** the **Sessions Plugin** requries a secret and is configured securely by default. +* Under all circumstances, the `secret` must be manually set to a string. +* If using HTTP instead of HTTPS, `cookie_secure` must be manually set to `false`. +* If using different domains for the Admin API and Kong Manager, `cookie_samesite` must be set to `off`. +Learn more about these properties in [Session Security in Kong Manager](/enterprise/{{page.kong_version}}/kong-manager/authentication/sessions/#session-security), and see [example configurations](/enterprise/{{page.kong_version}}/kong-manager/authentication/sessions/#example-configurations). + +Replace the entries surrounded by `<>` with values that are valid for your IdP. +For example, Google credentials can be found here: +https://console.cloud.google.com/projectselector/apis/credentials + +## Step 1 + +Create an **Admin** that has a **username** matching the **email** returned from +the Identity Provider upon successful login. + +```bash +$ http POST :8001/admins username="" email="" Kong-Admin-Token: +``` + +For example, if a user has a Google email address, **hal9000@sky.net**: + +```bash +$ http POST :8001/admins username="hal9000@sky.net" email="hal9000@sky.net" Kong-Admin-Token: +``` + +**Note:** The **email** entered for the **Admin** in the request is used to +ensure the **Admin** receives an email invitation, whereas **username** is the +attribute that the **Plugin** uses with the IdP. + +## Step 2 + +Assign the new **Admin** at least one **Role** so they can log in and access +Kong entities. + +```bash +$ http POST :8001/admins//roles roles="" +``` + +For example, if we wanted to grant **hal9000@sky.net** the **Role** of **Super Admin**: + +```bash +$ http POST :8001/admins/hal9000@sky.net/roles roles="super-admin" +``` diff --git a/app/enterprise/1.3-x/kong-manager/authentication/sessions.md b/app/enterprise/1.3-x/kong-manager/authentication/sessions.md new file mode 100644 index 000000000000..7bafe6702c46 --- /dev/null +++ b/app/enterprise/1.3-x/kong-manager/authentication/sessions.md @@ -0,0 +1,99 @@ +--- +title: Sessions in Kong Manager +book: admin_gui +--- + +## How does the Sessions Plugin work in Kong Manager? + +When a user logs in to Kong Manager with their credentials, the Sessions Plugin +will create a session cookie. The cookie is used for all subsequent requests and +is valid to authenticate the user. The session has a limited duration and renews +at a configurable interval, which helps prevent an attacker from obtaining and + using a stale cookie after the session has ended. + +The Session configuration is secure by default, which may +[require alteration](#session-security) if using HTTP or different domains for +the Admin API and Kong Manager. Even if an attacker were to obtain a stale +cookie, it would not benefit them since the cookie is encrypted. The encrypted +session data may be stored either in Kong or the cookie itself. + +## Configuration to Use the Sessions Plugin with Kong Manager + +To enable sessions authentication, configure the following: + +``` +enforce_rbac = on +admin_gui_auth = +admin_gui_session_conf = { + "secret":"", + "cookie_name":"", + "storage":"", + "cookie_lifetime":, + "cookie_renew": + "cookie_secure": + "cookie_samesite":"" +} +``` + +* `"cookie_name":""`: The name of the cookie + * For example, `"cookie_name":"kong_cookie"` +* `"secret":""`: The secret used in keyed HMAC generation. Although + the **Session Plugin's** default is a random string, the `secret` _must_ be + manually set for use with Kong Manager since it must be the same across all + Kong workers/nodes. +* `"storage":""`: Where session data is stored. It is `"cookie"` by default, but may be more secure if set to `"kong"` since access to the database would be required. +* `"cookie_lifetime":`: The duration (in seconds) that the session will remain open; 3600 by default. +* `"cookie_renew":`: The duration (in seconds) of a session remaining at which point + the Plugin renews the session; 600 by default. +* `"cookie_secure":`: `true` by default. See [Session Security](#session-security) for + exceptions. +* `"cookie_samesite":""`: `"Strict"` by default. See [Session Security](#session-security) for + exceptions. + +⚠️**Important:** +*The following properties must not be altered from default for use with Kong Manager:* +* `logout_methods` +* `logout_query_arg` +* `logout_post_arg` + +For detailed descriptions of each configuration property, learn more in the +[Session Plugin documentation](/enterprise/{{page.kong_version}}/plugins/session). + +## Session Security + +The Session configuration is secure by default, so the cookie uses the +[Secure, HttpOnly](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Secure_and_HttpOnly_cookies), +and [SameSite](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#SameSite_cookies) +directives. + +⚠️**Important:** The following properties must be altered depending on the protocol and domains in use: +* If using HTTP instead of HTTPS: `"cookie_secure": false` +* If using different domains for the Admin API and Kong Manager: `"cookie_samesite": "off"` + +## Example Configurations + +If using HTTPS and hosting Kong Manager and the Admin API from the same domain, +the following configuration could be used for Basic Auth: + +``` +enforce_rbac = on +admin_gui_auth = basic-auth +admin_gui_session_conf = { + "cookie_name":"$4m04$" + "secret":"change-this-secret" + "storage":"kong" +} +``` + +In testing, if using HTTP, the following configuration could be used instead: + +``` +enforce_rbac = on +admin_gui_auth = basic-auth +admin_gui_session_conf = { + "cookie_name":"04tm34l" + "secret":"change-this-secret" + "storage":"kong" + "cookie_secure":false +} +``` diff --git a/app/enterprise/1.3-x/kong-manager/authentication/super-admin.md b/app/enterprise/1.3-x/kong-manager/authentication/super-admin.md new file mode 100644 index 000000000000..783ebe933ec8 --- /dev/null +++ b/app/enterprise/1.3-x/kong-manager/authentication/super-admin.md @@ -0,0 +1,54 @@ +--- +title: How to Create a Super Admin +book: admin_gui +toc: false +--- + +If you seeded a **Super Admin** at the time of running +migrations by passing `KONG_PASSWORD`, you may log in to Kong Manager +with the `kong_admin` username. + +Otherwise, if `enforce_rbac=off`, you may create your first +**Super Admin** within Kong Manager itself. + +You may also use this guide to create additional **Super Admins** once +you have an account and `enforce_rbac=on`. + +1. Go to the "Organization" tab in Kong Manager. + +2. Click "+ Invite User" and fill out the form. + +3. Give the user the `super-admin` role in the `default` workspace. + +4. Return to the "Organization" page, and in the "Invited" section, +click the email address of the user in order to view them. + +5. Click "Generate Registration Link". + +6. Copy the link for later use after completing the account setup. + + + +## How to Create Your First Super Admin Account Post Installation + +In the event that the default `kong_admin`, **Super Admin**, was not seeded +during the initial database preparation step as defined in +[Step 1 in How To Start Kong Enterprise Securely](/enterprise/{{page.kong_version}}/getting-started/start-kong/#step-1), +the following steps outline how to create and enable a new Super Admin post +installation. + +1. Follow the instructions outlined above to create a new **Super Admin** user +account and generate a registration link. + +2. Before the link generated above can be used, RBAC and GUI Authentication must +be enabled. Follow the instructions on +[how to enable Basic Auth on Kong Manager](/enterprise/{{page.kong_version}}/kong-manager/authentication/basic). + +3. Paste the URL in your browser and you will be asked to create a password for +the newly defined **Super Admin** user on the Kong Manager. + +4. Go to the Kong Manager homepage and you will be prompted to login with the +new ***Super Admin*** credentials. diff --git a/app/enterprise/1.3-x/kong-manager/best-practices.md b/app/enterprise/1.3-x/kong-manager/best-practices.md new file mode 100644 index 000000000000..d5ee700ab51e --- /dev/null +++ b/app/enterprise/1.3-x/kong-manager/best-practices.md @@ -0,0 +1,4 @@ +--- +title: Best Practices with Kong Manager +book: admin_gui +--- \ No newline at end of file diff --git a/app/enterprise/1.3-x/kong-manager/faq.md b/app/enterprise/1.3-x/kong-manager/faq.md new file mode 100644 index 000000000000..c682e72f21a9 --- /dev/null +++ b/app/enterprise/1.3-x/kong-manager/faq.md @@ -0,0 +1,4 @@ +--- +title: FAQ/Troubleshooting Kong Manager +book: admin_gui +--- \ No newline at end of file diff --git a/app/enterprise/1.3-x/kong-manager/networking/configuration.md b/app/enterprise/1.3-x/kong-manager/networking/configuration.md new file mode 100644 index 000000000000..62ec0719eb35 --- /dev/null +++ b/app/enterprise/1.3-x/kong-manager/networking/configuration.md @@ -0,0 +1,103 @@ +--- +title: Default and Custom Networking Configuration for Kong Manager +book: admin_gui +--- + +## Default Configuration + +By default, Kong Manager starts up without authentication (see +[`admin_gui_auth`]), and it assumes that the Admin API is available +on port 8001 (see [Default Ports]) of the same host that serves +Kong Manager. + +## Custom Configuration + +Common configurations to enable are + +* Serving Kong Manager from a dedicated Kong node + + When Kong Manager is on a dedicated Kong node, it must make + external calls to the Admin API. Set [`admin_api_uri`] to the + location of your Admin API. + +* Securing Kong Manager through a **Kong Authentication Plugin** + + When Kong Manager is **secured through an Authentication Plugin** + and _not_ on a dedicated node, it makes calls to the Admin API on + the same host. By default, the Admin API listens on ports 8001 and + 8444 on localhost. Change [`admin_listen`] if necessary, or set + [`admin_api_uri`]. + +* Securing Kong Manager and serving it from a dedicated node + + When Kong Manager is **secured and served from a dedicated node**, + set [`admin_api_uri`] to the location of the Admin API. + +The table below summarizes which properties to set (or defaults to +verify) when configuring Kong Manager connectivity to the Admin API. + +| authentication enabled | local API | remote API | auth settings | +|------------------------|--------------|---------------|---------------------------------------------------| +| yes | [`admin_listen`] | [`admin_api_uri`] | [`admin_gui_auth`], [`enforce_rbac`], [`admin_gui_auth_conf`], [`admin_gui_session_conf`] | +| no | [`admin_listen`] | [`admin_api_uri`] | n/a | + +To enable authentication, configure the following properties: + +* [`admin_gui_auth`] set to the desired plugin +* [`admin_gui_auth_conf`] (optional) +* [`admin_gui_session_conf`] set to the desired configuration +* [`enforce_rbac`] set to `on` + +⚠️ When Kong Manager authentication is enabled, RBAC must be turned +on to enforce authorization rules. Otherwise, whoever can log in +to Kong Manager can perform any operation available on the Admin API. + +## TLS Certificates + +By default, if Kong Manager’s URL is accessed over HTTPS _without_ a certificate issued by a CA, it will +receive a self-signed certificate that modern web browsers will not trust, preventing the application +from accessing the Admin API. + +In order to serve Kong Manager over HTTPS, use a trusted certificate authority to issue TLS certificates, +and have the resulting `.crt` and `.key` files ready for the next step. + +1) Move `.crt` and `.key` files into the desired directory of the Kong node. + +2) Point [`admin_gui_ssl_cert`] and [`admin_gui_ssl_cert_key`] at the absolute paths of the certificate and key. + +``` +admin_gui_ssl_cert = /path/to/test.crt +admin_gui_ssl_cert_key = /path/to/test.key +``` + +3) Ensure that `admin_gui_url` is prefixed with `https` to use TLS, e.g., + +``` +admin_gui_url = https://test.com:8445 +``` + +### Using `https://localhost` + +If serving Kong Manager on localhost, it may be preferable to use HTTP as the protocol. If also using RBAC, +set `cookie_secure=false` in `admin_gui_session_conf`. The reason to use HTTP for `localhost` is that +creating TLS certificates for `localhost` requires more effort and configuration, and there may not be any +reason to use it. The adequate use cases for TLS are (1) when data is in transit between hosts, or (2) +when testing an application with [mixed content](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content) +(which Kong Manager does not use). + +External CAs cannot provide a certificate since no one uniquely owns `localhost`, nor is it rooted in a top-level +domain (e.g., `.com`, `.org`). Likewise, self-signed certificates will not be trusted in modern browsers. Instead, +it is necessary to use a private CA that allows you to issue your own certificates. Also ensure that the SSL state +is cleared from the browser after testing to prevent stale certificates from interfering with future access to +`localhost`. + + +[`admin_gui_auth`]: /enterprise/{{page.kong_version}}/property-reference/#admin_gui_auth +[`admin_gui_ssl_cert`]: /enterprise/{{page.kong_version}}/property-reference/#admin_gui_ssl_cert +[`admin_gui_ssl_cert_key`]: /enterprise/{{page.kong_version}}/property-reference/#admin_gui_ssl_cert_key +[`default_ports`]: /enterprise/{{page.kong_version}}/getting-started/start-kong/#default-ports +[`admin_api_uri`]: /enterprise/{{page.kong_version}}/property-reference/#admin_api_uri +[`admin_gui_auth_conf`]: /enterprise/{{page.kong_version}}/property-reference/#admin_gui_auth_conf +[`enforce_rbac`]: /enterprise/{{page.kong_version}}/property-reference/#enforce_rbac +[`admin_listen`]: /enterprise/{{page.kong_version}}/property-reference/#admin_listen +[`admin_gui_session_conf`]: /enterprise/{{page.kong_version}}/property-reference/#admin_gui_session_conf diff --git a/app/enterprise/1.3-x/kong-manager/networking/email.md b/app/enterprise/1.3-x/kong-manager/networking/email.md new file mode 100644 index 000000000000..e9ef4f711f03 --- /dev/null +++ b/app/enterprise/1.3-x/kong-manager/networking/email.md @@ -0,0 +1,23 @@ +--- +title: Configuring Kong Manager to Send Email +book: admin_gui +--- + +A **Super Admin** can invite other **Admins** to register in Kong Manager, and **Admins** +can reset their passwords using "Forgot Password" functionality. Both of these +workflows use email to communicate with the user. + +Emails from Kong Manager require the following configuration: + +* [`admin_emails_from`](/enterprise/{{page.kong_version}}/property-reference/#admin_emails_from) +* [`admin_emails_reply_to`](/enterprise/{{page.kong_version}}/property-reference/#admin_emails_reply_to) +* [`admin_invitation_expiry`](/enterprise/{{page.kong_version}}/property-reference/#admin_invitation_expiry) + +⚠️**Important:** Kong does not check for the validity of email +addresses set in the configuration. If the SMTP settings are +configured incorrectly, e.g., if they point to a non-existent +email address, Kong Manager will _not_ display an error message. + +For additional information about SMTP, refer to the +[general SMTP configuration](/enterprise/{{page.kong_version}}/property-reference/#general-smtp-configuration) +shared by Kong Manager and Dev Portal. \ No newline at end of file diff --git a/app/enterprise/1.3-x/kong-manager/overview.md b/app/enterprise/1.3-x/kong-manager/overview.md new file mode 100644 index 000000000000..a33d63fa49d4 --- /dev/null +++ b/app/enterprise/1.3-x/kong-manager/overview.md @@ -0,0 +1,70 @@ +--- +title: Kong Manager +toc: false +--- + +# Welcome to Kong Manager + +![Welcome to Kong Manager](https://konghq.com/wp-content/uploads/2018/11/km-overview.png) + +
+
+

+ + Networking +

+

Check and customize Kong Manager's networking configuration.

+ + Learn more → + +
+ +
+

+ + Security +

+

Authenticate Kong Admins with Basic Auth, OIDC, LDAP, and Sessions. Authorize Admins with RBAC and Workspaces.

+ + Learn more → + +
+ +
+

+ + Workspaces +

+

Segment your cluster into Workspaces for specific teams.

+ Learn more → +
+ +
+

+ + + RBAC Roles and Permissions +

+

Authorize Admins with default and custom Roles and Permissions.

+ Learn more → +
+ +
+

+ + Managing Admins +

+

Invite and keep track of every team member, all from one place

+ Learn more → +
+ +
+

+ + Vitals +

+

Feel the pulse of all Workspaces with health charts and performance metrics.

+ Learn more → +
+ +
diff --git a/app/enterprise/1.3-x/kong-manager/reset-password.md b/app/enterprise/1.3-x/kong-manager/reset-password.md new file mode 100644 index 000000000000..ebcd13838255 --- /dev/null +++ b/app/enterprise/1.3-x/kong-manager/reset-password.md @@ -0,0 +1,61 @@ +--- +title: How to Reset Passwords and RBAC Tokens in Kong Manager +--- + +## Passwords and RBAC Tokens + +For authentication, Kong uses two different credentials for **Admins**: + +1. An **Admin** uses a **password** to log in to Kong Manager. +2. An **Admin** uses an **RBAC token** to make requests to the Kong Admin API. + +If (and only if) using **Basic Authentication**, an Admin may reset their **password** from within Kong Manager. Since **LDAP** and **OIDC Authentication** imply that an organization stores and manages passwords outside of Kong, password reset is not possible with either type. + +Since a hash of each **RBAC token** is stored in Kong, then regardless of the Authentication option selected, an **Admin** may reset their **RBAC token** from within Kong Manager. Note that to support confidentiality, **RBAC tokens** are hashed and cannot be retrieved after they are created. If a user forgets the token, the only recourse is to reset it. + +## How to Reset a Forgotten Password in Kong Manager + +Prerequisites: + +* `enforce_rbac = on` +* `admin_gui_auth = basic-auth` +* SMTP is configured to send emails + +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. + +## How to Reset a Password from within Kong Manager + +Prerequisites: + +* `enforce_rbac = on` +* `admin_gui_auth = basic-auth` +* [`admin_gui_session_conf` is configured](/enterprise/{{page.kong_version}}/kong-manager/authentication/sessions/). +* Already logged in to Kong Manager + +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: + +* `enforce_rbac = on` +* [`admin_gui_auth` is set](/enterprise/{{page.kong_version}}/kong-manager/security/#authentication-with-plugins). +* [`admin_gui_session_conf` is configured](/enterprise/{{page.kong_version}}/kong-manager/authentication/sessions/). +* Already logged in to Kong Manager + +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/1.3-x/kong-manager/security.md b/app/enterprise/1.3-x/kong-manager/security.md new file mode 100644 index 000000000000..a02c70059390 --- /dev/null +++ b/app/enterprise/1.3-x/kong-manager/security.md @@ -0,0 +1,68 @@ +--- +title: Securing Kong Manager +book: admin_gui +--- + +## What Can Admins Do in Kong Manager? + +Kong Manager enables users with **Admin** accounts to access Kong entities such +as **Services**, **Plugins**, and **Consumers.** + +The following document summarizes Kong Manager's controls for *authentication* +and *authorization*. + +## Configuring Authentication + +Kong Enterprise comes packaged with **Authentication Plugins** that can be used +to secure Kong Manager. Unlike enabling a **Plugin** on an entity or cluster, +enabling an **Authentication Plugin** for *only* Kong Manager requires turning +on `enforce_rbac`, setting `admin_gui_auth` to the desired type, proper +configuration of `admin_gui_session_conf`, and configuring `admin_gui_auth_conf` +if needed. + +Kong Manager currently supports the following **Authentication Plugins**: + +* [**Basic Auth**](/enterprise/{{page.kong_version}}/kong-manager/authentication/basic/) +* [**OIDC**](/enterprise/{{page.kong_version}}/kong-manager/authentication/oidc/) +* [**LDAP**](/enterprise/{{page.kong_version}}/kong-manager/authentication/ldap/) + +In addition to the **Authentication Plugins** above, the new +[**Sessions Plugin**](/enterprise/{{page.kong_version}}/kong-manager/authentication/sessions/) +is now required when RBAC is enabled. It sends HTTP cookies to authenticate +client requests and maintain session information. + +⚠️**Important:** the **Sessions Plugin** requries a secret and is configured +securely by default. +* Under all circumstances, the `secret` must be manually set to a string. +* If using HTTP instead of HTTPS, `cookie_secure` must be manually set to `false`. +* If using different domains for the Admin API and Kong Manager, +`cookie_samesite` must be set to `off`. +Learn more about these properties in +[Session Security in Kong Manager](/enterprise/{{page.kong_version}}/kong-manager/authentication/sessions/#session-security), +and see [example configurations](/enterprise/{{page.kong_version}}/kong-manager/authentication/sessions/#example-configurations). + +## Access Control with Roles and Workspaces + +An **Admin** belongs to a **Workspace** and should have at least one **Role** +with a set of **Permissions**. If an **Admin** is in a **Workspace** *without* +a **Role**, they will not have the ability to see or interact with anything. + +By creating separate +[**Workspaces**](/enterprise/{{page.kong_version}}/kong-manager/administration/workspaces/workspaces/), + an organization with multiple teams can segment its Kong cluster so that + different teams do not have access to each other's Kong entities. + +Kong Enterprise implements Role-Based Access Control +([RBAC](/enterprise/{{page.kong_version}}/kong-manager/administration/rbac/rbac/)). +**Admins** are assigned **Roles** that have clearly defined **Permissions**. A +**Super Admin** has the ability to: + +* further customize **Permissions** +* create entirely new **Roles** +* invite or deactivate **Admins** +* assign or revoke their **Roles** + +In Kong Manager, limiting **Permissions** also restricts the visibility of the +application interface and navigation. Learn more about RBAC in Kong Manager in +our guide +[RBAC in Kong Manager](/enterprise/{{page.kong_version}}/kong-manager/administration/rbac/rbac). diff --git a/app/enterprise/1.3-x/kong-manager/service-directory-mapping.md b/app/enterprise/1.3-x/kong-manager/service-directory-mapping.md new file mode 100644 index 000000000000..599a196587a7 --- /dev/null +++ b/app/enterprise/1.3-x/kong-manager/service-directory-mapping.md @@ -0,0 +1,164 @@ +--- +title: Mapping Service Directory Groups to Kong Roles +--- + +### Introduction + +Service Directory Mapping allows organizations to use their LDAP Directory for authentication and authorization in Kong Enterprise. + +After starting Kong Enterprise with the desired configuration, you can create new Admins whose usernames match those in your LDAP directory. Those users will then be able to accept invitations to join Kong Manager and log in with their LDAP credentials. + +How Service Directory Mapping works in Kong: +Roles are created in Kong Enterprise using the Admin API or Kong Manager. +Groups are created and roles are associated with the groups. +When users log in to Kong Manager, they get permissions based on the group(s) they belong to. + +For example, if a User's Group changes in the Service Directory, their Kong Admin account's associated Role also changes in Kong Enterprise the next time they log in to Kong Manager. The mapping removes the task of manually managing access in Kong Enterprise, as it makes the Service Directory the system of record. + +### Prerequisites + +* Kong Enterprise installed and configured +* Kong Manager access +* A local LDAP directory + +### Configure Service Directory Mapping + +Configure Service Directory Mapping to use your LDAP Directory for authentication and authorization. + +### Step 1: Start Kong Enterprise + +From a terminal window, enter: + +``` +$ kong start [-c /path/to/kong/conf] +``` + +### Step 2: Enable LDAP Authentication and enforce RBAC + +To enable LDAP Authentication and enforce RBAC for Kong Manager, configure Kong with the following properties: + +``` +admin_gui_auth = ldap-auth-advanced +enforce_rbac = on +``` + +**Note**: When enabling LDAP Authentication in this step, you are enabling and configuring the LDAP Authentication Advanced Plugin for Kong Manager. No other configuration for the plugin is needed. + +### Step 3: Configure the Sessions plugin + +Configure the Sessions Plugin for Kong Manager: + +``` +admin_gui_session_conf = { "secret":"set-your-string-here" } +``` + +>Note: The **Sessions Plugin** requires a **secret** and is configured securely by default: + +* Under all circumstances, the secret must be manually set to a string. +* If using HTTP instead of HTTPS, cookie_secure must be manually set to false. +* If using different domains for the Admin API and Kong Manager, cookie_samesite must be set to off. Learn more about these properties in [_Session Security in Kong Manager_](https://docs.konghq.com/enterprise/0.36-x/kong-manager/authentication/sessions/#session-security), and see [_example configurations_](https://docs.konghq.com/enterprise/0.36-x/kong-manager/authentication/sessions/#example-configurations). + +### Step 4: Configure LDAP Authentication for Kong Manager + +Configure LDAP Authentication for Kong Manager with the following properties. Note the attribute variables are defined below: + +``` +admin_gui_auth_conf = { + "anonymous":"", \ + "attribute":"", \ + "bind_dn":"", \ + "base_dn":"", \ + "cache_ttl": 2, \ + "header_type":"Basic", \ + "keepalive":60000, \ + "ldap_host":"", \ + "ldap_password":"", \ + "ldap_port":389, \ + "start_tls":false, \ + "timeout":10000, \ + "verify_ldap_host":true, \ + "consumer_by":["username", "custom_id"], \ + "group_base_dn":"", + "group_name_attribute":"", + "group_member_attribute":"", +} +``` + +* `attribute`:``: The attribute used to identify LDAP users + * For example, to map LDAP users to admins by their username, `attribute":"uid` +* `bind_dn`:``: LDAP Bind DN (Distinguished Name) + * Used to perform LDAP search of user. This bind_dn should have permissions to search for the user being authenticated. + * For example, `uid=einstein,ou=scientists,dc=ldap,dc=com` +* `base_dn`:``: LDAP Base DN (Distinguished Name) + * For example, `ou=scientists,dc=ldap,dc=com` +* `ldap_host`:``: LDAP host domain. + * For example, `ec2-XX-XXX-XX-XXX.compute-1.amazonaws.com` +* `ldap_password`:``: LDAP password + * *Important*: As with any configuration property, sensitive information may be set as an environment variable instead of being written directly in the configuration file. +* `group_base_dn`:``: The default is `conf.base_dn` +* `group_name_attribute`: ``: The default is `conf.attribute` +* `group_member_attribute`:``: The default is `memberOf` + +### Define Roles with Permissions + +Define **Roles** with **Permissions** in Kong Enterprise, using the Admin API's [**_RBAC endpoints_**](https://docs.konghq.com/enterprise/latest/admin-api/rbac/reference/#update-or-create-a-role) or using Kong Manager's **Teams > [Admins tab](https://docs.konghq.com/enterprise/latest/kong-manager/administration/admins/invite/#using-the-organization-page-to-manage-users)**. You must manually define which Kong **Roles** correspond to each of the Service Directory's **Groups** using either of the following: + +In Kong Manager's **Directory Mapping** section. Go to **Teams > Groups** tab. +With the Admin API's **Directory Mapping** endpoints. + +Kong Enterprise will not write to the Service Directory, for example, a Kong Enterprise Admin cannot create **Users** or **Groups** in the directory. You must create **Users** and **Groups** independently before mapping them to Kong Enterprise. + +### User-Admin Mapping + +To map a Service Directory **User** to a Kong **Admin**, you must configure the **Admin's** username as the value of the **User's** name from their LDAP Distinguished Name (DN) corresponding the attribute configured in admin_gui_auth_conf. Creating an **Admin** account in [_Kong Manager_](https://docs.konghq.com/enterprise/latest/getting-started/add-admin/) or using the [_Admin API_](https://docs.konghq.com/enterprise/latest/admin-api/admins/reference/#invite-an-admin). + +For instructions on how to pair the bootstrapped **Super Admin** with a **Directory User**, see [_How to Set Up a Service Directory User as the First Super Admin_](https://github.com/Kong/docs.konghq.com-private/diffs/0?base_sha=51610257bfe352f3848bc43a98afb75c78951603&commentable=true&pull_number=339&sha1=51610257bfe352f3848bc43a98afb75c78951603&sha2=e8fcb3b1020e46603edee2c28bec7f20e4c61c94&short_path=8fcaf76&unchanged=expanded&utf8=%E2%9C%93#how-to-set-up-a-directory-user-as-the-first-super-admin). + +If you already have **Admins** with assigned **Roles** and want to use **Group** mapping instead, it is necessary to first remove all of their Roles. The Service Directory will serve as the system of record for **User** privileges. Assigned **Roles** will affect a user's privileges in addition to any roles mapped from **Groups.** + +### Group-Role Assignment + +Using Service Directory Mapping, **Groups** to **Roles** are mapped. When a user logs in, they are identified with their **Admin** username and then authenticated with the matching **User** credentials in the** Service Directory**. The Groups in the Service Directory are then automatically matched to the associated Roles that the organization has defined. + +#### Example + +1. Wayne Enterprises maps the Service Directory Group, T1-Mgmt, to the Kong Role super-admin. +2. Wayne Enterprises maps a Service Directory User, named bruce-wayne, to a Kong Admin account with the same name, bruce-wayne. +3. The User, bruce-wayne, is assigned to the Group T1-Mgmt in the LDAP Directory. + + +When bruce-wayne logs in as an Admin to Kong Manager, they will automatically have the Role of super-admin as a result of the mapping. + +If Wayne Enterprises decides to revoke bruce-wayne's privileges by removing their assignment to T1-Mgmt, they will no longer have the super-admin Role when they attempt to log in. + +### Set Up a Directory User as the First Super Admin + +**Important**: Setting up a Directory User as the first Super Admin is recommended by Kong. + + +The following is an example of setting up a Directory User as the first Super Admin. +The example shows an attribute is configured with a unique identifier (UID), and the Directory User you want to make the Super Admin has a distinguished name (DN) entry of UID=bruce-wayne: + +``` +HTTPie +$ http PATCH :8001/admins/kong_admin username="bruce-wayne" +Kong-Admin-Token: +cURL +$ curl --request 'PATCH' --header 'Kong-Admin-Token: ' --header +'Content-Type: application/json' --data '{"username":"bruce-wayne"}' +'localhost:8001/admins/kong_admin' +``` + +This User will be able to log in, but until you map a Group belonging to bruce-wayne to a Role, the User will only use the Directory for authentication. Once you map the super-admin Role to a Group that bruce-wayne is in, then you can delete the super-admin Role from the bruce-wayne Admin. Note the group you pick needs to be “super” in your directory, otherwise as other admins log in with a generic group, for example the “employee” group, they will also become super-admins. + +**Important**: If you delete the super-admin Role from your only Admin, and have not yet mapped the super-admin Role to a Group that Admin belongs to, then you will not be able to log in to Kong Manager. + +Alternatives: + +* Start Kong with RBAC turned off, map a Group to the super-admin Role, and then create an Admin to correspond to a User belonging to that Group. Doing so ensures that the Super Admin's privileges are entirely tied to the Directory Group, whereas bootstrapping a Super Admin only uses the Directory for authentication. + +Create all Admin accounts for matching Directory Users and ensure that their existing Groups map to appropriate Roles before enforcing RBAC. + + + + diff --git a/app/enterprise/1.3-x/kong-manager/vitals.md b/app/enterprise/1.3-x/kong-manager/vitals.md new file mode 100644 index 000000000000..b272bde2bbb7 --- /dev/null +++ b/app/enterprise/1.3-x/kong-manager/vitals.md @@ -0,0 +1,42 @@ +--- +title: Vitals in Kong Manager +book: admin_gui +--- + +For information about how to toggle the Vitals feature and use the Vitals API, +visit [Kong Vitals](/enterprise/{{page.kong_version}}/admin-api/vitals) + +## Vitals Charts + +Kong Manager's Vitals charts display the successes and errors of each Kong +Workspace within a given timespan. This visualization makes it easy for an +Admin to quickly identify the Workspaces in need of attention from the moment +they log in. + +To see the exact number of errors and successes at a given timestamp, hover +over coordinates on the chart. + +## Overview and Workspace Vitals + +Vitals will be on by default, so it will be accessible the first time a Super +Admin logs in. + +Any authorized user will see a large overview of Vitals for the entire Kong +cluster. Beneath it, each Workspace they have access to will also display their +respective Vitals. + +In addition to the chart with errors and successes, an authorized user will be +able to see the total number of requests and consumers. + + To see a more detailed chart of the entire Kong cluster, click the "Vitals" + link in the top navigation. For a more detailed chart of a particular Workspace, + navigate to the Workspace, then hover over the circular chart icon and click + "Status Codes". + +⚠️ **IMPORTANT**: If a user does not have access to a Workspace, its Vitals will +be hidden, and if they do not have access to any Vitals data, the charts will not appear. + +## Dashboard + +Beneath the Vitals graph, each Workspace will display the most recently added +services, consumers, and plugins. diff --git a/app/enterprise/1.3-x/loadbalancing.md b/app/enterprise/1.3-x/loadbalancing.md new file mode 100644 index 000000000000..ccb24bd8aa5c --- /dev/null +++ b/app/enterprise/1.3-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/1.3-x/logging.md b/app/enterprise/1.3-x/logging.md new file mode 100644 index 000000000000..8b35b3f48477 --- /dev/null +++ b/app/enterprise/1.3-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/1.3-x/network.md b/app/enterprise/1.3-x/network.md new file mode 100644 index 000000000000..5266093c8ebb --- /dev/null +++ b/app/enterprise/1.3-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/1.3-x/oasconfig.md b/app/enterprise/1.3-x/oasconfig.md new file mode 100644 index 000000000000..3999c89ad0b6 --- /dev/null +++ b/app/enterprise/1.3-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/1.3-x/pdk/index.md b/app/enterprise/1.3-x/pdk/index.md new file mode 100644 index 000000000000..2f951970b6c4 --- /dev/null +++ b/app/enterprise/1.3-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/1.3-x/pdk/kong.client.md b/app/enterprise/1.3-x/pdk/kong.client.md new file mode 100644 index 000000000000..947beb0aedbd --- /dev/null +++ b/app/enterprise/1.3-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/1.3-x/pdk/kong.ctx.md b/app/enterprise/1.3-x/pdk/kong.ctx.md new file mode 100644 index 000000000000..c44dc7e8a776 --- /dev/null +++ b/app/enterprise/1.3-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/1.3-x/pdk/kong.ip.md b/app/enterprise/1.3-x/pdk/kong.ip.md new file mode 100644 index 000000000000..86c74d21942e --- /dev/null +++ b/app/enterprise/1.3-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/1.3-x/pdk/kong.log.md b/app/enterprise/1.3-x/pdk/kong.log.md new file mode 100644 index 000000000000..1914b5d02f3c --- /dev/null +++ b/app/enterprise/1.3-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/1.3-x/pdk/kong.node.md b/app/enterprise/1.3-x/pdk/kong.node.md new file mode 100644 index 000000000000..b712a6340fd1 --- /dev/null +++ b/app/enterprise/1.3-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/1.3-x/pdk/kong.request.md b/app/enterprise/1.3-x/pdk/kong.request.md new file mode 100644 index 000000000000..4f86f01fec99 --- /dev/null +++ b/app/enterprise/1.3-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/1.3-x/pdk/kong.response.md b/app/enterprise/1.3-x/pdk/kong.response.md new file mode 100644 index 000000000000..34e0288186a0 --- /dev/null +++ b/app/enterprise/1.3-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/1.3-x/pdk/kong.router.md b/app/enterprise/1.3-x/pdk/kong.router.md new file mode 100644 index 000000000000..c30ceb5fca48 --- /dev/null +++ b/app/enterprise/1.3-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/1.3-x/pdk/kong.service.md b/app/enterprise/1.3-x/pdk/kong.service.md new file mode 100644 index 000000000000..dce94eb96192 --- /dev/null +++ b/app/enterprise/1.3-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/1.3-x/pdk/kong.service.request.md b/app/enterprise/1.3-x/pdk/kong.service.request.md new file mode 100644 index 000000000000..c47d45e974b6 --- /dev/null +++ b/app/enterprise/1.3-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/1.3-x/pdk/kong.service.response.md b/app/enterprise/1.3-x/pdk/kong.service.response.md new file mode 100644 index 000000000000..feede11b266e --- /dev/null +++ b/app/enterprise/1.3-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/1.3-x/pdk/kong.table.md b/app/enterprise/1.3-x/pdk/kong.table.md new file mode 100644 index 000000000000..7e62db9eed94 --- /dev/null +++ b/app/enterprise/1.3-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/1.3-x/plugin-development/access-the-datastore.md b/app/enterprise/1.3-x/plugin-development/access-the-datastore.md new file mode 100644 index 000000000000..f783a00d90a5 --- /dev/null +++ b/app/enterprise/1.3-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/1.3-x/plugin-development/admin-api.md b/app/enterprise/1.3-x/plugin-development/admin-api.md new file mode 100644 index 000000000000..b60861663d9e --- /dev/null +++ b/app/enterprise/1.3-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/72cf66ad8db0e104b775f3b5e913a08b9d02e3b1/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/1.3-x/plugin-development/custom-entities.md b/app/enterprise/1.3-x/plugin-development/custom-entities.md new file mode 100644 index 000000000000..c8272133ce83 --- /dev/null +++ b/app/enterprise/1.3-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 +-- `/migrations/000_base_my_plugin.lua` +return { + postgresql = { + up = [[ + CREATE TABLE IF NOT EXISTS "my_plugin_table" ( + "id" UUID PRIMARY KEY, + "created_at" TIMESTAMP WITHOUT TIME ZONE, + "col1" TEXT + ); + + DO $$ + BEGIN + CREATE INDEX IF NOT EXISTS "my_plugin_table_col1" + ON "my_plugin_table" ("col1"); + EXCEPTION WHEN UNDEFINED_COLUMN THEN + -- Do nothing, accept existing state + END$$; + ]], + }, + + cassandra = { + up = [[ + CREATE TABLE IF NOT EXISTS my_plugin_table ( + id uuid PRIMARY KEY, + created_at timestamp, + col1 text + ); + + CREATE INDEX IF NOT EXISTS ON my_plugin_table (col1); + ]], + } +} + +-- `/migrations/001_100_to_110.lua` +return { + postgresql = { + up = [[ + DO $$ + BEGIN + ALTER TABLE IF EXISTS ONLY "my_plugin_table" ADD "cache_key" TEXT UNIQUE; + EXCEPTION WHEN DUPLICATE_COLUMN THEN + -- Do nothing, accept existing state + END; + $$; + ]], + teardown = function(connector, helpers) + assert(connector:connect_migrations()) + assert(connector:query([[ + DO $$ + BEGIN + ALTER TABLE IF EXISTS ONLY "my_plugin_table" DROP "col1"; + EXCEPTION WHEN UNDEFINED_COLUMN THEN + -- Do nothing, accept existing state + END$$; + ]]) + end, + }, + + cassandra = { + up = [[ + ALTER TABLE my_plugin_table ADD cache_key text; + CREATE INDEX IF NOT EXISTS ON my_plugin_table (cache_key); + ]], + teardown = function(connector, helpers) + assert(connector:connect_migrations()) + assert(connector:query("ALTER TABLE my_plugin_table DROP col1")) + end, + } +} +``` + +If a plugin only supports Postgres or Cassandra, only the section for one strategy is +needed. Each strategy section has two parts, `up` and `teardown`. + +* `up` is an optional string of raw SQL/CQL statements. Those statements will be executed + when `kong migrations up` is executed. +* `teardown` is an optional Lua function, which takes a `connector` parameter. Such connector + can invoke the `query` method to execute SQL/CQL queries. Teardown is triggered by + `kong migrations finish` + +It is recommended that all the non-destructive operations, such as creation of new tables and +addition of new records is done on the `up` sections, while destructive operations (such as +removal of data, changing row types, insertion of new data) is done on the `teardown` sections. + +In both cases, it is recommended that all the SQL/CQL statements are written so that they are +as reentrant as possible. `DROP TABLE IF EXISTS` instead of `DROP TABLE`, +`CREATE INDEX IF NOT EXIST` instead of `CREATE INDEX`, etc. If a migration fails for some +reason, it is expected that the first attempt at fixing the problem will be simply +re-running the migrations. + +While Postgres does, Cassandra does not support constraints such as "NOT +NULL", "UNIQUE" or "FOREIGN KEY", but Kong provides you with such features when +you define your model's schema. Bear in mind that this schema will be the same +for both Postgres and Cassandra, hence, you might trade-off a pure SQL schema +for one that works with Cassandra too. + +**IMPORTANT**: if your `schema` uses a `unique` constraint, then Kong will +enforce it for Cassandra, but for Postgres you must set this constraint in +the migrations. + +To see a real-life example, give a look at the [Key-Auth plugin migrations](https://github.com/Kong/kong/tree/{{page.kong_version}}/kong/plugins/key-auth/migrations). + +--- + +## Defining a Schema + +The first step to using custom entities in a custom plugin is defining one +or more *schemas*. + +A schema is a Lua table which describes entities. There's structural information +like how are the different fields of the entity named and what are their types, +which is similar to the fields describing your [plugin +configuration]({{page.book.chapters.plugin-configuration}})). +Compared to plugin configuration schemas, custom entity schemas require +additional metadata (e.g. which field, or fields, constitute the entities' +primary key). + +Schemas are to be defined in a module named: + +``` +kong.plugins..daos +``` + +Meaning that there should be a file called `/daos.lua` inside your +plugin folder. The `daos.lua` file should return a table containing one or more +schemas. For example: + +```lua +-- daos.lua +local typedefs = require "kong.db.schema.typedefs" + + +return { + -- this plugin only results in one custom DAO, named `keyauth_credentials`: + keyauth_credentials = { + name = "keyauth_credentials", -- the actual table in the database + endpoint_key = "key", + primary_key = { "id" }, + cache_key = { "key" }, + generate_admin_api = true, + fields = { + { + -- a value to be inserted by the DAO itself + -- (think of serial id and the uniqueness of such required here) + id = typedefs.uuid, + }, + { + -- also interted by the DAO itself + created_at = typedefs.auto_timestamp_s, + }, + { + -- a foreign key to a consumer's id + consumer = { + type = "foreign", + reference = "consumers", + default = ngx.null, + on_delete = "cascade", + }, + }, + { + -- a unique API key + key = { + type = "string", + required = false, + unique = true, + auto = true, + }, + }, + }, + }, +} +``` + +This example `daos.lua` file introduces a single schema called `keyauth_credentials`. + +Here is a description of some top-level properties: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
namestring (required)It will be used to determine the DAO name (kong.db.[name]).
primary_keytable (required) + Field names forming the entity's primary key. + Schemas support composite keys, even if most Kong core entities currently use an UUID named + id. If you are using Cassandra and need a composite key, it should have the same + fields as the partition key. +
endpoint_keystring (optional) + The name of the field used as an alternative identifier on the Admin API. + On the example above, key is the endpoint_key. This means that a credential with + id = 123 and key = "foo" could be referenced as both + /keyauth_credentials/123 and /keyauth_credentials/foo. +
cache_keytable (optional) + Contains the name of the fields used for generating the cache_key, a string which must + unequivocally identify the entity inside Kong's cache. A unique field, like key in your example, + is usually good candidate. In other cases a combination of several fields is preferable. +
fieldstable + Each field definition is a table with a single key, which is the field's name. The table value is + a subtable containing the field's attributes, some of which will be explained below. +
+ +Many field attributes encode *validation rules*. When attempting to insert or update entities using +the DAO, these validations will be checked, and an error returned if the provided input doesn't conform +to them. + +The `typedefs` variable (obtained by requiring `kong.db.schema.typedefs`) is a table containing +a lot of useful type definitions and aliases, including `typedefs.uuid`, the most usual type for the primary key, +and `typedefs.auto_timestamp_s`, for `created_at` fields. It is used extensively when defining fields. + +Here's a non-exhaustive explanation of some of the field attributes available: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Attribute nametypeDescription
typestring + Schemas support the following scalar types: "string", "integer", "number" and + "boolean". Compound types like "array", "record", or "set" are + also supported.

+ + In additon to these values, the type attribute can also take the special "foreign" value, + which denotes a foreign relationship.

+ + Each field will need to be backed by database fields of appropriately similar types, created via migrations.

+ + type is the only required attribute for all field definitions. +
defaultany (matching with type attribute) + Specifies the value the field will have when attempting to insert it, if no value was provided. + Default values are always set via Lua, never by the underlying database. It is thus not recommended to set + any default values on fields in migrations. +
requiredboolean + When set to true on a field, an error will be thrown when attempting to insert an entity lacking a value + for said field (unless the field in question has a default value). +
uniqueboolean +

When set to true on a field, an error will be thrown when attempting to insert an entity on the database, + but another entity already has the given value on said field.

+ +

This attribute must be backed up by declaring fields as UNIQUE in migrations when using + PostgreSQL. The Cassandra strategy does a check in Lua before attempting inserts, so it doesn't require any special treatment. +

+
autoboolean + When attempting to insert an entity without providing a value for this a field where auto is set to true, +

+
    +
  • If type == "uuid", the field will take a random UUID as value.
  • +
  • If type == "string", the field will take a random string.
  • +
  • If the field name is created_at or updated_at, the field will take the current time when + inserting / updating, as appropriate.
  • +
+
referencestringRequired for fields of type foreign. The given string must be the name of an existing schema, + to which the foreign key will "point to". This means that if a schema B has a foreign key pointing to schema A, + then A needs to be loaded before B. +
on_deletestring + Optional and exclusive for fields of type foreign. It dictates what must happen + with entities linked by a foreign key when the entity being referenced is deleted. It can have three possible + values:

+ +
    +
  • "cascade": When the linked entity is deleted, all the dependent entities must also be deleted.
  • +
  • "null": When the linked entity is deleted, all the dependent entities will have their foreign key + field set to null.
  • +
  • "restrict": Attempting to delete an entity with linked entities will result in an error.
  • +
+ +

+ In Cassandra this is handled with pure Lua code, but in PostgreSQL it will be necessary to declare the references + as ON DELETE CASCADE/NULL/RESTRICT in a migration. +
+ + +To learn more about schemas, see: + +* The source code of [typedefs.lua](https://github.com/Kong/kong/blob/{{page.kong_version | replace: "x", "0"}}/kong/db/schema/typedefs.lua) + to get an idea of what's provided there by default. +* [The Core Schemas](https://github.com/Kong/kong/tree/{{page.kong_version | replace: "x", "0"}}/kong/db/schema/entities) + to see examples of some other field attributes not discussed here. +* [All the `daos.lua` files for embedded plugins](https://github.com/search?utf8=%E2%9C%93&q=repo%3Akong%2Fkong+path%3A%2Fkong%2Fplugins+filename%3Adaos.lua), + especially [the key-auth one](https://github.com/Kong/kong/blob/{{page.kong_version | replace: "x", "0"}}/kong/plugins/key-auth/daos.lua), + which was used for this guide as an example. + +--- + +## The custom DAO + +The schemas are not used directly to interact with the database. Instead, a DAO +is built for each valid schema. A DAO takes the name of the schema it wraps, and is +accessible through the `kong.db` interface. + +For the example schema above, the DAO generated would be available for plugins +via `kong.db.keyauth_credentials`. + +### Selecting an entity + +``` lua +local entity, err, err_t = kong.db.:select(primary_key) +``` + +Attempts to find an entity in the database and return it. Three things can happen: + +* The entity was found. In this case, it is returned as a regular Lua table. +* An error occurred - for example the connection with the database was lost. In that + case the first returned value will be `nil`, the second one will be a string + describing the error, and the last one will be the same error in table form. +* An error does not occur but the entity is not found. Then the function will + just return `nil`, with no error. + +Example of usage: + +``` lua +local entity, err = kong.db.keyauth_credentials:select({ + id = "c77c50d2-5947-4904-9f37-fa36182a71a9" +}) + +if err then + kong.log.err("Error when inserting keyauth credential: " .. err) + return nil +end + +if not entity then + kong.log.err("Could not find credential.") + return nil +end +``` + +### Iterating over all the entities + +``` lua +for entity, err on kong.db.:each(entities_per_page) do + if err then + ... + end + ... +end +``` + +This method efficiently iterates over all the entities in the database by making paginated +requests. The `entities_per_page` parameter, which defaults to `100`, controls how many +entities per page are returned. + +On each iteration, a new `entity` will be returned or, if there is any error, the `err` +variable will be filled up with an error. The recommended way to iterate is checking `err` first, +and otherwise assume that `entity` is present. + +Example of usage: + +``` lua +for credential, err on kong.db.keyauth_credentials:each(1000) do + if err then + kong.log.err("Error when iterating over keyauth credentials: " .. err) + return nil + end + + kong.log("id: " .. credential.id) +end +``` + +This example iterates over the credentials in pages of 1000 items, logging their ids unless +an error happens. + +### Inserting an entity + +``` lua +local entity, err, err_t = kong.db.:insert() +``` + +Inserts an entity in the database, and returns a copy of the inserted entity, or +`nil`, an error message (a string) and a table describing the error in table form. + +When the insert is successful, the returned entity contains the extra values produced by +`default` and `auto`. + +The following example uses the `keyauth_credentials` DAO to insert a credential for a given +Consumer, setting its `key` to `"secret"`. Notice the syntax for referencing foreign keys. + +``` lua +local entity, err = kong.db.keyauth_credentials:insert({ + consumer = { id = "c77c50d2-5947-4904-9f37-fa36182a71a9" }, + key = "secret", +}) + +if not entity then + kong.log.err("Error when inserting keyauth credential: " .. err) + return nil +end +``` + +The returned entity, assuming no error happened will have `auto`-filled fields, like `id` and `created_at`. + +### Updating an entity + +``` lua +local entity, err, err_t = kong.db.:update(primary_key, ) +``` + +Updates an existing entity, provided it can be found using the provided primary key and a set of values. + +The returned entity will be the entity after the update takes place, or `nil` + an error message + an error table. + +The following example modifies the `key` field of an existing credential given the credential's id: + +``` lua +local entity, err = kong.db.keyauth_credentials:update({ + { id = "2b6a2022-770a-49df-874d-11e2bf2634f5" }, + { key = "updated_secret" }, +}) + +if not entity then + kong.log.err("Error when updating keyauth credential: " .. err) + return nil +end +``` + +Notice how the syntax for specifying a primary key is similar to the one used to specify a foreign key. + +### Upserting an entity + +``` lua +local entity, err, err_t = kong.db.:upsert(primary_key, ) +``` + +`upsert` is a mixture of `insert` and `update`: + +* When the provided `primary_key` identifies an existing entity, it works like `update`. +* When the provided `primary_key` does not identify an existing entity, it works like `insert` + +Given this code: + +``` lua +local entity, err = kong.db.keyauth_credentials:upsert({ + { id = "2b6a2022-770a-49df-874d-11e2bf2634f5" }, + { consumer = { id = "a96145fb-d71e-4c88-8a5a-2c8b1947534c" } }, +}) + +if not entity then + kong.log.err("Error when upserting keyauth credential: " .. err) + return nil +end +``` + +Two things can happen: + +* If a credential with id `2b6a2022-770a-49df-874d-11e2bf2634f5` exists, + then this code will attempt to set its Consumer to the provided one. +* If the credential does not exist, then this code is attempting to create + a new credential, with the given id and Consumer. + +### Deleting an entity + +``` lua +local ok, err, err_t = kong.db.:delete(primary_key) +``` + +Attempts to delete the entity identified by `primary_key`. It returns `true` +if the entity *doesn't exist* after calling this method, or `nil` + error + +error table if an error is detected. + +Notice that calling `delete` will succeed if the entity didn't exist *before +calling it*. This is for performance reasons - we want to avoid doing a +read-before-delete if we can avoid it. If you want to do this check, you +must do it manually, by checking with `select` before invoking `delete`. + +Example: + +``` lua +local ok, err = kong.db.keyauth_credentials:delete({ + { id = "2b6a2022-770a-49df-874d-11e2bf2634f5" } +}) + +if not ok then + kong.log.err("Error when deleting keyauth credential: " .. err) + return nil +end +``` + +--- + +## Caching custom entities + +Sometimes custom entities are required on every request/response, which in turn +triggers a query on the datastore every time. This is very inefficient because +querying the datastore adds latency and slows the request/response down, and +the resulting increased load on the datastore could affect the datastore +performance itself and, in turn, other Kong nodes. + +When a custom entity is required on every request/response it is good practice +to cache it in-memory by leveraging the in-memory cache API provided by Kong. + +The next chapter will focus on caching custom entities, and invalidating them +when they change in the datastore: [Caching custom entities]({{page.book.next}}). + +--- + +Next: [Caching custom entities ›]({{page.book.next}}) + +[Admin API]: /enterprise/{{page.kong_version}}/admin-api/ +[Plugin Development Kit]: /enterprise/{{page.kong_version}}/pdk diff --git a/app/enterprise/1.3-x/plugin-development/custom-logic.md b/app/enterprise/1.3-x/plugin-development/custom-logic.md new file mode 100644 index 000000000000..fdb5f54c64bf --- /dev/null +++ b/app/enterprise/1.3-x/plugin-development/custom-logic.md @@ -0,0 +1,303 @@ +--- +title: Plugin Development - Implementing Custom Logic +book: plugin_dev +chapter: 3 +--- + +
+ Note: This chapter assumes that you are familiar with + Lua. +
+ +## Introduction + +A Kong plugin allows you to inject custom logic (in Lua) at several +entry-points in the life-cycle of a request/response or a tcp stream +connection as it is proxied by Kong. To do so, one must implement one +or several of the methods of the `base_plugin.lua` interface. Those +methods are to be implemented in a module namespaced under: +`kong.plugins..handler` + +## Module + +``` +kong.plugins..handler +``` + +## Available contexts + +The plugins interface allows you to override any of the following methods in +your `handler.lua` file to implement custom logic at various entry-points +of the execution life-cycle of Kong: + +- **[HTTP Module]** *is used for plugins written for HTTP/HTTPS requests* + +| Function name | Phase | Description +|--------------------|-------------------|------------ +| `:init_worker()` | [init_worker] | Executed upon every Nginx worker process's startup. +| `:certificate()` | [ssl_certificate] | Executed during the SSL certificate serving phase of the SSL handshake. +| `:rewrite()` | [rewrite] | Executed for every request upon its reception from a client as a rewrite phase handler. *NOTE* in this phase neither the `Service` nor the `Consumer` have been identified, hence this handler will only be executed if the plugin was configured as a global plugin! +| `:access()` | [access] | Executed for every request from a client and before it is being proxied to the upstream service. +| `:header_filter()` | [header_filter] | Executed when all response headers bytes have been received from the upstream service. +| `:body_filter()` | [body_filter] | Executed for each chunk of the response body received from the upstream service. Since the response is streamed back to the client, it can exceed the buffer size and be streamed chunk by chunk. hence this method can be called multiple times if the response is large. See the [lua-nginx-module] documentation for more details. +| `:log()` | [log] | Executed when the last response byte has been sent to the client. + +- **[Stream Module]** *is used for plugins written for TCP stream connections* + +| Function name | Phase | Description +|--------------------|------------------------------------------------------------------------------|------------ +| `:init_worker()` | [init_worker] | Executed upon every Nginx worker process's startup. +| `:preread()` | [preread] | Executed once for every connection. +| `:log()` | [log](https://github.com/openresty/stream-lua-nginx-module#log_by_lua_block) | Executed once for each connection after it has been closed. + +All of those functions, except `init_worker`, take one parameter which is given +by Kong upon its invocation: the configuration of your plugin. This parameter +is a Lua table, and contains values defined by your users, according to your +plugin's schema (described in the `schema.lua` module). More on plugins schemas +in the [next chapter]({{page.book.next}}). + +[HTTP Module]: https://github.com/openresty/lua-nginx-module +[Stream Module]: https://github.com/openresty/stream-lua-nginx-module +[init_worker]: https://github.com/openresty/lua-nginx-module#init_worker_by_lua_by_lua_block +[ssl_certificate]: https://github.com/openresty/lua-nginx-module#ssl_certificate_by_lua_block +[rewrite]: https://github.com/openresty/lua-nginx-module#rewrite_by_lua_block +[access]: https://github.com/openresty/lua-nginx-module#access_by_lua_block +[header_filter]: https://github.com/openresty/lua-nginx-module#header_filter_by_lua_block +[body_filter]: https://github.com/openresty/lua-nginx-module#body_filter_by_lua_block +[log]: https://github.com/openresty/lua-nginx-module#log_by_lua_block +[preread]: https://github.com/openresty/stream-lua-nginx-module#preread_by_lua_block + +--- + +## handler.lua specifications + +The `handler.lua` file must return a table implementing the functions you wish +to be executed. In favor of brevity, here is a commented example module +implementing all the available methods of both modules (please note some +of them are shared between modules, like `log`): + +
+ Note: Kong uses the + rxi/classic module to simulate + classes in Lua and ease the inheritance pattern. +
+ +```lua +-- Extending the Base Plugin handler is optional, as there is no real +-- concept of interface in Lua, but the Base Plugin handler's methods +-- can be called from your child implementation and will print logs +-- in your `error.log` file (where all logs are printed). +local BasePlugin = require "kong.plugins.base_plugin" + + +local CustomHandler = BasePlugin:extend() + + +CustomHandler.VERSION = "1.0.0" +CustomHandler.PRIORITY = 10 + + +-- Your plugin handler's constructor. If you are extending the +-- Base Plugin handler, it's only role is to instantiate itself +-- with a name. The name is your plugin name as it will be printed in the logs. +function CustomHandler:new() + CustomHandler.super.new(self, "my-custom-plugin") +end + +function CustomHandler:init_worker() + -- Eventually, execute the parent implementation + -- (will log that your plugin is entering this context) + CustomHandler.super.init_worker(self) + + -- Implement any custom logic here +end + + +function CustomHandler:preread(config) + -- Eventually, execute the parent implementation + -- (will log that your plugin is entering this context) + CustomHandler.super.preread(self) + + -- Implement any custom logic here +end + + +function CustomHandler:certificate(config) + -- Eventually, execute the parent implementation + -- (will log that your plugin is entering this context) + CustomHandler.super.certificate(self) + + -- Implement any custom logic here +end + +function CustomHandler:rewrite(config) + -- Eventually, execute the parent implementation + -- (will log that your plugin is entering this context) + CustomHandler.super.rewrite(self) + + -- Implement any custom logic here +end + +function CustomHandler:access(config) + -- Eventually, execute the parent implementation + -- (will log that your plugin is entering this context) + CustomHandler.super.access(self) + + -- Implement any custom logic here +end + +function CustomHandler:header_filter(config) + -- Eventually, execute the parent implementation + -- (will log that your plugin is entering this context) + CustomHandler.super.header_filter(self) + + -- Implement any custom logic here +end + +function CustomHandler:body_filter(config) + -- Eventually, execute the parent implementation + -- (will log that your plugin is entering this context) + CustomHandler.super.body_filter(self) + + -- Implement any custom logic here +end + +function CustomHandler:log(config) + -- Eventually, execute the parent implementation + -- (will log that your plugin is entering this context) + CustomHandler.super.log(self) + + -- Implement any custom logic here +end + +-- This module needs to return the created table, so that Kong +-- can execute those functions. +return CustomHandler +``` + +Of course, the logic of your plugin itself can be abstracted away in another +module, and called from your `handler` module. Many existing plugins have +already chosen this pattern when their logic is verbose, but it is purely +optional: + +```lua +local BasePlugin = require "kong.plugins.base_plugin" + +-- The actual logic is implemented in those modules +local access = require "kong.plugins.my-custom-plugin.access" +local body_filter = require "kong.plugins.my-custom-plugin.body_filter" + + +local CustomHandler = BasePlugin:extend() + + +CustomHandler.VERSION = "1.0.0" +CustomHandler.PRIORITY = 10 + + +function CustomHandler:new() + CustomHandler.super.new(self, "my-custom-plugin") +end + +function CustomHandler:access(config) + CustomHandler.super.access(self) + + -- Execute any function from the module loaded in `access`, + -- for example, `execute()` and passing it the plugin's configuration. + access.execute(config) +end + +function CustomHandler:body_filter(config) + CustomHandler.super.body_filter(self) + + -- Execute any function from the module loaded in `body_filter`, + -- for example, `execute()` and passing it the plugin's configuration. + body_filter.execute(config) +end + + +return CustomHandler +``` + +See [the source code of the Key-Auth plugin](https://github.com/Kong/kong/blob/master/kong/plugins/key-auth/handler.lua) +for an example of a real-life handler code. + +--- + +## Plugin Development Kit + +Logic implemented in those phases will most likely have to interact with the +request/response objects or core components (e.g. access the cache, and +database). Kong provides a [Plugin Development Kit][pdk] (or "PDK") for such +purposes: a set of Lua functions and variables that can be used by plugins to +execute various gateway operations in a way that is guaranteed to be +forward-compatible with future releases of Kong. + +When you are trying to implement some logic that needs to interact with Kong +(e.g. retrieving request headers, producing a response from a plugin, logging +some error or debug information), you should consult the [Plugin Development +Kit Reference][pdk]. + +--- + +## Plugins execution order + +Some plugins might depend on the execution of others to perform some +operations. For example, plugins relying on the identity of the consumer have +to run **after** authentication plugins. Considering this, Kong defines +**priorities** between plugins execution to ensure that order is respected. + +Your plugin's priority can be configured via a property accepting a number in +the returned handler table: + +```lua +CustomHandler.PRIORITY = 10 +``` + +The higher the priority, the sooner your plugin's phases will be executed in +regard to other plugins' phases (such as `:access()`, `:log()`, etc.). + +The current order of execution for the bundled plugins is: + +Plugin | Priority +----------------------------|---------- +pre-function | `+inf` +zipkin | 100000 +ip-restriction | 3000 +bot-detection | 2500 +cors | 2000 +session | 1900 +kubernetes-sidecar-injector | 1006 +jwt | 1005 +oauth2 | 1004 +key-auth | 1003 +ldap-auth | 1002 +basic-auth | 1001 +hmac-auth | 1000 +request-size-limiting | 951 +acl | 950 +rate-limiting | 901 +response-ratelimiting | 900 +request-transformer | 801 +response-transformer | 800 +aws-lambda | 750 +azure-functions | 749 +prometheus | 13 +http-log | 12 +statsd | 11 +datadog | 10 +file-log | 9 +udp-log | 8 +tcp-log | 7 +loggly | 6 +syslog | 4 +request-termination | 2 +correlation-id | 1 +post-function | -1000 + +--- + +Next: [Plugin configuration ›]({{page.book.next}}) + +[lua-nginx-module]: https://github.com/openresty/lua-nginx-module +[pdk]: /enterprise/{{page.kong_version}}/pdk diff --git a/app/enterprise/1.3-x/plugin-development/distribution.md b/app/enterprise/1.3-x/plugin-development/distribution.md new file mode 100644 index 000000000000..6e847f49326f --- /dev/null +++ b/app/enterprise/1.3-x/plugin-development/distribution.md @@ -0,0 +1,306 @@ +--- +title: Plugin Development - (un)Installing your plugin +book: plugin_dev +chapter: 10 +--- + +## Introduction + +Custom plugins for Kong consist of Lua source files that need to be in the file +system of each of your Kong nodes. This guide will provide you with +step-by-step instructions that will make a Kong node aware of your custom +plugin(s). + +These steps should be applied to each node in your Kong cluster, to ensure the +custom plugin(s) are available on each one of them. + +## Packaging sources + +You can either use a regular packing strategy (e.g. `tar`), or use the LuaRocks +package manager to do it for you. We recommend LuaRocks as it is installed +along with Kong when using one of the official distribution packages. + +When using LuaRocks, you must create a `rockspec` file, which specifies the +package contents. For an example see the [Kong plugin +template][plugin-template], for more info about the format see the LuaRocks +[documentation on rockspecs][rockspec]. + +Pack your rock using the following command (from the plugin repo): + + # install it locally (based on the `.rockspec` in the current directory) + $ luarocks make + + # pack the installed rock + $ luarocks pack + +Assuming your plugin rockspec is called +`kong-plugin-my-plugin-0.1.0-1.rockspec`, the above would become; + + $ luarocks pack kong-plugin-my-plugin 0.1.0-1 + +The LuaRocks `pack` command has now created a `.rock` file (this is simply a +zip file containing everything needed to install the rock). + +If you do not or cannot use LuaRocks, then use `tar` to pack the +`.lua` files of which your plugin consists into a `.tar.gz` archive. You can +also include the `.rockspec` file if you do have LuaRocks on the target +systems. + +The contents of this archive should be close to the following: + + $ tree + + ├── INSTALL.txt + ├── README.md + ├── kong + │ └── plugins + │ └── + │ ├── handler.lua + │ └── schema.lua + └── -.rockspec + +[Back to TOC](#table-of-contents) + +--- + +## Installing the plugin + +For a Kong node to be able to use the custom plugin, the custom plugin's Lua +sources must be installed on your host's file system. There are multiple ways +of doing so: via LuaRocks, or manually. Choose one, and jump to section 3. + +1. Via LuaRocks from the created 'rock' + + The `.rock` file is a self contained package that can be installed locally + or from a remote server. + + If the `luarocks` utility is installed in your system (this is likely the + case if you used one of the official installation packages), you can + install the 'rock' in your LuaRocks tree (a directory in which LuaRocks + installs Lua modules). + + It can be installed by doing: + + $ luarocks install + + The filename can be a local name, or any of the supported methods, eg. + `http://myrepository.lan/rocks/my-plugin-0.1.0-1.all.rock` + +2. Via LuaRocks from the source archive + + If the `luarocks` utility is installed in your system (this is likely the + case if you used one of the official installation packages), you can + install the Lua sources in your LuaRocks tree (a directory in which + LuaRocks installs Lua modules). + + You can do so by changing the current directory to the extracted archive, + where the rockspec file is: + + $ cd + + And then run the following: + + $ luarocks make + + This will install the Lua sources in `kong/plugins/` in your + system's LuaRocks tree, where all the Kong sources are already present. + +3. Manually + + A more conservative way of installing your plugin's sources is + to avoid "polluting" the LuaRocks tree, and instead, point Kong + to the directory containing them. + + This is done by tweaking the `lua_package_path` property of your Kong + configuration. Under the hood, this property is an alias to the `LUA_PATH` + variable of the Lua VM, if you are familiar with it. + + Those properties contain a semicolon-separated list of directories in + which to search for Lua sources. It should be set like so in your Kong + configuration file: + + lua_package_path = //?.lua;; + + Where: + + * `/` is the path to the directory containing the + extracted archive. It should be the location of the `kong` directory + from the archive. + * `?` is a placeholder that will be replaced by + `kong.plugins.` when Kong will try to load your plugin. Do + not change it. + * `;;` a placeholder for the "the default Lua path". Do not change it. + + Example: + + The plugin `something` being located on the file system such that the + handler file is: + + /usr/local/custom/kong/plugins//handler.lua + + The location of the `kong` directory is: `/usr/local/custom`, hence the + proper path setup would be: + + lua_package_path = /usr/local/custom/?.lua;; + + Multiple plugins: + + If you wish to install two or more custom plugins this way, you can set + the variable to something like: + + lua_package_path = /path/to/plugin1/?.lua;/path/to/plugin2/?.lua;; + + * `;` is the separator between directories. + * `;;` still means "the default Lua path". + + Note: you can also set this property via its environment variable + equivalent: `KONG_LUA_PACKAGE_PATH`. + +Reminder: regardless of which method you are using to install your plugin's +sources, you must still do so for each node in your Kong cluster. + +[Back to TOC](#table-of-contents) + +--- + +## Load the plugin + +You must now add the custom plugin's name to the `plugins` list in your +Kong configuration (on each Kong node): + + plugins = bundled, + +Or, if you don't want to include the bundled plugins: + + plugins = + + +If you are using two or more custom plugins, insert commas in between, like so: + + plugins = bundled,plugin1,plugin2 + +Or + + plugins = plugin1,plugin2 + +Note: you can also set this property via its environment variable equivalent: +`KONG_PLUGINS`. + +Reminder: don't forget to update the `plugins` directive for each node +in your Kong cluster. + +Reminder: the plugin will take effect after restart kong: + + kong restart + +But, if you want to apply plugin while kong never stop, you can use this: + + kong prepare + kong reload + + +[Back to TOC](#table-of-contents) + +--- + +## Verify loading the plugin + +You should now be able to start Kong without any issue. Consult your custom +plugin's instructions on how to enable/configure your plugin +on a Service, Route, or Consumer entity. + +To make sure your plugin is being loaded by Kong, you can start Kong with a +`debug` log level: + + log_level = debug + +or: + + KONG_LOG_LEVEL=debug + +Then, you should see the following log for each plugin being loaded: + + [debug] Loading plugin + + +[Back to TOC](#table-of-contents) + +--- + +## Removing a plugin + +There are three steps to completely remove a plugin. + +1. Remove the plugin from your Kong Service or Route configuration. Make sure + that it is no longer applied globally nor for any Service, Route, or + consumer. This has to be done only once for the entire Kong cluster, no + restart/reload required. This step in itself will make that the plugin is + no longer in use. But it remains available and it is still possible to + re-apply the plugin. + +2. Remove the plugin from the `plugins` directive (on each Kong node). + Make sure to have completed step 1 before doing so. After this step + it will be impossible for anyone to re-apply the plugin to any Kong + Service, Route, Consumer, or even globally. This step requires to + restart/reload the Kong node to take effect. + +3. To remove the plugin thoroughly, delete the plugin-related files from + each of the Kong nodes. Make sure to have completed step 2, including + restarting/reloading Kong, before deleting the files. If you used LuaRocks + to install the plugin, you can do `luarocks remove ` to remove + it. + +[Back to TOC](#table-of-contents) + +--- + +## Distributing your plugin + +The preferred way to do so is to use [LuaRocks](https://luarocks.org/), a +package manager for Lua modules. It calls such modules "rocks". **Your module +does not have to live inside the Kong repository**, but it can be if that's +how you'd like to maintain your Kong setup. + +By defining your modules (and their eventual dependencies) in a [rockspec] +file, you can install those modules on your platform via LuaRocks. You can +also upload your module on LuaRocks and make it available to everyone! + +Here is an example rockspec which would use the "builtin" build type to define +modules in Lua notation and their corresponding file: + + +For an example see the [Kong plugin template][plugin-template], for more info +about the format see the LuaRocks [documentation on rockspecs][rockspec]. + +[Back to TOC](#table-of-contents) + +--- + +## Troubleshooting + +Kong can fail to start because of a misconfigured custom plugin for several +reasons: + +* "plugin is in use but not enabled" -> You configured a custom plugin from + another node, and that the plugin configuration is in the database, but the + current node you are trying to start does not have it in its `plugins` + directive. To resolve, add the plugin's name to the node's `plugins` + directive. + +* "plugin is enabled but not installed" -> The plugin's name is present in the + `plugins` directive, but that Kong is unable to load the `handler.lua` + source file from the file system. To resolve, make sure that the + [lua_package_path](/enterprise/{{page.kong_version}}/property-reference/#development-miscellaneous-section) + directive is properly set to load this plugin's Lua sources. + +* "no configuration schema found for plugin" -> The plugin is installed, + enabled in the `plugins` directive, but Kong is unable to load the + `schema.lua` source file from the file system. To resolve, make sure that + the `schema.lua` file is present alongside the plugin's `handler.lua` file. + +[Back to TOC](#table-of-contents) + +--- + +[rockspec]: https://github.com/keplerproject/luarocks/wiki/Creating-a-rock +[plugin-template]: https://github.com/Kong/kong-plugin diff --git a/app/enterprise/1.3-x/plugin-development/entities-cache.md b/app/enterprise/1.3-x/plugin-development/entities-cache.md new file mode 100644 index 000000000000..677e9227597e --- /dev/null +++ b/app/enterprise/1.3-x/plugin-development/entities-cache.md @@ -0,0 +1,349 @@ +--- +title: Plugin Development - Caching Custom Entities +book: plugin_dev +chapter: 7 +--- + +## Introduction + +Your plugin may need to frequently access custom entities (explained in the +[previous chapter]({{page.book.previous}})) on every request and/or response. +Usually, loading them once and caching them in-memory dramatically improves +the performance while making sure the datastore is not stressed with an +increased load. + +Think of an api-key authentication plugin that needs to validate the api-key on +every request, thus loading the custom credential object from the datastore on +every request. When the client provides an api-key along with the request, +normally you would query the datastore to check if that key exists, and then +either block the request or retrieve the Consumer ID to identify the user. This +would happen on every request, and it would be very inefficient: + +* Querying the datastore adds latency on every request, making the request + processing slower. +* The datastore would also be affected by an increase of load, potentially + crashing or slowing down, which in turn would affect every Kong + node. + +To avoid querying the datastore every time, we can cache custom entities +in-memory on the node, so that frequent entity lookups don't trigger a +datastore query every time (only the first time), but happen in-memory, which +is much faster and reliable that querying it from the datastore (especially +under heavy load). + +## Modules + +``` +kong.plugins..daos +``` + +## Caching custom entities + +Once you have defined your custom entities, you can cache them in-memory in +your code by using the [kong.cache](/enterprise/{{page.kong_version}}/pdk/#kong-cache) +module provided by the [Plugin Development Kit]: + +``` +local cache = kong.cache +``` + +There are 2 levels of cache: + +1. L1: Lua memory cache - local to an Nginx worker process. + This can hold any type of Lua value. +2. L2: Shared memory cache (SHM) - local to an Nginx node, but shared between + all the workers. This can only hold scalar values, and hence requires + (de)serialization of a more complex types such as Lua tables. + +When data is fetched from the database, it will be stored in both caches. +If the same worker process requests the data again, it will retrieve the +previously deserialized data from the Lua memory cache. If a different +worker within the same Nginx node requests that data, it will find the data +in the SHM, deserialize it (and store it in its own Lua memory cache) and +then return it. + +This module exposes the following functions: + +Function name | Description +----------------------------------------------|--------------------------- +`value, err = cache:get(key, opts?, cb, ...)` | Retrieves the value from the cache. If the cache does not have value (miss), invokes `cb` in protected mode. `cb` must return one (and only one) value that will be cached. It *can* throw errors, as those will be caught and properly logged by Kong, at the `ngx.ERR` level. This function **does** cache negative results (`nil`). As such, one must rely on its second argument `err` when checking for errors. +`ttl, err, value = cache:probe(key)` | Checks if a value is cached. If it is, returns its remaining ttl. It not, returns `nil`. The value being cached can also be a negative caching. The third return value is the value being cached itself. +`cache:invalidate_local(key)` | Evicts a value from the node's cache. +`cache:invalidate(key)` | Evicts a value from the node's cache **and** propagates the eviction events to all other nodes in the cluster. +`cache:purge()` | Evicts **all** values from the node's cache. + +Bringing back our authentication plugin example, to lookup a credential with a +specific api-key, we would write something similar to: + +```lua +-- handler.lua +local BasePlugin = require "kong.plugins.base_plugin" + + +local kong = kong + + +local function load_credential(key) + local credential, err = kong.db.keyauth_credentials:select_by_key(key) + if not credential then + return nil, err + end + return credential +end + + +local CustomHandler = BasePlugin:extend() + + +CustomHandler.VERSION = "1.0.0" +CustomHandler.PRIORITY = 1010 + + +function CustomHandler:new() + CustomHandler.super.new(self, "my-custom-plugin") +end + + +function CustomHandler:access(config) + CustomHandler.super.access(self) + + -- retrieve the apikey from the request querystring + local key = kong.request.get_query_arg("apikey") + + local credential_cache_key = kong.db.keyauth_credentials:cache_key(key) + + -- We are using cache.get to first check if the apikey has been already + -- stored into the in-memory cache. If it's not, then we lookup the datastore + -- and return the credential object. Internally cache.get will save the value + -- in-memory, and then return the credential. + local credential, err = kong.cache:get(credential_cache_key, nil, + load_credential, credential_cache_key) + if err then + kong.log.err(err) + return kong.response.exit(500, { + message = "Unexpected error" + }) + end + + if not credential then + -- no credentials in cache nor datastore + return kong.response.exit(401, { + message = "Invalid authentication credentials" + }) + end + + -- set an upstream header if the credential exists and is valid + kong.service.request.set_header("X-API-Key", credential.apikey) +end + + +return CustomHandler +``` + +Note that in the above example, we use various components from the [Plugin +Development Kit] to interact with the request, cache module, or even produce a +response from our plugin. + +Now, with the above mechanism in place, once a Consumer has made a request with +their API key, the cache will be considered warm and subsequent requests won't +result in a database query. + +The cache is used in several places in the [Key-Auth plugin handler](https://github.com/Kong/kong/blob/master/kong/plugins/key-auth/handler.lua). +Give that file a look in order to see how an official plugin uses the cache. + +### Updating or deleting a custom entity + +Every time a cached custom entity is updated or deleted in the datastore (i.e. +using the Admin API), it creates an inconsistency between the data in the +datastore, and the data cached in the Kong nodes' memory. To avoid this +inconsistency, we need to evict the cached entity from the in-memory store and +force Kong to request it again from the datastore. We refer to this process as +cache invalidation. + +--- + +## Cache invalidation for your entities + +If you wish that your cached entities be invalidated upon a CRUD operation +rather than having to wait for them to reach their TTL, you have to follow a +few steps. This process can be automated for most entities, but manually +subscribing to some CRUD events might be required to invalidate some entities +with more complex relationships. + +### Automatic cache invalidation + +Cache invalidation can be provided out of the box for your entities if you rely +on the `cache_key` property of your entity's schema. For example, in the +following schema: + +```lua +local typedefs = require "kong.db.schema.typedefs" + + +return { + -- this plugin only results in one custom DAO, named `keyauth_credentials`: + keyauth_credentials = { + name = "keyauth_credentials", -- the actual table in the database + endpoint_key = "key", + primary_key = { "id" }, + cache_key = { "key" }, + generate_admin_api = true, + fields = { + { + -- a value to be inserted by the DAO itself + -- (think of serial id and the uniqueness of such required here) + id = typedefs.uuid, + }, + { + -- also interted by the DAO itself + created_at = typedefs.auto_timestamp_s, + }, + { + -- a foreign key to a consumer's id + consumer = { + type = "foreign", + reference = "consumers", + default = ngx.null, + on_delete = "cascade", + }, + }, + { + -- a unique API key + key = { + type = "string", + required = false, + unique = true, + auto = true, + }, + }, + }, + }, +} +``` + +We can see that we declare the cache key of this API key entity to be its +`key` attribute. We use `key` here because it has a unique constraints +applied to it. Hence, the attributes added to `cache_key` should result in +a unique combination, so that no two entities could yield the same cache key. + +Adding this value allows you to use the following function on the DAO of that +entity: + +```lua +cache_key = kong.db.:cache_key(arg1, arg2, arg3, ...) +``` + +Where the arguments must be the attributes specified in your schema's +`cache_key` property, in the order they were specified. This function then +computes a string value `cache_key` that is ensured to be unique. + +For example, if we were to generate the cache_key of an API key: + +```lua +local cache_key = kong.db.keyauth_credentials:cache_key("abcd") +``` + +This would produce a cache_key for the API key `"abcd"` (retrieved from one +of the query's arguments) that we can the use to retrieve the key from the +cache (or fetch from the database if the cache is a miss): + +```lua +local key = kong.request.get_query_arg("apikey") +local cache_key = kong.db.keyauth_credentials:cache_key(key) + +local credential, err = kong.cache:get(cache_key, nil, load_entity_key, apikey) +if err then + kong.log.err(err) + return kong.response.exit(500, { message = "Unexpected error" }) +end + +if not credential then + return kong.response.exit(401, { message = "Invalid authentication credentials" }) +end + + +-- do something with the credential +``` + +If the `cache_key` is generated like so and specified in an entity's schema, +cache invalidation will be an automatic process: every CRUD operation that +affects this API key will be make Kong generate the affected `cache_key`, and +broadcast it to all of the other nodes on the cluster so they can evict +that particular value from their cache, and fetch the fresh value from the +datastore on the next request. + +When a parent entity is receiving a CRUD operation (e.g. the Consumer owning +this API key, as per our schema's `consumer_id` attribute), Kong performs the +cache invalidation mechanism for both the parent and the child entity. + +**Note**: Be aware of the negative caching that Kong provides. In the above +example, if there is no API key in the datastore for a given key, the cache +module will store the miss just as if it was a hit. This means that a +"Create" event (one that would create an API key with this given key) is also +propagated by Kong so that all nodes that stored the miss can evict it, and +properly fetch the newly created API key from the datastore. + +See the [Clustering Guide](/enterprise/{{page.kong_version}}/clustering/) to ensure +that you have properly configured your cluster for such invalidation events. + +### Manual cache invalidation + +In some cases, the `cache_key` property of an entity's schema is not flexible +enough, and one must manually invalidate its cache. Reasons for this could be +that the plugin is not defining a relationship with another entity via the +traditional `foreign = "parent_entity:parent_attribute"` syntax, or because +it is not using the `cache_key` method from its DAO, or even because it is +somehow abusing the caching mechanism. + +In those cases, you can manually setup your own subscriber to the same +invalidation channels Kong is listening to, and perform your own, custom +invalidation work. + +To listen on invalidation channels inside of Kong, implement the following in +your plugin's `init_worker` handler: + +```lua +function MyCustomHandler:init_worker() + -- listen to all CRUD operations made on Consumers + kong.worker_events.register(function(data) + + end, "crud", "consumers") + + -- or, listen to a specific CRUD operation only + kong.worker_events.register(function(data) + kong.log.inspect(data.operation) -- "update" + kong.log.inspect(data.old_entity) -- old entity table (only for "update") + kong.log.inspect(data.entity) -- new entity table + kong.log.inspect(data.schema) -- entity's schema + end, "crud", "consumers:update") +end +``` + +Once the above listeners are in place for the desired entities, you can perform +manual invalidations of any entity that your plugin has cached as you wish so. +For instance: + +```lua +kong.worker_events.register(function(data) + if data.operation == "delete" then + local cache_key = data.entity.id + kong.cache:invalidate("prefix:" .. cache_key) + end +end, "crud", "consumers") +``` + +## Extending the Admin API + +As you are probably aware, the [Admin API] is where Kong users communicate with +Kong to setup their APIs and plugins. It is likely that they also need to be +able to interact with the custom entities you implemented for your plugin (for +example, creating and deleting API keys). The way you would do this is by +extending the Admin API, which we will detail in the next chapter: +[Extending the Admin API]({{page.book.next}}). + +--- + +Next: [Extending the Admin API ›]({{page.book.next}}) + +[Admin API]: /enterprise/{{page.kong_version}}/admin-api/ +[Plugin Development Kit]: /enterprise/{{page.kong_version}}/pdk diff --git a/app/enterprise/1.3-x/plugin-development/file-structure.md b/app/enterprise/1.3-x/plugin-development/file-structure.md new file mode 100644 index 000000000000..240f31bd261e --- /dev/null +++ b/app/enterprise/1.3-x/plugin-development/file-structure.md @@ -0,0 +1,124 @@ +--- +title: Plugin Development - File Structure +book: plugin_dev +chapter: 2 +--- + +
+ Note: This chapter assumes that you are familiar with + Lua. +
+ +## Introduction + +Consider your plugin as a set of [Lua +modules](http://www.lua.org/manual/5.1/manual.html#6.3). Each file described in +this chapter is to be considered as a separate module. Kong will detect and +load your plugin's modules if their names follow this convention: + +``` +kong.plugins.. +``` + +> Your modules of course need to be accessible through your +> [package.path](http://www.lua.org/manual/5.1/manual.html#pdf-package.path) +> variable, which can be tweaked to your needs via the +> [lua_package_path](/enterprise/{{page.kong_version}}/property-reference/#lua_package_path) +> configuration property. +> However, the preferred way of installing plugins is through +> [LuaRocks](https://luarocks.org/), which Kong natively integrates with. +> More on LuaRocks-installed plugins later in this guide. + +To make Kong aware that it has to look for your plugin's modules, you'll have +to add it to the +[plugins](/enterprise/{{page.kong_version}}/property-reference/#plugins) property in +your configuration file, which is a comma-separated list. For example: + +```yaml +plugins = bundled,my-custom-plugin # your plugin name here +``` + +Or, if you don't want to load any of the bundled plugins: + +```yaml +plugins = my-custom-plugin # your plugin name here +``` + +Now, Kong will try to load several Lua modules from the following namespace: + +``` +kong.plugins.my-custom-plugin. +``` + +Some of these modules are mandatory (e.g. `handler.lua`), and some are +optional, and will allow the plugin to implement some extra-functionalities +(e.g. `api.lua` to extend the Admin API endpoints). + +Now let's describe exactly what are the modules you can implement and what +their purpose is. + +--- + +## Basic plugin modules + +In its purest form, a plugin consists of two mandatory modules: + +``` +simple-plugin +├── handler.lua +└── schema.lua +``` + +- **[handler.lua]**: the core of your plugin. It is an interface to implement, in + which each function will be run at the desired moment in the lifecycle of a + request / connection. +- **[schema.lua]**: your plugin probably has to retain some configuration entered + by the user. This module holds the *schema* of that configuration and defines + rules on it, so that the user can only enter valid configuration values. + +--- + +## Advanced plugin modules + +Some plugins might have to integrate deeper with Kong: have their own table in +the database, expose endpoints in the Admin API, etc. Each of those can be +done by adding a new module to your plugin. Here is what the structure of a +plugin would look like if it was implementing all of the optional modules: + +``` +complete-plugin +├── api.lua +├── daos.lua +├── handler.lua +├── migrations +│   ├── init.lua +│   └── 000_base_complete_plugin.lua +└── schema.lua +``` + +Here is the complete list of possible modules to implement and a brief +description of what their purpose is. This guide will go in details to let you +master each one of them. + +| Module name | Required | Description +|:-----------------------|------------|------------ +| **[api.lua]** | No | Defines a list of endpoints to be available in the Admin API to interact with the custom entities handled by your plugin. +| **[daos.lua]** | No | Defines a list of DAOs (Database Access Objects) that are abstractions of custom entities needed by your plugin and stored in the datastore. +| **[handler.lua]** | Yes | An interface to implement. Each function is to be run by Kong at the desired moment in the lifecycle of a request / connection. +| **[migrations/*.lua]** | No | The database migrations (e.g. creation of tables). Migrations are only necessary when your plugin has to store custom entities in the database and interact with them through one of the DAOs defined by [daos.lua]. +| **[schema.lua]** | Yes | Holds the schema of your plugin's configuration, so that the user can only enter valid configuration values. + +The [Key-Auth plugin] is an example of plugin with this file structure. +See [its source code] for more details. + +--- + +Next: [Write custom logic ›]({{page.book.next}}) + +[api.lua]: {{page.book.chapters.admin-api}} +[daos.lua]: {{page.book.chapters.custom-entities}} +[handler.lua]: {{page.book.chapters.custom-logic}} +[schema.lua]: {{page.book.chapters.plugin-configuration}} +[migrations/*.lua]: {{page.book.chapters.custom-entities}} +[Key-Auth plugin]: /hub/kong-inc/key-auth/ +[its source code]: https://github.com/Kong/kong/tree/master/kong/plugins/key-auth diff --git a/app/enterprise/1.3-x/plugin-development/index.md b/app/enterprise/1.3-x/plugin-development/index.md new file mode 100644 index 000000000000..2dfd5555482b --- /dev/null +++ b/app/enterprise/1.3-x/plugin-development/index.md @@ -0,0 +1,37 @@ +--- +title: Plugin Development - Introduction +book: plugin_dev +chapter: 1 +--- + +# What are plugins and how do they integrate with Kong? + +Before going further, it is necessary to briefly explain how Kong is built, +especially how it integrates with Nginx and what Lua has to do with it. + +[lua-nginx-module] enables Lua scripting capabilities in Nginx. Instead of +compiling Nginx with this module, Kong is distributed along with +[OpenResty](https://openresty.org/), which already includes lua-nginx-module. +OpenResty is *not* a fork of Nginx, but a bundle of modules extending its +capabilities. + +Hence, Kong is a Lua application designed to load and execute Lua modules +(which we more commonly refer to as "*plugins*") and provides an entire +development environment for them, including an SDK, database abstractions, +migrations, and more. + +Plugins consist of Lua modules interacting with the request/response objects or +streams via the **Plugin Development Kit** (or "PDK") to implement arbitrary logic. +The PDK is a set of Lua functions that a plugin can use to facilitate interactions +between plugins and the core (or other components) of Kong. + +This guide will explore in detail the structure of plugins, what they can +extend, and how to distribute and install them. For a complete reference of the +PDK, see the [Plugin Development Kit] reference. + +--- + +Next: [File structure of a plugin ›]({{page.book.next}}) + +[lua-nginx-module]: https://github.com/openresty/lua-nginx-module +[Plugin Development Kit]: /enterprise/{{page.kong_version}}/pdk diff --git a/app/enterprise/1.3-x/plugin-development/plugin-configuration.md b/app/enterprise/1.3-x/plugin-development/plugin-configuration.md new file mode 100644 index 000000000000..18ac7acac0b0 --- /dev/null +++ b/app/enterprise/1.3-x/plugin-development/plugin-configuration.md @@ -0,0 +1,420 @@ +--- +title: Plugin Development - Plugin Configuration +book: plugin_dev +chapter: 4 +--- + +## Introduction + +Most of the time, it makes sense for your plugin to be configurable to answer +all of your users' needs. Your plugin's configuration is stored in the +datastore for Kong to retrieve it and pass it to your +[handler.lua]({{page.book.chapters.custom-logic}}) methods when the plugin is +being executed. + +The configuration consists of a Lua table in Kong that we call a **schema**. It +contains key/value properties that the user will set when enabling the plugin +through the [Admin API]. Kong provides you with a way of validating the user's +configuration for your plugin. + +Your plugin's configuration is being verified against your schema when a user +issues a request to the [Admin API] to enable or update a plugin on a given +Service, Route and/or Consumer. + +For example, a user performs the following request: + +```bash +$ curl -X POST http://kong:8001/services//plugins \ + -d "name=my-custom-plugin" \ + -d "config.foo=bar" +``` + +If all properties of the `config` object are valid according to your schema, +then the API would return `201 Created` and the plugin would be stored in the +database along with its configuration: +```lua +{ + foo = "bar" +} + ``` + +If the configuration is not valid, the Admin API would return `400 Bad Request` +and the appropriate error messages. + +## Module + +``` +kong.plugins..schema +``` + +## schema.lua specifications + +This module is to return a Lua table with properties that will define how your +plugins can later be configured by users. Available properties are: + +| Property name | Lua type | Description +|-----------------|------------|------------ +| `name` | `string` | Name of the plugin, e.g. `key-auth`. +| `fields` | `table` | Array of field definitions. +| `entity_checks` | `function` | Array of conditional entity level validation checks. + + +All the plugins inherit some default fields which are: + +| Field name | Lua type | Description +|-----------------|------------|------------ +| `id` | `string` | Auto-generated plugin id. +| `name` | `string` | Name of the plugin, e.g. `key-auth`. +| `created_at` | `number` | Creation time of the plugin configuration (seconds from epoch). +| `route` | `table` | Route to which plugin is bound, if any. +| `service` | `table` | Service to which plugin is bound, if any. +| `consumer` | `table` | Consumer to which plugin is bound when possible, if any. +| `run_on` | `string` | Determines on which node the plugin should run on service mesh. +| `protocols` | `table` | The plugin will run on specified protocol(s). +| `enabled` | `boolean` | Whether or not the plugin is enabled. +| `tags` | `table` | The tags for the plugin. + +In most of the cases you can ignore most of those and use the defaults. Or let the user +specify value when enabling a plugin. + +Here is an example of a potential `schema.lua` file (with some overrides applied): + +```lua +local typedefs = require "kong.db.schema.typedefs" + + +return { + name = "", + fields = { + { + -- this plugin will only be applied to Services or Routes + consumer = typedefs.no_consumer + }, + { + -- this plugin will only be executed on the first Kong node + -- if a request comes from a service mesh (when acting as + -- a non-service mesh gateway, the nodes are always considered + -- to be "first". + run_on = typedefs.run_on_first + }, + { + -- this plugin will only run within Nginx HTTP module + protocols = typedefs.protocols_http + }, + { + config = { + type = "record", + fields = { + -- Describe your plugin's configuration's schema here. + }, + }, + }, + }, + entity_checks = { + -- Describe your plugin's entity validation rules + }, +} +``` + +## Describing your configuration schema + +The `config.fields` property of your `schema.lua` file describes the schema of your +plugin's configuration. It is a flexible array of field definitions where each field +is a valid configuration property for your plugin, describing the rules for that +property. For example: + +```lua +{ + name = "", + fields = { + config = { + type = "record", + fields = { + { + some_string = { + type = "string", + required = false, + }, + }, + { + some_boolean = { + type = "boolean", + default = false, + }, + }, + { + some_array = { + type = "array", + elements = { + type = "string", + one_of = { + "GET", + "POST", + "PUT", + "DELETE", + }, + }, + }, + }, + }, + }, + }, +} +``` + +Here is the list of some common (not all) accepted rules for a property (see the fields table above for examples): + +| Rule | Description +|--------------------|---------------------------- +| `type` | The type of a property. +| `required` | Whether or not the property is required +| `default` | The default value for the property when not specified +| `elements` | Field definition of `array` or `set` elements. +| `keys` | Field definition of `map` keys. +| `values` | Field definition of `map` values. +| `fields` | Field definition(s) of `record` fields. + +There are many more, but the above are commonly used. + +You can also add field validators, to mention a few: + +| Rule | Description +|--------------------|---------------------------- +| `between` | Checks that the input number is between allowed values. +| `eq` | Checks the equality of the input to allowed value. +| `ne` | Checks the inequality of the input to allowed value. +| `gt` | Checks that the number is greater than given value. +| `len_eq` | Checks that the input string length is equal to the given value. +| `len_min` | Checks that the input string length is at least the given value. +| `len_max` | Checks that the input string length is at most the given value. +| `match` | Checks that the input string matches the given Lua pattern. +| `not_match` | Checks that the input string doesn't match the given Lua pattern. +| `match_all` | Checks that the input string matches all the given Lua patterns. +| `match_none` | Checks that the input string doesn't match any of the given Lua patterns. +| `match_any` | Checks that the input string matches any of the given Lua patterns. +| `starts_with` | Checks that the input string starts with a given value. +| `one_of` | Checks that the input string is one of the accepted values. +| `contains` | Checks that the input array contains the given value. +| `is_regex` | Checks that the input string is a valid regex pattern. +| `custom_validator` | A custom validation function written in Lua. + +There are some additional validators, but you get a good idea how you can specify validation +rules on fields from the above table. + +--- + +### Examples + +This `schema.lua` file is for the [key-auth](/hub/kong-inc/key-auth/) plugin: + +```lua +-- schema.lua +local typedefs = require "kong.db.schema.typedefs" + + +return { + name = "key-auth", + fields = { + { + consumer = typedefs.no_consumer + }, + { + run_on = typedefs.run_on_first + }, + { + protocols = typedefs.protocols_http + }, + { + config = { + type = "record", + fields = { + { + key_names = { + type = "array", + required = true, + elements = typedefs.header_name, + default = { + "apikey", + }, + }, + }, + { + hide_credentials = { + type = "boolean", + default = false, + }, + }, + { + anonymous = { + type = "string", + uuid = true, + legacy = true, + }, + }, + { + key_in_body = { + type = "boolean", + default = false, + }, + }, + { + run_on_preflight = { + type = "boolean", + default = true, + }, + }, + }, + }, + }, + }, +} +``` + +Hence, when implementing the `access()` function of your plugin in +[handler.lua]({{page.book.chapters.custom-logic}}) and given that the user +enabled the plugin with the default values, you'd have access to: + +```lua +-- handler.lua +local BasePlugin = require "kong.plugins.base_plugin" + + +local kong = kong + + +local CustomHandler = BasePlugin:extend() + + +CustomHandler.VERSION = "1.0.0" +CustomHandler.PRIORITY = 10 + + +function CustomHandler:new() + CustomHandler.super.new(self, "my-custom-plugin") +end + + +function CustomHandler:access(config) + CustomHandler.super.access(self) + + kong.log.inspect(config.key_names) -- { "apikey" } + kong.log.inspect(config.hide_credentials) -- false +end + + +return CustomHandler +``` + +Note that the above example uses the +[kong.log.inspect](/enterprise/{{page.kong_version}}/pdk/kong.log/#kong_log_inspect) +function of the [Plugin Development Kit] to print out those values to the Kong +logs. + +--- + +A more complex example, which could be used for an eventual logging plugin: + +```lua +-- schema.lua +local typedefs = require "kong.db.schema.typedefs" + + +return { + name = "my-custom-plugin", + fields = { + { + config = { + type = "record", + fields = { + { + environment = { + type = "string", + required = true, + one_of = { + "production", + "development", + }, + }, + }, + { + server = { + type = "record", + fields = { + { + host = typedefs.host { + default = "example.com", + }, + }, + { + port = { + type = "number", + default = 80, + between = { + 0, + 65534 + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, +} +``` + +Such a configuration will allow a user to post the configuration to your plugin +as follows: + +```bash +$ curl -X POST http://kong:8001/services//plugins \ + -d "name=my-custom-plugin" \ + -d "config.environment=development" \ + -d "config.server.host=http://localhost" +``` + +And the following will be available in +[handler.lua]({{page.book.chapters.custom-logic}}): + +```lua +-- handler.lua +local BasePlugin = require "kong.plugins.base_plugin" + + +local kong = kong + + +local CustomHandler = BasePlugin:extend() + + +CustomHandler.VERSION = "1.0.0" +CustomHandler.PRIORITY = 10 + + +function CustomHandler:new() + CustomHandler.super.new(self, "my-custom-plugin") +end + +function CustomHandler:access(config) + CustomHandler.super.access(self) + + kong.log.inspect(config.environment) -- "development" + kong.log.inspect(config.server.host) -- "http://localhost" + kong.log.inspect(config.server.port) -- 80 +end + + +return CustomHandler +``` + +You can also see a real-world example of schema in [the Key-Auth plugin source code]. + +--- + +Next: [Accessing the Datastore ›]({{page.book.next}}) + +[Admin API]: /enterprise/{{page.kong_version}}/admin-api +[Plugin Development Kit]: /enterprise/{{page.kong_version}}/pdk +[the Key-Auth plugin source code]: https://github.com/Kong/kong/blob/master/kong/plugins/key-auth/schema.lua diff --git a/app/enterprise/1.3-x/plugin-development/tests.md b/app/enterprise/1.3-x/plugin-development/tests.md new file mode 100644 index 000000000000..c94392339c74 --- /dev/null +++ b/app/enterprise/1.3-x/plugin-development/tests.md @@ -0,0 +1,108 @@ +--- +title: Plugin Development - Writing tests +book: plugin_dev +chapter: 9 +toc: false +--- + +## Introduction + +If you are serious about your plugins, you probably want to write tests for it. +Unit testing Lua is easy, and [many testing +frameworks](http://lua-users.org/wiki/UnitTesting) are available. However, you +might also want to write integration tests. Again, Kong has your back. + +## Write integration tests + +The preferred testing framework for Kong is +[busted](http://olivinelabs.com/busted/) running with the +[resty-cli](https://github.com/openresty/resty-cli) interpreter, though you are +free to use another one if you wish. In the Kong repository, the busted +executable can be found at `bin/busted`. + +Kong provides you with a helper to start and stop it from Lua in your test +suite: `spec.helpers`. This helper also provides you with ways to insert +fixtures in your datastore before running your tests, as well as dropping it, +and various other helpers. + +If you are writing your plugin in your own repository, you will need to copy +the following files until the Kong testing framework is released: + +- `bin/busted`: the busted executable running with the resty-cli interpreter +- `spec/helpers.lua`: helper functions to start/stop Kong from busted +- `spec/kong_tests.conf`: a configuration file for your running your test Kong instances with the helpers module + +Assuming that the `spec.helpers` module is available in your `LUA_PATH`, you +can use the following Lua code in busted to start and stop Kong: + +```lua +local helpers = require "spec.helpers" + +for _, strategy in helpers.each_strategy() do + describe("my plugin", function() + + local bp = helpers.get_db_utils(strategy) + + setup(function() + local service = bp.services:insert { + name = "test-service", + host = "httpbin.org" + } + + bp.routes:insert({ + hosts = { "test.com" }, + service = { id = service.id } + }) + + -- start Kong with your testing Kong configuration (defined in "spec.helpers") + assert(helpers.start_kong( { plugins = "bundled,my-plugin" })) + + admin_client = helpers.admin_client() + end) + + teardown(function() + if admin_client then + admin_client:close() + end + + helpers.stop_kong() + end) + + before_each(function() + proxy_client = helpers.proxy_client() + end) + + after_each(function() + if proxy_client then + proxy_client:close() + end + end) + + describe("thing", function() + it("should do thing", function() + -- send requests through Kong + local res = proxy_client:get("/get", { + headers = { + ["Host"] = "test.com" + } + }) + + local body = assert.res_status(200, res) + + -- body is a string containing the response + end) + end) + end) +end +``` + +> Reminder: With the test Kong configuration file, Kong is running with +its proxy listening on port 9000 (HTTP), 9443 (HTTPS) +and Admin API on port 9001. + +If you want to see a real-world example, give a look at the +[Key-Auth plugin specs](https://github.com/Kong/kong/tree/master/spec/03-plugins/09-key-auth) + +--- + +Next: [Distribute your plugin ›]({{page.book.next}}) diff --git a/app/enterprise/1.3-x/plugins/allowing-multiple-authentication-methods.md b/app/enterprise/1.3-x/plugins/allowing-multiple-authentication-methods.md new file mode 100644 index 000000000000..218388f6ac0e --- /dev/null +++ b/app/enterprise/1.3-x/plugins/allowing-multiple-authentication-methods.md @@ -0,0 +1,110 @@ +--- +title: Allowing Multiple Authentication Methods +toc: false +--- + +The default behavior for Kong authentication plugins is to require credentials +for all requests without regard for whether a request has been authenticated +via some other plugin. Configuring an anonymous consumer on your authentication +plugins allows you to offer clients multiple options for authentication. + +To begin, [create a Service](/enterprise/{{page.kong_version}}/getting-started/add-service/) and then create three consumers: + +```bash +$ curl -sX POST kong-admin:8001/consumers \ + -H "Content-Type: application/json" \ + --data '{"username": "anonymous"}' + +{"created_at":1517528237000,"username":"anonymous","id":"d955c0cb-1a6e-4152-9440-414ebb8fee8a"} + +$ curl -sX POST kong-admin:8001/consumers \ + -H "Content-Type: application/json" \ + --data '{"username": "medvezhonok"}' + +{"created_at":1517528259000,"username":"medvezhonok","id":"b3c95318-a932-4bb2-9d74-1298a3ffc87c"} + +$ curl -sX POST kong-admin:8001/consumers \ + -H "Content-Type: application/json" \ + --data '{"username": "ezhik"}' + +{"created_at":1517528266000,"username":"ezhik","id":"47e74a17-dc08-4786-a8cf-d8e4f38a5459"} +``` + +The `anonymous` consumer does not correspond to any real user, and will only serve as a fallback. + +Next, we add both Key Auth and Basic Auth plugins to our consumer, and set the anonymous fallback to the consumer we created earlier. + +```bash +$ curl -sX POST kong-admin:8001/apis/example-api/plugins/ \ + -H "Content-Type: application/json" \ + --data '{"name": "key-auth", "config": { "hide_credentials": true, "anonymous": "d955c0cb-1a6e-4152-9440-414ebb8fee8a"} }' + +{"created_at":1517528304000,"config":{"key_in_body":false,"hide_credentials":true,"anonymous":"d955c0cb-1a6e-4152-9440-414ebb8fee8a","run_on_preflight":true,"key_names":["apikey"]},"id":"bb884f7b-4e48-4166-8c80-c858b5a4c357","name":"key-auth","api_id":"a2a168a8-4491-4fe1-9426-cde3b5fcd45b","enabled":true} + +$ curl -sX POST kong-admin:8001/apis/example-api/plugins/ \ + -H "Content-Type: application/json" \ + --data '{"name": "basic-auth", "config": { "hide_credentials": true, "anonymous": "d955c0cb-1a6e-4152-9440-414ebb8fee8a"} }' + +{"created_at":1517528499000,"config":{"hide_credentials":true,"anonymous":"d955c0cb-1a6e-4152-9440-414ebb8fee8a"},"id":"e5a40543-debe-4225-a879-a54901368e6d","name":"basic-auth","api_id":"a2a168a8-4491-4fe1-9426-cde3b5fcd45b","enabled":true} +``` + +If using [OpenID Connect](/enterprise/{{page.kong_version}}/plugins/openid-connect), you must also set `config.consumer_claim` along with `anonymous`, as setting `anonymous` alone will not map that consumer. + +At this point unauthenticated requests and requests with invalid credentials are still allowed. The anonymous consumer is allowed, and will be applied to any request that does not pass a set of credentials associated with some other consumer. + +```bash +$ curl -s example.com:8000/user-agent + +{"user-agent": "curl/7.58.0"} + +$ curl -s example.com:8000/user-agent?apikey=nonsense + +{"user-agent": "curl/7.58.0"} +``` + +We'll now add a Key Auth credential for one consumer, and a Basic Auth credential for another. + +```bash +$ curl -sX POST kong-admin:8001/consumers/medvezhonok/basic-auth \ + -H "Content-Type: application/json" \ + --data '{"username": "medvezhonok", "password": "hunter2"}' + +{"created_at":1517528647000,"id":"bb350b87-f0d2-4605-b997-e28a116d8b6d","username":"medvezhonok","password":"f239a0404351d7170201e7f92fa9b3159e47bb01","consumer_id":"b3c95318-a932-4bb2-9d74-1298a3ffc87c"} + +$ curl -sX POST kong-admin:8001/consumers/ezhik/key-auth \ + -H "Content-Type: application/json" \ + --data '{"key": "hunter3"}' + +{"id":"06412d6e-8d41-47f7-a911-3c821ec98f1b","created_at":1517528730000,"key":"hunter3","consumer_id":"47e74a17-dc08-4786-a8cf-d8e4f38a5459"} + +``` + +Lastly, we add a Request Terminator to the anonymous consumer. + +```bash +$ curl -sX POST kong-admin:8001/consumers/d955c0cb-1a6e-4152-9440-414ebb8fee8a/plugins/ \ + -H "Content-Type: application/json" \ + --data '{"name": "request-termination", "config": { "status_code": 401, "content_type": "application/json; charset=utf-8", "body": "{\"error\": \"Authentication required\"}"} }' + +{"created_at":1517528791000,"config":{"status_code":401,"content_type":"application\/json; charset=utf-8","body":"{\"error\": \"Authentication required\"}"},"id":"21fc5f6f-363f-4d79-b533-ce26d4478879","name":"request-termination","enabled":true,"consumer_id":"d955c0cb-1a6e-4152-9440-414ebb8fee8a"} +``` + +Requests with missing or invalid credentials are now rejected, whereas authorized requests using either authentication method are allowed. + +```bash +$ curl -s example.com:8000/user-agent?apikey=nonsense + +{"error": "Authentication required"} + +$ curl -s example.com:8000/user-agent + +{"error": "Authentication required"} + +$ curl -s example.com:8000/user-agent?apikey=hunter3 + +{"user-agent": "curl/7.58.0"} + +$ curl -s example.com:8000/user-agent -u medvezhonok:hunter2 + +{"user-agent": "curl/7.58.0"} +``` diff --git a/app/enterprise/1.3-x/plugins/canary-release.md b/app/enterprise/1.3-x/plugins/canary-release.md new file mode 100644 index 000000000000..3d8bda2bbaea --- /dev/null +++ b/app/enterprise/1.3-x/plugins/canary-release.md @@ -0,0 +1,3 @@ +--- +redirect_to: /hub/kong-inc/canary +--- diff --git a/app/enterprise/1.3-x/plugins/degraphql.md b/app/enterprise/1.3-x/plugins/degraphql.md new file mode 100644 index 000000000000..5c6fb3a6ea4f --- /dev/null +++ b/app/enterprise/1.3-x/plugins/degraphql.md @@ -0,0 +1,3 @@ +--- +redirect_to: /hub/kong-inc/degraphql +--- diff --git a/app/enterprise/1.3-x/plugins/forward-proxy.md b/app/enterprise/1.3-x/plugins/forward-proxy.md new file mode 100644 index 000000000000..0317bd2ad718 --- /dev/null +++ b/app/enterprise/1.3-x/plugins/forward-proxy.md @@ -0,0 +1,3 @@ +--- +redirect_to: /hub/kong-inc/forward-proxy +--- diff --git a/app/enterprise/1.3-x/plugins/graphql-proxy-cache-advanced.md b/app/enterprise/1.3-x/plugins/graphql-proxy-cache-advanced.md new file mode 100644 index 000000000000..c2f739cfe927 --- /dev/null +++ b/app/enterprise/1.3-x/plugins/graphql-proxy-cache-advanced.md @@ -0,0 +1,3 @@ +--- +redirect_to: /hub/kong-inc/graphql-proxy-cache-advanced +--- diff --git a/app/enterprise/1.3-x/plugins/graphql-rate-limiting-advanced.md b/app/enterprise/1.3-x/plugins/graphql-rate-limiting-advanced.md new file mode 100644 index 000000000000..23c5754313a2 --- /dev/null +++ b/app/enterprise/1.3-x/plugins/graphql-rate-limiting-advanced.md @@ -0,0 +1,337 @@ +--- +title: GraphQL Rate Limiting Advanced +--- + +The GraphQL Rate limiting advanced plugin is an extension of the +enterprise rate-limiting plugin that provides rate-limiting for +GraphQL queries. + +Due to the nature of client-specified GraphQL queries, the same HTTP request +to the same URL with the same method can vary greatly in cost depending on the +semantics of the GraphQL operation in the body. + +A common pattern to protect your GraphQL API is then to analyze and +assign costs to incoming GraphQL queries and rate limit the consumer's +cost for a given time window. + +## Configuration + +This plugin is configured as the rate-limiting-advanced plugin, plus some additional +options related to graphql: + +| Form Parameter | default | description +|-------------------|-----------|------------- +| `cost_strategy` | `default` | Strategy to use to evaluate query costs. +| `max_cost` | `0` | A defined maximum cost per query. 0 means unlimited. +| `score_factor` | `1.0` | A scoring factor to multiply (or divide) the cost. + + +## Costs in GraphQL queries + +GraphQL query costs are evaluated by introspecting the endpoint's graphql schema +and applying cost decoration to parts of the schema tree. + +Initially all nodes start with zero cost, with any operation at cost 1. +Add rate-limiting constraints on any subtree. If subtree omitted, then +rate-limit window applies on the whole tree (any operation). + +Since there are many ways of approximating the cost of a graphql query, the +plugin exposes two strategies: `default` and `node_quantifier`. + +The following example queries can be run on this [SWAPI playground]. + +[SWAPI playground]: https://swapi-graphql.eskerda.now.sh + +### `default` + +The default strategy is meant as a good middle ground for general graphql +queries, where it's difficult to assert a clear cost strategy, so every operation +has a cost of 1. + +``` +query { # + 1 + allPeople { # + 1 + people { # + 1 + name # + 1 + } + } +} + +# total cost: 4 +``` + +Default node costs can be defined by decorating the schema: + +| `type_path` | `mul_arguments` | `mul_constant` | `add_arguments` | `add_constant` +|---------------------------|-------------------|-------------------|-------------------|--------------- +| Query.allPeople | ["first"] | 1 | [] | 1 +| Person.vehicleConnection | ["first"] | 1 | [] | 1 + + +``` +query { # + 1 + allPeople(first:20) { # * 20 + 1 + people { # + 1 + name # + 1 + vehicleConnection(first:10) { # * 10 + 1 + vehicles { # + 1 + id # + 1 + name # + 1 + cargoCapacity # + 1 + } + } + } + } +} + +# total cost: ((((4 * 10 + 1) + 1) + 1) * 20 + 1) + 1 = 862 +``` + +Generally speaking, vehicleConnection weight (4) is applied 10 times, and the +total weight of it (40) 20 times, which gives us a rough 800. + +Cost constants can be atomically defined as: + +| `type_path` | `mul_arguments` | `mul_constant` | `add_arguments` | `add_constant` +|---------------------------|-------------------|-------------------|-------------------|--------------- +| Query.allPeople | ["first"] | 2 | [] | 2 +| Person.vehicleConnection | ["first"] | 1 | [] | 5 +| Vehicle.name | [] | 1 | [] | 8 + +On this example, `Vehicle.name` and `Person.vehicleConnection` have specific +weights of 8 and 5 respectively. `allPeople` weights 2, and also has double +its weight when multiplied by arguments. + +``` +query { # + 1 + allPeople(first:20) { # 2 * 20 + 2 + people { # + 1 + name # + 1 + vehicleConnection(first:10) { # * 10 + 5 + vehicles { # + 1 + id # + 1 + name # + 8 + cargoCapacity # + 1 + } + } + } + } +} + +# total cost: ((((11 * 10 + 5) + 1) + 1) * 2 * 20 + 2) + 1 = 4683 +``` + +### `node_quantifier` + +This strategy is fit for graphql schemas that enforce quantifier arguments on +any connection, providing a good approximation on the number of nodes visited +for satisfying a query. Any query without decorated quantifiers has a cost of 1. +It is roughly based on [github's Graphql resource limits]. + +[github's Graphql resource limits]: https://developer.github.com/v4/guides/resource-limitations/ + +``` +query { + allPeople(first:100) { # 1 + people { + name + vehicleConnection(first:10) { # 100 + vehicles { + name + filmConnection(first:5) { # 10 * 100 + films{ + title + characterConnection(first:50) { # 5 * 10 * 100 + characters { + name + } + } + } + } + } + } + } + } +} +# total cost: 1 + 100 + 10 * 100 + 5 * 10 * 100 = 6101 +``` + +| `type_path` | `mul_arguments` | `mul_constant` | `add_arguments` | `add_constant` +|---------------------------|-------------------|-------------------|-------------------|--------------- +| Query.allPeople | ["first"] | 1 | [] | 1 +| Person.vehicleConnection | ["first"] | 1 | [] | 1 +| Vehicle.filmConnection | ["first"] | 1 | [] | 1 +| Film.characterConnection | ["first"] | 1 | [] | 1 + +Roughly speaking: + +* allPeople returns 100 nodes, and has been called once +* vehicleConnection returns 10 nodes, and has been called 100 times +* filmConnection returns 5 nodes, and has been called 10 * 100 times +* characterConnection returns 50 nodes, and has been called 5 * 10 * 100 times + + +Specific costs per node can be specified by adding a constant: + +| `type_path` | `mul_arguments` | `mul_constant` | `add_arguments` | `add_constant` +|---------------------------|-------------------|-------------------|-------------------|--------------- +| Query.allPeople | ["first"] | 1 | [] | 1 +| Person.vehicleConnection | ["first"] | 1 | [] | 42 +| Vehicle.filmConnection | ["first"] | 1 | [] | 1 +| Film.characterConnection | ["first"] | 1 | [] | 1 + + +``` +query { + allPeople(first:100) { # 1 + people { + name + vehicleConnection(first:10) { # 100 * 42 + vehicles { + name + filmConnection(first:5) { # 10 * 100 + films{ + title + characterConnection(first:50) { # 5 * 10 * 100 + characters { + name + } + } + } + } + } + } + } + } +} +# total cost: 1 + 100 * 42 + 10 * 100 + 5 * 10 * 100 = 10201 +``` + +## Usage + +The following configuration example targets a GraphQL endpoint at our [SWAPI playground]. + +### Add a GraphQL service + +``` +http -f :8001/services name=example host=swapi-graphql.eskerda.now.sh port=443 protocol=https +http -f :8001/services/example/routes hosts=example.com +``` + +### Enable the plugin on the service + +``` +$ curl -i -X POST http://kong:8001/services/{service}/plugins \ + --data name=rate-limiting-advanced \ + --data config.limit=100,10000 \ + --data config.window_size=60,3600 \ + --data config.sync_rate=10 +``` + +### Decorate gql schema for costs + +Cost decoration schema looks like: + +| Form Parameter | default | description +|-------------------|-----------|------------- +| `type_path | | Path to node to decorate +| `add_constant` | `1` | Node weight when added +| `add_arguments` | `[]` | List of arguments to add to add_constant +| `mul_constant` | `1` | Node weight multiplier value +| `mul_arguments` | `[]` | List of arguments that multiply weight + + +Cost decoration is available on the following routes: + +#### `/services/{service}/graphql-rate-limiting-advanced/costs` + +* GET: list of costs associated to a service schema +* PUT, POST: add a cost to a service schema + + +#### `/graphql-rate-limiting-advanced/costs` + +* GET: list of all costs on any service +* PUT, POST: add a cost to a service schema + + +#### `/graphql-rate-limiting-advanced/costs/{cost_id}` + +* GET: get cost associated by id +* PATCH: modify cost associated by id +* DELETE: delete cost associated by id + + +For example: + +``` +http -f :8001/services/example/graphql-rate-limiting-advanced/costs type_path="Query.allPeople" mul_arguments="first" +http -f :8001/services/example/graphql-rate-limiting-advanced/costs type_path="Person.vehicleConnection" mul_arguments="first" add_constant=42 +http -f :8001/services/example/graphql-rate-limiting-advanced/costs type_path="Vehicle.filmConnection" mul_arguments="first" +http -f :8001/services/example/graphql-rate-limiting-advanced/costs type_path="Film.characterConnection" mul_arguments="first" +``` + +### Changing the default strategy + +``` +$ curl -i -X POST http://kong:8001/services/{service}/plugins \ + --data name=rate-limiting-advanced \ + --data config.limit=100,10000 \ + --data config.window_size=60,3600 \ + --data config.sync_rate=10 \ + --data config.cost_strategy=node_quantifier +``` + +``` +$ curl -i -X PATCH http://kong:8001/plugins/{plugin_id} \ + --data config.cost_strategy=node_quantifier +``` + +### Limit query cost by using `config.max_cost` + +It's usually a good idea to define a maximum cost applied to any query, regardless +if the call is within the rate limits for a consumer. + +By defining a `max_cost` on our service, we are ensuring no query will run with +a cost higher than our set `max_cost`. By default it's set to 0, which means +no limit. + +``` +$ curl -i -X POST http://kong:8001/services/{service}/plugins \ + --data name=rate-limiting-advanced \ + --data config.limit=100,10000 \ + --data config.window_size=60,3600 \ + --data config.sync_rate=10 \ + --data config.max_cost=5000 +``` + +``` +$ curl -i -X PATCH http://kong:8001/plugins/{plugin_id} \ + --data config.max_cost=5000 +``` + +### Using `config.score_factor` to modify costs + +GraphQL query cost depend on multiple factors depending on our resolvers +and the implementation of the schema. Cost on queries, depending on the cost +strategy might turn very high when using quantifiers, or very low with no +quantifiers at all. By using `config.score_factor` the cost can be divided +or multiplied to a certain order of mangitude. + +For example, a `score_factor` of `0.01` will divide the costs by 100, meaning +every cost unit represents 100 nodes. + +``` +$ curl -i -X POST http://kong:8001/services/{service}/plugins \ + --data name=rate-limiting-advanced \ + --data config.limit=100,10000 \ + --data config.window_size=60,3600 \ + --data config.sync_rate=10 \ + --data config.score_factor=0.01 + --data config.max_cost=5000 +``` + +``` +$ curl -i -X PATCH http://kong:8001/plugins/{plugin_id} \ + --data config.score_factor=0.01 +``` diff --git a/app/enterprise/1.3-x/plugins/http-proxy-caching.md b/app/enterprise/1.3-x/plugins/http-proxy-caching.md new file mode 100644 index 000000000000..c48571a29dd7 --- /dev/null +++ b/app/enterprise/1.3-x/plugins/http-proxy-caching.md @@ -0,0 +1,3 @@ +--- +redirect_to: /hub/kong-inc/proxy-cache-advanced +--- diff --git a/app/enterprise/1.3-x/plugins/index.md b/app/enterprise/1.3-x/plugins/index.md new file mode 100644 index 000000000000..6284586b59df --- /dev/null +++ b/app/enterprise/1.3-x/plugins/index.md @@ -0,0 +1,3 @@ +--- +redirect_to: /hub +--- \ No newline at end of file diff --git a/app/enterprise/1.3-x/plugins/jwt-signer.md b/app/enterprise/1.3-x/plugins/jwt-signer.md new file mode 100644 index 000000000000..0a74d595ba34 --- /dev/null +++ b/app/enterprise/1.3-x/plugins/jwt-signer.md @@ -0,0 +1,3 @@ +--- +redirect_to: /hub/kong-inc/jwt-signer +--- \ No newline at end of file diff --git a/app/enterprise/1.3-x/plugins/kafka-upstream.md b/app/enterprise/1.3-x/plugins/kafka-upstream.md new file mode 100644 index 000000000000..90a28a2780c8 --- /dev/null +++ b/app/enterprise/1.3-x/plugins/kafka-upstream.md @@ -0,0 +1,165 @@ +--- +title: Kafka Upstream Plugin +--- + +This plugin transforms requests into [Kafka](https://kafka.apache.org/) messages in a topic. + +## Supported Kong Releases +Kong >= 1.0.x + +## Installation + +Manually download and install: +``` +$ git clone https://github.com/kong/kong-plugin-kafka-upstream.git /path/to/kong/plugins/kong-plugin-kafka-upstream +$ cd /path/to/kong/plugins/kong-plugin-kafka-upstream +$ luarocks make *.rockspec +``` + +In both cases, you need to change your Kong [`plugins` configuration option](https://docs.konghq.com/1.3.x/configuration/#plugins) +to include this plugin: + +``` +plugins = bundled,kafka-upstream +``` + +Or, if you don't want to activate any of the bundled plugins: + +``` +plugins = kafka-upstream +``` + +Then reload kong: + +``` +kong reload +``` + +## Configuration + +### Enabling on a serviceless route + +```bash +$ curl -X POST http://kong:8001/routes/my-route/plugins \ + --data "name=kafka-upstream" \ + --data "config.bootstrap_servers[1].host=localhost" \ + --data "config.bootstrap_servers[1].port=9092" \ + --data "config.topic=kong-upstream" \ + --data "config.timeout=10000" \ + --data "config.keepalive=60000" \ + --data "config.forward_method=false", + --data "config.forward_uri=false", + --data "config.forward_headers=false", + --data "config.forward_body=true", + --data "config.producer_request_acks=1" \ + --data "config.producer_request_timeout=2000" \ + --data "config.producer_request_limits_messages_per_request=200" \ + --data "config.producer_request_limits_bytes_per_request=1048576" \ + --data "config.producer_request_retries_max_attempts=10" \ + --data "config.producer_request_retries_backoff_timeout=100" \ + --data "config.producer_async=true" \ + --data "config.producer_async_flush_timeout=1000" \ + --data "config.producer_async_buffering_limits_messages_in_memory=50000" +``` + +### Parameters + +Here's a list of all the parameters which can be used in this plugin's configuration: + +| Form Parameter | default | description | +| --- | --- | --- | +| `name` | | The name of the plugin to use, in this case `kafka-upstream` | +| `config.bootstrap_servers` | | List of bootstrap brokers in `{host: host, port: port}` format | +| `config.topic` | | Topic to publish to | +| `config.timeout`
Optional | 10000 | Socket timeout in millis | +| `config.keepalive`
Optional | 60000 | Keepalive timeout in millis | +| `config.forward_method`
Optional | false | Include the request method in the message | +| `config.forward_uri`
Optional | false | Include the request uri and uri arguments (AKA query arguments) in the message | +| `config.forward_headers`
Optional | false | Include the request headers in the message | +| `config.forward_body`
Optional | true | Include the request body in the message | +| `config.producer_request_acks`
Optional | 1 | The number of acknowledgments the producer requires the leader to have received before considering a request complete. Allowed values: 0 for no acknowledgments, 1 for only the leader and -1 for the full ISR | +| `config.producer_request_timeout`
Optional | 2000 | Time to wait for a Produce response in millis | +| `config.producer_request_limits_messages_per_request`
Optional | 200 | Maximum number of messages to include into a single Produce request | +| `config.producer_request_limits_bytes_per_request`
Optional | 1048576 | Maximum size of a Produce request in bytes | +| `config.producer_request_retries_max_attempts`
Optional | 10 | Maximum number of retry attempts per single Produce request | +| `config.producer_request_retries_backoff_timeout`
Optional | 100 | Backoff interval between retry attempts in millis | +| `config.producer_async`
Optional | true | Flag to enable asynchronous mode | +| `config.producer_async_flush_timeout`
Optional | 1000 | Maximum time interval in millis between buffer flushes in in asynchronous mode | +| `config.producer_async_buffering_limits_messages_in_memory`
Optional | 50000 | Maximum number of messages that can be buffered in memory in asynchronous mode | + + +## Implementation details + +This plugin makes use of [lua-resty-kafka](https://github.com/doujiang24/lua-resty-kafka) client under the hood. + +When encoding request bodies, several things happen: + +* For requests with content-type header of `application/x-www-form-urlencoded`, `multipart/form-data` + or `application/json`, this plugin will pass the request body "raw" on the `body` attribute, but also try + to return a parse version of those arguments in `body_args`. If this parsing fails, an error message will be + returned and the message will not be sent. +* If the `content-type` is not `text/plain`, `text/html`, `application/xml`, `text/xml` or `application/soap+xml`, + then the body will be base64-encoded to ensure that the message can be sent as JSON. In such a case, + the message will have an extra attribute called `body_base64` set to `true`. + +## Known issues and limitations + +Known limitations: + +1. There is no support for TLS +2. There is no support for Authentication +3. There is no support for message compression +4. The message format is not customizable + +## Quickstart + +The following guidelines assume that both `Kong` and `Kafka` have been installed on your local machine: + +1. Install `kong-plugin-kafka-upstream` as mentioned on the "Installation" section of this readme. + +2. Create `kong-upstream` topic in your `Kafka` cluster: + + ``` + ${KAFKA_HOME}/bin/kafka-topics.sh --create \ + --zookeeper localhost:2181 \ + --replication-factor 1 \ + --partitions 10 \ + --topic kong-upstream + ``` + +3. Create a Service-less Route, and add the `kong-plugin-kafka-upstream` plugin to it: + + ``` + curl -X POST http://localhost:8001/routes \ + --data "name=kafka-upstream" \ + --data "hosts[]=kafka-upstream.dev" + ``` + + ``` + curl -X POST http://localhost:8001/routes/kafka-upstream/plugins \ + --data "name=kafka-upstream" \ + --data "config.bootstrap_servers[1].host=localhost" \ + --data "config.bootstrap_servers[1].port=9092" \ + --data "config.topic=kong-upstream" + ``` + +4. (On a different console) start a Kafka consumer: + + ``` + ${KAFKA_HOME}/bin/kafka-console-consumer.sh \ + --bootstrap-server localhost:9092 \ + --topic kong-upstream \ + --partition 0 \ + --from-beginning \ + --timeout-ms 1000 + ``` + +5. Make sample requests: + + ``` + curl -X POST http://localhost:8000 --header 'Host: kafka-upstream.dev' foo=bar + ``` + + You should receive a `200 { message: "message sent" }` response, and should see the request bodies appear on + the Kafka consumer console you started on the previous step. + diff --git a/app/enterprise/1.3-x/plugins/ldap-authentication-advanced.md b/app/enterprise/1.3-x/plugins/ldap-authentication-advanced.md new file mode 100644 index 000000000000..ed6d9d740a6d --- /dev/null +++ b/app/enterprise/1.3-x/plugins/ldap-authentication-advanced.md @@ -0,0 +1,3 @@ +--- +redirect_to: /hub/kong-inc/ldap-auth-advanced +--- diff --git a/app/enterprise/1.3-x/plugins/oauth2-introspection.md b/app/enterprise/1.3-x/plugins/oauth2-introspection.md new file mode 100644 index 000000000000..b9689de1bc69 --- /dev/null +++ b/app/enterprise/1.3-x/plugins/oauth2-introspection.md @@ -0,0 +1,3 @@ +--- +redirect_to: /hub/kong-inc/oauth2-introspection +--- diff --git a/app/enterprise/1.3-x/plugins/oidc-auth0.md b/app/enterprise/1.3-x/plugins/oidc-auth0.md new file mode 100644 index 000000000000..deb2e42682e9 --- /dev/null +++ b/app/enterprise/1.3-x/plugins/oidc-auth0.md @@ -0,0 +1,49 @@ +--- +title: OpenID Connect with Auth0 +--- + +## Introduction + +This guide covers an example OpenID Connect plugin configuration to authenticate headless service consumers using Auth0's identity provider. + +## Auth0 IDP Configuration + +This configuration will use a [client credentials grant][client-credentials-grant] as it is non-interactive, and because we expect clients to authenticate on behalf of themselves, not an end-user. To do so, you will need to [create an Auth0 API][create-auth0-api] and a [non-interactive client][non-interactive-client]. + +### API Configuration + +When creating your API, you will need to specify an Identifier. Using the URL that your consumer makes requests to is generally appropriate, so this will typically be the hostname/path combination configured as an API in Kong. + +After creating your API, you will also need to add the `openid` scope at `https://manage.auth0.com/#/apis//scopes`. + +### Client Configuration + +You will need to authorize your client to access your API. Auth0 will prompt you to do so after client creation if you select the API you created previously from the client's Quick Start menu. After toggling the client to Authorized, expand its authorization settings and enable the `openid` scope. + +## Kong Configuration + +If you have not done so already, [create a **Service**][add-service] to protect. The `url` configuration should match the Identifier you used when configuring Auth0. + +Add an OpenID plugin configuration using the parameters in the example below using an HTTP client or Kong Manager. Auth0's token endpoint [requires passing the API identifier in the `audience` parameter][audience-required], which must be added as a custom argument: + +```bash +$ curl -i -X POST http://kong:8001/kong-admin/apis//plugins --data name="openid-connect" \ + --data config.auth_methods="client_credentials" \ + --data config.issuer="https://.auth0.com/.well-known/openid-configuration" \ + --data config.token_post_args_names="audience" \ + --data config.token_post_args_values="https://example.com/" +``` + +## Downstream configuration + +The service accessing your resource will need to pass its credentials to Kong. It can do so via HTTP basic authentication, query string arguments, or parameters in the request body. Basic authentication is generally preferable, as credentials in a query string will be present in Kong's access logs (and possibly in other infrastructure's access logs, if you have HTTP-aware infrastructure in front of Kong) and credentials in request bodies are limited to request methods that expect +client payloads. + +For basic authentication, use your client ID as the username and your client secret as the password. For the other methods, pass them as parameters named `client_id` and `client_secret`, respectively. + + +[client-credentials-grant]: https://auth0.com/docs/api-auth/tutorials/client-credentials +[create-auth0-api]: https://auth0.com/docs/apis#how-to-configure-an-api-in-auth0 +[non-interactive-client]: https://auth0.com/docs/clients +[add-service]: /enterprise/{{page.kong_version}}/getting-started/add-service +[audience-required]: https://auth0.com/docs/api/authentication#client-credentials diff --git a/app/enterprise/1.3-x/plugins/oidc-azuread.md b/app/enterprise/1.3-x/plugins/oidc-azuread.md new file mode 100644 index 000000000000..5ae264aea899 --- /dev/null +++ b/app/enterprise/1.3-x/plugins/oidc-azuread.md @@ -0,0 +1,88 @@ +--- +title: OpenID Connect with Azure AD +--- +## Introduction + +This guide covers an example OpenID Connect plugin configuration to authenticate browser clients using an Azure AD identity provider. + +## Prerequisites + +Because OpenID Connect deals with user credentials, all transactions should take place over HTTPS. Although user passwords for third party identity providers are only submitted to those providers and not Kong, authentication tokens do grant access to a subset of user account data and protected APIs, and should be secured. As such, you should make Kong's proxy available via a fully-qualified domain name and [add a certificate][add-certificate] for it. + +## Kong Configuration + +If you have not yet [added a **Route** and a **Service**][add-service], go ahead and do so. Again, note that you should be able to secure this route with HTTPS, so use a hostname you have a certificate for. Add a location handled by your route as an authorized redirect URI in Azure (under the **Authentication** section of your app registration). + +## Azure AD IDP Configuration + +You must [register an app][azure-create-app] in your Azure AD configuration and [add a client secret credential][azure-client-secret] that Kong will use to access it. You must also configure a redirect URI that is handled by your Route. + +Azure AD provides two interfaces for its OAuth2/OIDC-related endpoints, v1.0 and v2.0. Support for some legacy v1.0 behavior is still available on v2.0, including use of v1.0 tokens by default, which is not compatible with Kong's OIDC implementation. To force Azure AD to use v2.0 tokens, [edit your application manifest][azure-manifest] and set `accessTokenAcceptedVersion` to `2` and include a `YOUR_CLIENT_ID/.default` scope in your plugin configuration as shown below. + +## Plugin Configuration + +Add a plugin with the configuration below to your route using an HTTP client or [Kong Manager][enable-plugin]. + +```bash +$ curl -i -X POST https://admin.kong.example/routes/ROUTE_ID/plugins --data name="openid-connect" \ + --data config.issuer="https://login.microsoftonline.com/YOUR_DIRECTORY_ID/v2.0/.well-known/openid-configuration" \ + --data config.client_id="YOUR_CLIENT_ID" \ + --data config.client_secret="YOUR_CLIENT_SECRET" \ + --data config.redirect_uri="https://example.com/api" \ + --data config.scopes="openid" \ + --data config.scopes="email" \ + --data config.scopes="profile" \ + --data config.scopes="YOUR_CLIENT_ID/.default" \ + --data config.verify_parameters="false" +``` + +Several pieces of configuration above must use values specific to your environment: + +* The `issuer` URL can be retrieved by pressing the **Endpoints** button on your app registration's **Overview** page. +* `redirect_uri` should be the URI you specified earlier when configuring your app. You can add one via the **Authentication** section of the app settings if you did not add one initially. +* For `client_id` and `scopes` replace `YOUR_CLIENT_ID` with the client ID shown on the app **Overview** page. +* For `client_secret` replace `YOUR_CLIENT_SECRET` with the URL-encoded representation of the secret you created earlier in the **Certificates & secrets** section. Azure AD secrets often include reserved URL characters, which cURL may handle incorrectly if they are not URL-encoded. + +Visiting a URL matched by that route in a browser will now redirect to Microsoft's authentication site and return you to the redirect URI after authenticating. + +### Access Restrictions + +The configuration above allows users to authenticate and access the Route even though no consumer was created for them: any user with a valid account in the directory will have access to the Route. The OIDC plugin allows this as the simplest authentication option, but you may wish to restrict access further. There are several options for this: + +#### Domain Restrictions + +Azure AD does not provide identity tokens with the `hd` claim, and as such the OIDC plugin's `domains` configuration cannot restrict users based on their domain. Using a [single-tenant][azure-tenant] application will restrict access to users in your directory only. Multi-tenant apps allow users with Microsoft accounts from other directories and optionally any Microsoft account (e.g. live.com or Xbox accounts) to sign in. + +#### Consumer Mapping + +If you need to interact with other Kong plugins using consumer information, you can add configuration that maps account data received from the identity provider to a Kong consumer. For this example, the user's Azure AD account GUID is mapped to a consumer by setting it as the `custom_id` on their consumer, e.g. + +```bash +$ curl -i -X POST http://admin.kong.example/consumers/ \ + --data username="Yoda" \ + --data custom_id="e5634b31-d67f-4661-a6fb-b6cb77849bcf" + +$ curl -i -X PATCH http://admin.kong.example/plugins/OIDC_PLUGIN_ID \ + --data config.consumer_by="custom_id" \ + --data config.consumer_claim="oid" +``` + +Now, if a user logs into an Azure AD account with the GUID `e5634b31-d67f-4661-a6fb-b6cb77849bcf`, Kong will apply configuration associated with the consumer `Yoda` to their requests. + +This also requires that clients login using an account mapped to some consumer, which may not be desirable (e.g. you apply OpenID Connect to a service, but only use plugins requiring a consumer on some routes). To deal with this, you can set the `anonymous` parameter in your OIDC plugin configuration to the ID of a generic consumer, which will then be used for all authenticated users that cannot be mapped to some other consumer. You can alternately set `consumer_optional` to `true` to allow similar logins without mapping an anonymous consumer. + +#### Pseudo-Consumer Mapping + +For plugins that typically require consumers, the OIDC plugin can provide a consumer ID based on the value of a claim without mapping to an actual consumer. Setting `credential_claim` to a claim [in your plugin configuration][credential-claim] will extract the value of that claim and use it where Kong would normally use a consumer ID. Note that this may not work with all consumer-related functionality. + +Similarly, setting `authenticated_groups_claim` will extract that claim's value and use it as a group for the ACL plugin. + +[azure-client-secret]: https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-access-web-apis#add-credentials-to-your-web-application +[azure-create-app]: https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app +[azure-manifest]: https://docs.microsoft.com/en-us/azure/active-directory/develop/reference-app-manifest#configure-the-app-manifest +[azure-tenants]: https://docs.microsoft.com/en-us/azure/active-directory/develop/single-and-multi-tenant-apps +[add-certificate]: /1.2.x/admin-api/#add-certificate +[add-service]: /enterprise/{{page.kong_version}}/getting-started/add-service +[oidc-id-token]: http://openid.net/specs/openid-connect-core-1_0.html#IDToken +[credential-claim]: https://docs.konghq.com/hub/kong-inc/openid-connect/#configcredential_claim +[enable-plugin]: /enterprise/{{page.kong_version}}/getting-started/enable-plugin/ diff --git a/app/enterprise/1.3-x/plugins/oidc-google.md b/app/enterprise/1.3-x/plugins/oidc-google.md new file mode 100644 index 000000000000..a90b3d3cb40d --- /dev/null +++ b/app/enterprise/1.3-x/plugins/oidc-google.md @@ -0,0 +1,66 @@ +--- +title: OpenID Connect with Google +--- +## Introduction + +This guide covers an example OpenID Connect plugin configuration to authenticate browser clients using Google's identity provider. + +## Prerequisites + +Because OpenID Connect deals with user credentials, all transactions should take place over HTTPS. Although user passwords for third party identity providers are only submitted to those providers and not Kong, authentication tokens do grant access to a subset of user account data and protected APIs, and should be secured. As such, you should make Kong's proxy available via a fully-qualified domain name and [add a certificate][add-certificate] for it. + +## Google IDP Configuration + +Before configuring Kong, you'll need to set up a Google APIs project and create a credential set. Following [Google's instructions][google-oidc], [create a new set of OAuth client ID credentials][google-create-credentials] with the Web application class. Add an authorized redirect URI for part of the API you wish to protect (more complex applications may redirect to a resource that sets additional +application-specific state on the client, but for our purposes, any protected URI will work). Authorized JavaScript origins can be left blank. + +You can optionally customize the consent screen to inform clients who/what application is requesting authentication, but this is not required for testing. All steps after can be ignored, as Kong handles the server-side authentication request and token validation. + +## Kong Configuration + +If you have not yet [added a **Service**][add-service], go ahead and do so. Again, note that you should be able to secure this API with HTTPS, so if you are configuring a host, use a hostname you have a certificate for. + +### Basic Plugin Configuration + +Add a plugin with the configuration below to your API using an HTTP client or Kong Manager. Make sure to use the same redirect URI as configured earlier: + +```bash +$ curl -i -X POST http://kong:8001/apis/example/plugins --data name="openid-connect" \ + --data config.issuer="https://accounts.google.com/.well-known/openid-configuration" \ + --data config.client_id="YOUR_CLIENT_ID" \ + --data config.client_secret="YOUR_CLIENT_SECRET" \ + --data config.redirect_uri="https://example.com/api" \ + --data config.scopes="openid,email" +``` + +Visiting a URL matched by that API in a browser will now redirect to Google's authentication site and return you to the redirect URI after authenticating. You'll note, however, that we did not configure anything to map authentication to consumers and that no consumer is associated with the subsequent request. Indeed, if you have configured other plugins that rely on consumer information, such as the ACL plugin, you will not have access. At present, the plugin configuration confirms that +users have a Google account, but doesn't do anything with that information. + +Depending on your needs, it may not be necessary to associate clients with a consumer. You can, for example, configure the `domains` parameter to limit access to a internal users if you have a G Suite hosted domain, or configure `upstream_headers_claims` to send information about the user upstream (e.g. their email, a profile picture, their name, etc.) for use in your applications or for analytics. + +### Consumer Mapping + +If you need to interact with other Kong plugins using consumer information, you must add configuration that maps account data received from the identity provider to a Kong consumer. For this example, we'll map the user's Google account email by setting a `custom_id` on their consumer, e.g. + +```bash +$ curl -i -X POST http://kong:8001/consumers/ \ + --data username="Yoda" \ + --data custom_id="user@example.com" + +$ curl -i -X PATCH http://kong:8001/apis/example/plugins/ \ + --data config.consumer_by="custom_id" \ + --data config.consumer_claim="email" +``` + +Now, if a user logs into a Google account with the email `user@example.com`, Kong will apply configuration associated with the consumer `Yoda` to their requests. Note that while Google provides account emails, not all identity providers will. OpenID Connect does not have many required claims--the [only required user identity claim][oidc-id-token] is `sub`, a unique subscriber ID. Many optional claims [are +standardized][oidc-standard-claims], however--if a provider returns an `email` claim, the contents will always be an email address. + +This also requires that clients login using an account mapped to some consumer, which may not be desirable (e.g. you apply OpenID Connect to a service, but only use plugins requiring a consumer on some routes). To deal with this, you can set the `anonymous` parameter in your OIDC plugin configuration to the ID of a generic consumer, which will then be used for all authenticated users that cannot be mapped to some other consumer. + + +[add-certificate]: /1.0.x/admin-api/#add-certificate +[google-oidc]: https://developers.google.com/identity/protocols/OpenIDConnect +[google-create-credentials]: https://console.developers.google.com/apis/credentials +[add-service]: /enterprise/{{page.kong_version}}/getting-started/add-service +[oidc-id-token]: http://openid.net/specs/openid-connect-core-1_0.html#IDToken +[oidc-standard-claims]: http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims diff --git a/app/enterprise/1.3-x/plugins/oidc-okta.md b/app/enterprise/1.3-x/plugins/oidc-okta.md new file mode 100644 index 000000000000..6d9d57ce4f9c --- /dev/null +++ b/app/enterprise/1.3-x/plugins/oidc-okta.md @@ -0,0 +1,108 @@ +--- +title: OpenID Connect with Okta +--- +## Introduction + +This guide covers an example OpenID Connect plugin configuration to authenticate browser clients using an Okta identity provider. + +## Prerequisites + +Because OpenID Connect deals with user credentials, all transactions should take place over HTTPS. Although user passwords for third party identity providers are only submitted to those providers and not Kong, authentication tokens grant access to a subset of user account data and protected APIs, and should be secured. As such, you should make Kong's proxy available via a fully-qualified domain name and [add a certificate][add-certificate] for it. + +## Kong Configuration + +If you have not yet [added a **Route** and a **Service**][add-service], go ahead and do so. Again, note that you should be able to secure this route with HTTPS, so use a hostname you have a certificate for. Add a location handled by your route as an authorized redirect URI in Okta (under the **Authentication** section of your app registration). + +## Okta IDP Configuration + +### Sample Okta Configuration Steps + +1. [Register an Application][okta-register-app]. Select the **Applications** page, click **Add Application**. + + + +2. Select **Web** as the platform. + + + +3. Fill out the Application's Settings + + **Login re-direct URIs** is a URI that corresponds to a Route you have configured in Kong that will use Okta to authenticate. **Group Assignment** defines who is allowed to use this application. **Grant Type Allowed** indicates the Grant types to allow for your application. + + + +4. After submitting the Application configuration, the client credentials will display on the **General** page. + + + +5. [Define and configure an Authorization server][okta-authorization-server]. Select the **API** page and add an Authorization Server if you don't have an existing one to use. + + + + + +6. Click **Save** and view your Authorization Server Settings. + + + +## Plugin Configuration + +Add a plugin with the configuration below to your route using an HTTP client or [Kong Manager][enable-plugin]. + +```bash +$ curl -i -X POST https://admin.kong.example/routes/ROUTE_ID/plugins --data name="openid-connect" \ + --data config.issuer="https://YOUR_OKTA_DOMAIN/oauth2/YOUR_AUTH_SERVER/.well-known/openid-configuration" \ + --data config.client_id="YOUR_CLIENT_ID" \ + --data config.client_secret="YOUR_CLIENT_SECRET" \ + --data config.redirect_uri="https://kong.com/api" \ + --data config.scopes="openid" \ + --data config.scopes="email" \ + --data config.scopes="profile" +``` + +Several pieces of configuration above must use values specific to your environment: + +* The `issuer` URL can be found from your Authorization Server settings. +* `redirect_uri` should be the URI you specified earlier when configuring your app. You can view and edit this from the **General** page for your application. +* For `client_id` and `client_secret` replace `YOUR_CLIENT_ID` and `YOUR_CLIENT_SECRET` with the client ID and secret shown in your Okta application's **General** page. + +Visiting a URL matched by that route in a browser will now redirect to Okta's authentication site and return you to the redirect URI after authenticating. + +Additional plugin parameter to consider: + +* The `auth_methods` parameter defines a lists of all the authentication methods that you want the plugin to accept. By default value is a list of all the supported methods. It is advisable to define this parameter with only the methods you wish to allow. + +### Access Restrictions + +The configuration above allows users to authenticate and access the Route even though no consumer was created for them: any user with a valid account in the directory will have access to the Route. The OIDC plugin allows this as the simplest authentication option, but you may wish to restrict access further. There are several options for this: + +#### Consumer Mapping + +If you need to interact with other Kong plugins using consumer information, you can add configuration that maps account data received from the identity provider to a Kong consumer. For this example, the user's Okta's AD account GUID is mapped to a consumer by setting it as the `custom_id` on their consumer, e.g. + +```bash +$ curl -i -X POST http://admin.kong.example/consumers/ \ + --data username="Yoda" \ + --data custom_id="e5634b31-d67f-4661-a6fb-b6cb77849bcf" + +$ curl -i -X PATCH http://admin.kong.example/plugins/OIDC_PLUGIN_ID \ + --data config.consumer_by="custom_id" \ + --data config.consumer_claim="sub" +``` + +Now, if a user logs into an Okta account with the GUID `e5634b31-d67f-4661-a6fb-b6cb77849bcf`, Kong will apply configuration associated with the consumer `Yoda` to their requests. + +This also requires that clients login using an account mapped to some consumer, which may not be desirable (e.g. you apply OpenID Connect to a service, but only use plugins requiring a consumer on some routes). To deal with this, you can set the `anonymous` parameter in your OIDC plugin configuration to the ID of a generic consumer, which will then be used for all authenticated users that cannot be mapped to some other consumer. You can alternately set `consumer_optional` to `true` to allow similar logins without mapping an anonymous consumer. + +#### Pseudo-consumers + +For plugins that typically require consumers, the OIDC plugin can provide a consumer ID based on the value of a claim without mapping to an actual consumer. Setting `credential_claim` to a claim [in your plugin configuration][credential-claim] will extract the value of that claim and use it where Kong would normally use a consumer ID. Note that this may not work with all consumer-related functionality. + +Similarly, setting `authenticated_groups_claim` will extract that claim's value and use it as a group for the ACL plugin. + +[okta-authorization-server]: https://developer.okta.com/docs/guides/customize-authz-server/create-authz-server/ +[okta-register-app]: https://developer.okta.com/docs/guides/add-an-external-idp/openidconnect/register-app-in-okta/ +[add-certificate]: /1.0.x/admin-api/#add-certificate +[add-service]: /enterprise/{{page.kong_version}}/getting-started/add-service +[credential-claim]: https://docs.konghq.com/hub/kong-inc/openid-connect/#configcredential_claim +[enable-plugin]: /enterprise/{{page.kong_version}}/getting-started/enable-plugin/ diff --git a/app/enterprise/1.3-x/plugins/openid-connect.md b/app/enterprise/1.3-x/plugins/openid-connect.md new file mode 100644 index 000000000000..8fb1c9ec0fe0 --- /dev/null +++ b/app/enterprise/1.3-x/plugins/openid-connect.md @@ -0,0 +1,3 @@ +--- +redirect_to: /hub/kong-inc/openid-connect +--- diff --git a/app/enterprise/1.3-x/plugins/rate-limiting-advanced.md b/app/enterprise/1.3-x/plugins/rate-limiting-advanced.md new file mode 100644 index 000000000000..fd033b30df16 --- /dev/null +++ b/app/enterprise/1.3-x/plugins/rate-limiting-advanced.md @@ -0,0 +1,3 @@ +--- +redirect_to: /hub/kong-inc/rate-limiting-advanced +--- diff --git a/app/enterprise/1.3-x/plugins/request-transformer.md b/app/enterprise/1.3-x/plugins/request-transformer.md new file mode 100644 index 000000000000..2a08b508327e --- /dev/null +++ b/app/enterprise/1.3-x/plugins/request-transformer.md @@ -0,0 +1,3 @@ +--- +redirect_to: /hub/kong-inc/request-transformer-advanced +--- diff --git a/app/enterprise/1.3-x/plugins/request-validator.md b/app/enterprise/1.3-x/plugins/request-validator.md new file mode 100644 index 000000000000..c7cec3132e36 --- /dev/null +++ b/app/enterprise/1.3-x/plugins/request-validator.md @@ -0,0 +1,3 @@ +--- +redirect_to: /hub/kong-inc/request-validator +--- diff --git a/app/enterprise/1.3-x/plugins/route-by-header.md b/app/enterprise/1.3-x/plugins/route-by-header.md new file mode 100644 index 000000000000..490b1f36ed4d --- /dev/null +++ b/app/enterprise/1.3-x/plugins/route-by-header.md @@ -0,0 +1,3 @@ +--- +redirect_to: /hub/kong-inc/route-by-header +--- \ No newline at end of file diff --git a/app/enterprise/1.3-x/plugins/route-by-headers.md b/app/enterprise/1.3-x/plugins/route-by-headers.md new file mode 100644 index 000000000000..fafe0c8cb91c --- /dev/null +++ b/app/enterprise/1.3-x/plugins/route-by-headers.md @@ -0,0 +1,3 @@ +--- +redirect_to: /hub/kong-inc/route-by-headers +--- \ No newline at end of file diff --git a/app/enterprise/1.3-x/plugins/route-transformer-advanced.md b/app/enterprise/1.3-x/plugins/route-transformer-advanced.md new file mode 100644 index 000000000000..66c9fbd573a9 --- /dev/null +++ b/app/enterprise/1.3-x/plugins/route-transformer-advanced.md @@ -0,0 +1,34 @@ +--- +title: Route Transformer Advanced Plugin +--- + +_NOTE_: the 'advanced' label is only attached since this is an enterprise only +plugin. There is not a 'regular' version available. + +## Synopsis + +This plugin transforms the routing on the fly in Kong, changing the upstream server/port/path to hit. The substitutions can be configured via flexible templates. + +## History + +See [the changelog](https://github.com/Kong/kong-plugin-route-transformer-advanced/blob/master/CHANGELOG.md). + +## Configuration + +| form parameter | default | description | +| --- | --- | --- | +| `name` | | The name of the plugin to use, in this case `route-transformer-advanced` +| `service_id` | | The id of the Service which this plugin will target. +| `route_id` | | The id of the Route which this plugin will target. +| `enabled` | `true` | Whether this plugin will be applied. +| `consumer_id` | | The id of the Consumer which this plugin will target. +| `config.path` | | Updates the upstream request path with given value/template. This value can only be used to update the path part of the URI, not the scheme, nor the hostname. +| `config.host` | | Updates the upstream request Host with given value/template. This value can only be used to update the routing, it will not update the Host-header value. +| `config.port` | | Updates the upstream request Port with given value/template. NOTE: the port as set may be overridden again by DNS resolution (in case of SRV records, or an Upstream) + +## Template as Value + +The templates that can be used as values are the same as the [request-transformer](https://docs.konghq.com/hub/kong-inc/request-transformer-advanced/). + +[badge-travis-url]: https://travis-ci.com/Kong/kong-plugin-route-transformer-advanced/branches +[badge-travis-image]: https://travis-ci.com/Kong/kong-plugin-route-transformer-advanced.svg?token=BfzyBZDa3icGPsKGmBHb&branch=master diff --git a/app/enterprise/1.3-x/plugins/session.md b/app/enterprise/1.3-x/plugins/session.md new file mode 100644 index 000000000000..e20675a6d484 --- /dev/null +++ b/app/enterprise/1.3-x/plugins/session.md @@ -0,0 +1,3 @@ +--- +redirect_to: /hub/kong-inc/session +--- diff --git a/app/enterprise/1.3-x/plugins/statsd-advanced.md b/app/enterprise/1.3-x/plugins/statsd-advanced.md new file mode 100644 index 000000000000..53fabda600c9 --- /dev/null +++ b/app/enterprise/1.3-x/plugins/statsd-advanced.md @@ -0,0 +1,3 @@ +--- +redirect_to: /hub/kong-inc/statsd-advanced +--- diff --git a/app/enterprise/1.3-x/plugins/statsd.rules.yaml b/app/enterprise/1.3-x/plugins/statsd.rules.yaml new file mode 100644 index 000000000000..d59063017be1 --- /dev/null +++ b/app/enterprise/1.3-x/plugins/statsd.rules.yaml @@ -0,0 +1,118 @@ +mappings: +# by API +- match: kong.api.*.request.count + name: "kong_requests_proxy" + labels: + job: "kong_metrics" + +- match: kong.api.*.status.* + name: "kong_status_code" + action: drop + +- match: kong.api.*.kong_latency + name: "kong_latency_proxy_request" + timer_type: histogram + buckets: [1] + min_max: true + labels: + job: "kong_metrics" + +- match: kong.api.*.upstream_latency + name: "kong_latency_upstream" + timer_type: histogram + buckets: [1] + min_max: true + labels: + job: "kong_metrics" + +- match: kong.api.*.cache_datastore_hits_total + name: "kong_cache_datastore_hits_total" + labels: + job: "kong_metrics" + +- match: kong.api.*.cache_datastore_misses_total + name: "kong_cache_datastore_misses_total" + labels: + job: "kong_metrics" + +# by Service +- match: kong.service.*.request.count + name: "kong_requests_proxy" + labels: + job: "kong_metrics" + +- match: kong.service.*.status.* + name: "kong_status_code" + labels: + service: "$1" + status_code: $2 + job: "kong_metrics" + +- match: kong.service.*.kong_latency + name: "kong_latency_proxy_request" + timer_type: histogram + buckets: [1] + min_max: true + labels: + job: "kong_metrics" + +- match: kong.service.*.upstream_latency + name: "kong_latency_upstream" + timer_type: histogram + buckets: [1] + min_max: true + labels: + job: "kong_metrics" + +- match: kong.service.*.cache_datastore_hits_total + name: "kong_cache_datastore_hits_total" + labels: + job: "kong_metrics" + +- match: kong.service.*.cache_datastore_misses_total + name: "kong_cache_datastore_misses_total" + labels: + job: "kong_metrics" + +# by Service and Route +- match: kong.service.*.user.*.status.* + name: "kong_status_code_per_consumer" + labels: + service: "$1" + route_id: "" + consumer: "$2" + status_code: $3 + job: "kong_metrics" + +- match: kong.route.*.user.*.status.* + name: "kong_status_code_per_consumer" + labels: + service: "" + route_id: "$1" + consumer: "$2" + status_code: $3 + job: "kong_metrics" + +# by Service and Workspace +- match: kong.service.*.workspace.*.status.* + name: "kong_status_code_per_workspace" + labels: + service: "$1" + workspace: "$2" + status_code: $3 + job: "kong_metrics" + +# by node +- match: kong.node.*.shdict.*.free_space + name: "kong_shdict_free_space" + labels: + node: "$1" + shdict: "$2" + job: "kong_metrics" + +- match: kong.node.*.shdict.*.capacity + name: "kong_shdict_capacity" + labels: + node: "$1" + shdict: "$2" + job: "kong_metrics" diff --git a/app/enterprise/1.3-x/plugins/upstream-tls.md b/app/enterprise/1.3-x/plugins/upstream-tls.md new file mode 100644 index 000000000000..0ba9c23bcc74 --- /dev/null +++ b/app/enterprise/1.3-x/plugins/upstream-tls.md @@ -0,0 +1,3 @@ +--- +redirect_to: /hub/kong-inc/upstream-tls +--- diff --git a/app/enterprise/1.3-x/plugins/vault-auth.md b/app/enterprise/1.3-x/plugins/vault-auth.md new file mode 100644 index 000000000000..d20973f3f256 --- /dev/null +++ b/app/enterprise/1.3-x/plugins/vault-auth.md @@ -0,0 +1,3 @@ +--- +redirect_to: /hub/kong-inc/vault-auth +--- diff --git a/app/enterprise/1.3-x/property-reference.md b/app/enterprise/1.3-x/property-reference.md new file mode 100644 index 000000000000..e29838e60ecc --- /dev/null +++ b/app/enterprise/1.3-x/property-reference.md @@ -0,0 +1,2435 @@ +--- +title: Configuration Property Reference for Kong Enterprise +toc: false +--- + +## Table of Contents + +* [General](#general) +* [NGINX](#nginx) +* [NGINX Injected Directives](#nginx-injected-directives) +* [Datastore](#datastore) +* [Datastore Cache](#datastore-cache) +* [DNS Resolver](#dns-resolver) +* [Development & Miscellaneous](#development-&-miscellaneous) +* [Kong Manager](#kong-manager) +* [Vitals](#vitals) +* [Dev Portal](#dev-portal) +* [Dev Portal Authentication](#dev-portal-authentication) +* [Dev Portal SMTP Configuration](#dev-portal-smtp-configuration) +* [Admin SMTP Configuration](#admin-smtp-configuration) +* [General SMTP Configuration](#general-smtp-configuration) +* [Data & Admin Audit](#data-&-admin-audit) +* [Granular Tracing](#granular-tracing) +* [Route Collision Detection and Prevention](#route-collision-detection-and-prevention) +* [Workspaces](#workspaces) + +## General + + +### prefix + +**Default:** `/usr/local/kong/` + +**Description:** + +Working directory. Equivalent to Nginx's prefix path, containing +temporary files and logs. Each Kong process must have a separate +working directory. + + +### log_level + +**Default:** `notice` + +**Description:** + +Log level of the Nginx server. Logs are found at +`/logs/error.log`. + +**Note:** See +http://nginx.org/en/docs/ngx_core_module.html#error_log for a list +of accepted values. + + +### proxy_access_log + +**Default:** `logs/access.log` + +**Description:** + +Path for proxy port request access logs. Set this value to `off` to +disable logging proxy requests. If this value is a relative path, +it will be placed under the `prefix` location. + + +### proxy_error_log + +**Default:** `logs/error.log` + +**Description:** + +Path for proxy port request error logs. The granularity of these +logs is adjusted by the `log_level` directive. + + +### admin_access_log + +**Default:** `logs/admin_access.log` + +**Description:** + +Path for Admin API request access logs. Set this value to `off` to +disable logging Admin API requests. If this value is a relative +path, it will be placed under the `prefix` location. + + +### admin_error_log + +**Default:** `logs/error.log` + +**Description:** + +Path for Admin API request error logs. The granularity of these +logs is adjusted by the `log_level` directive. + + +### plugins + +**Default:** `bundled` + +**Description:** + +Comma-separated list of plugins this node should load. +By default, only plugins bundled in official distributions are loaded via the `bundled` keyword.. Plugins will be loaded from the `kong.plugins.{name}.*` +namespace. + + +### anonymous_reports + +**Default:** `on` + +**Description:** + +Send anonymous usage data such as error stack traces to help +improve Kong. + + +## NGINX + + +### proxy_listen + +**Default:** `0.0.0.0:8000, 0.0.0.0:8443 ssl` + +**Description:** + +Comma-separated list of addresses and ports on which the proxy +server should listen. The proxy server is the public entrypoint of +Kong, which proxies traffic from your consumers to your backend +services. This value accepts IPv4, IPv6, and hostnames. + +Some suffixes can be specified for each pair: + +- `ssl` requires that all connections made through a particular + address/port be made with TLS enabled. +- `http2` allows for clients to open HTTP/2 connections to Kong's proxy + server. +- `proxy_protocol` enables usage of the PROXY protocol for a given + address/port. +- `transparent` causes Kong to listen to, and respond from, any and all + IP addresses and ports you configure in `iptables`. +- `deferred` instructs to use a deferred accept on Linux (the + TCP_DEFER_ACCEPT socket option). +- `bind` instructs to make a separate bind() call for a given `address:port` pair. +- `reuseport` instructs to create an individual listening socket for each worker process, + allowing a kernel to distribute incoming connections between worker processes. + +This value can be set to `off`, thus disabling the proxy port for this node, +enabling a 'control-plane' mode (without traffic proxying capabilities) which +can configure a cluster of nodes connected to the same database. + + +### proxy_url + +**Default:** `NONE` (auto generated) + +**Description:** + +Here you may provide the lookup, or balancer, +address for your Kong Proxy nodes. + +This value is commonly used in a microservices +or service-mesh oriented architecture. + +Accepted format (parts in parenthesis are optional): + +``` +://(:(/)) +``` + +**Examples:** + +``` +- ://: + proxy_url = http://127.0.0.1:8000 +- SSL :// + proxy_url = https://proxy.domain.tld +- :/// + proxy_url = http://dev-machine/dev-285 +``` + +**Default:** +Kong Manager and Dev Portal will use +the window request host and append the resolved +listener port depending on the requested protocol. + +**Note:** see http://nginx.org/en/docs/http/ngx_http_core_module.html#listen +for a description of the accepted formats for this and other *_listen values. + +**Note:** see https://www.nginx.com/resources/admin-guide/proxy-protocol/ +for more details about the `proxy_protocol` parameter. + +**Example:** + +``` +proxy_url = https://127.0.0.1:8443 +``` + +### stream_listen + +**Description** + +Comma-separated list of addresses and ports on which the stream mode should listen. + +This value accepts IPv4, IPv6, and hostnames. Some suffixes can be specified for each pair: + +- `proxy_protocol` enables usage of the PROXY protocol for a given address/port. +- `transparent` causes Kong Gateway to listen to (and respond from) any and all IP addresses and + ports you configure in `iptables`. +- `bind` causes Kong Gateway to make a separate bind() call for a given `address:port` pair. +- `reuseport` causes Kong Gateway to create an individual listening socket for each worker process + allowing a kernel to distribute incoming connections between worker processes. + +**Note:** The `ssl` suffix is not supported, and each address/port will accept TCP with or + without TLS enabled. + +**Default:** `off` + +**Examples:** +``` +stream_listen = 127.0.0.1:7000 +stream_listen = 0.0.0.989, 0.0.0.0:20 +stream_listen = [::1]:1234 +``` + +### admin_api_uri + +**Default:** `NONE` (auto generated) + +**Description:** + +Hierarchical part of a URI which is composed +optionally of a host, port, and path at which your +Admin interface API accepts HTTP or HTTPS traffic. +When this config is disabled, the gui will use the +window protocol + host and append the resolved +admin_gui_listen HTTP/HTTPS port. + +**Example:** + +``` +admin_api_uri = https://127.0.0.1:8444 +``` + + +### admin_listen + +**Default:** `127.0.0.1:8001, 127.0.0.1:8444 ssl` + +**Description:** + +Comma-separated list of addresses and ports on which the +Admin interface should listen. The Admin interface is +the API allowing you to configure and manage Kong. +Access to this interface should be *restricted* to Kong +administrators *only*. This value accepts IPv4, IPv6, +and hostnames. + +Some suffixes can be specified for each pair: +- `ssl` will require that all connections made + through a particular address/port be made with TLS + enabled. +- `http2` will allow for clients to open HTTP/2 + connections to Kong's proxy server. +- Finally, `proxy_protocol` will enable usage of the + PROXY protocol for a given address/port. + +This value can be set to `off`, thus disabling +the Admin interface for this node, enabling a +'data-plane' mode (without configuration +capabilities) pulling its configuration changes +from the database. + + +### nginx_user + +**Default:** `nobody nobody` + +**Description:** + +Defines user and group credentials used by +worker processes. If group is omitted, a +group whose name equals that of user is +used. + +**Example:** `[user] [group]` + + +### nginx_worker_processes + +**Default:** `auto` + +**Description:** + +Determines the number of worker processes spawned by Nginx. + + +### nginx_daemon + +**Default:** `on` + +**Description:** + +Determines wether Nginx will run as a daemon +or as a foreground process. Mainly useful +for development or when running Kong inside +a Docker environment. + + +### mem_cache_size + +**Default:** `128m` + +**Description:** + +Size of the in-memory cache for database +entities. The accepted units are `k` and +`m`, with a minimum recommended value of +a few MBs. + + +### ssl_cipher_suite + +**Default:** `modern` + +**Description:** + +Defines the TLS ciphers served by Nginx. +Accepted values are `modern`, +`intermediate`, `old`, or `custom`. + +**Note:** see https://wiki.mozilla.org/Security/Server_Side_TLS for detailed +descriptions of each cipher suite. + +### ssl_ciphers + +**Default:** `nil` + +**Description:** + +Defines a custom list of TLS ciphers to be +served by Nginx. This list must conform to +the pattern defined by `openssl ciphers`. +This value is ignored if `ssl_cipher_suite` +is not `custom`. + + +### ssl_cert + +**Default:** `nil` + +**Description:** + +The absolute path to the SSL certificate for +`proxy_listen` values with SSL enabled. + + +### ssl_cert_key + +**Default:** `nil` + +**Description:** + +The absolute path to the SSL key for +`proxy_listen` values with SSL enabled. + + +### client_ssl + +**Default:** `off` + +**Description:** + +Determines if Nginx should send client-side +SSL certificates when proxying requests. + + +### client_ssl_cert + +**Default:** `nil` + +**Description:** + +If `client_ssl` is enabled, the absolute +path to the client SSL certificate for the +`proxy_ssl_certificate` directive. Note that +this value is statically defined on the +node, and currently cannot be configured on +a per-API basis. + + +### client_ssl_cert_key + +**Default:** `nil` + +**Description:** + +If `client_ssl` is enabled, the absolute +path to the client SSL key for the +`proxy_ssl_certificate_key` address. Note +this value is statically defined on the +node, and currently cannot be configured on +a per-API basis. + + +### admin_ssl_cert + +**Default:** `nil` + +**Description:** + +The absolute path to the SSL certificate for +`admin_listen` values with SSL enabled. + + +### admin_ssl_cert_key + +**Default:** `nil` + +**Description:** + +The absolute path to the SSL key for +`admin_listen` values with SSL enabled. + + +### headers + +**Defaul:t** `server_tokens, latency_tokens` + +**Description** + Specify Kong-specific headers that should be injected in responses to the client. + Acceptable values are: + - `server_tokens`: inject 'Via' and 'Server' + headers. + - `latency_tokens`: inject + 'X-Kong-Proxy-Latency' and + 'X-Kong-Upstream-Latency' headers. + - `X-Kong-`: only inject this + specific the header when applicable. + + This value can be set to `off`, which prevents Kong from injecting any of these + headers. Note that plugins can still inject headers. + + +### trusted_ips + +**Default:** `nil` + +**Description:** + +Defines trusted IP addresses blocks that are +known to send correct X-Forwarded-* headers. +Requests from trusted IPs make Kong forward +their X-Forwarded-* headers upstream. +Non-trusted requests make Kong insert its +own X-Forwarded-* headers. + +This property also sets the +`set_real_ip_from` directive(s) in the Nginx +configuration. It accepts the same type of +values (CIDR blocks) but as a +comma-separated list. + +To trust *all* /!\ IPs, set this value to +`0.0.0.0/0,::/0`. + +If the special value `unix:` is specified, +all UNIX-domain sockets will be trusted. + +**Note:** see http://nginx.org/en/docs/http/ngx_http_realip_module.html for +examples of accepted values. + + +### real_ip_header + +**Default:** `X-Real-IP` + +**Description:** + +Defines the request header field whose value +will be used to replace the client address. +This value sets the ngx_http_realip_module +directive of the same name in the Nginx +configuration. + +If set to `proxy_protocol`, then at least +one of the `proxy_listen` entries must +have the `proxy_protocol` flag enabled. + +**Note:** see +http://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header +for a description of this directive. + + +### real_ip_recursive + +**Default:** `off` + +**Description:** + +This value sets the ngx_http_realip_module +directive of the same name in the Nginx +configuration. + +**Note:** see +http://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_recursive +for a description of this directive. + + +### client_max_body_size + +**Default:** `0` + +**Description:** + +Defines the maximum request body size allowed +by requests proxied by Kong, specified in +the Content-Length request header. If a +request exceeds this limit, Kong will +respond with a 413 (Request Entity Too +Large). Setting this value to 0 disables +checking the request body size. + +Note: see +http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size +for further description of this parameter. Numeric values may be suffixed +with 'k' or 'm' to denote limits in terms of kilobytes or megabytes. + +### client_body_buffer_size + +**Default:** `8k` + +**Description:** + +Defines the buffer size for reading the +request body. If the client request body is +larger than this value, the body will be +buffered to disk. Note that when the body is +buffered to disk Kong plugins that access or +manipulate the request body may not work, so +it is advisable to set this value as high as +possible (e.g., set it as high as +`client_max_body_size` to force request +bodies to be kept in memory). Do note that +high-concurrency environments will require +significant memory allocations to process +many concurrent large request bodies. + +**Note:** see +http://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_buffer_size +for further description of this parameter. Numeric values may be suffixed +with 'k' or 'm' to denote limits in terms of kilobytes or megabytes. + + +### error_default_type + +**Default:** `text/plain` + +**Description:** + +Default MIME type to use when the request +`Accept` header is missing and Nginx +is returning an error for the request. +Accepted values are `text/plain`, +`text/html`, `application/json`, and +`application/xml`. + + +## NGINX Injected Directives + +Nginx directives can be dynamically injected in the runtime nginx.conf file +without requiring a custom Nginx configuration template. + +All configuration properties respecting the naming scheme +`nginx__` will result in `` being injected in +the Nginx configuration block corresponding to the property's ``. + +Example: + +`nginx_proxy_large_client_header_buffers = 8 24k` + +Will inject the following directive in Kong's proxy `server {}` block: + +`large_client_header_buffers 8 24k;` + +The following namespaces are supported: + +- `nginx_http_`: Injects `` in Kong's `http {}` block. +- `nginx_proxy_`: Injects `` in Kong's proxy + `server {}` block. +- `nginx_http_upstream_`: Injects `` in Kong's proxy + `upstream {}` block. +- `nginx_admin_`: Injects `` in Kong's Admin API + `server {}` block. +- `nginx_stream_`: Injects `` in Kong's stream module + `stream {}` block (only effective if `stream_listen` is enabled). +- `nginx_sproxy_`: Injects `` in Kong's stream module + `server {}` block (only effective if `stream_listen` is enabled). + +As with other configuration properties, Nginx directives can be injected via +environment variables when capitalized and prefixed with `KONG_`. + +Example: + +`KONG_NGINX_HTTP_SSL_PROTOCOLS` -> `nginx_http_ssl_protocols` + +Will inject the following directive in Kong's `http {}` block: + +`ssl_protocols ;` + +If different sets of protocols are desired between the proxy and Admin API +server, you may specify `nginx_proxy_ssl_protocols` and/or +`nginx_admin_ssl_protocols`, both of which taking precedence over the +`http {}` block. + +### nginx_http_ssl_protocols + +**Default:** `TLSv1.1 TLSv1.2 TLSv1.3` + +**Description:** + +Enables the specified protocols for +client-side connections. The set of +supported protocol versions also depends +on the version of OpenSSL Kong was built +with. + +See [http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_protocols](http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_protocols) + +### nginx_http_upstream_keepalive + +**Default:** `60` + +**Description:** + +Sets the maximum number of idle keepalive +connections to upstream servers that are +preserved in the cache of each worker +process. When this number is exceeded, the +least recently used connections are closed. +A value of `NONE` will disable this behavior +altogether, forcing each upstream request +to open a new connection. + +See [http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive](http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive) + +### nginx_http_upstream_keepalive_requests + +**Default:** `100` + +**Description:** + +Sets the maximum number of requests that can +be served through one keepalive connection. +After the maximum number of requests is +made, the connection is closed. + +See [http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive_requests](http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive_requests) + +### nginx_http_upstream_keepalive_timeout + +**Default:** `60s` + +**Description:** + +Sets a timeout during which an idle +keepalive connection to an upstream server +will stay open. + +See [http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive_timeout](http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive_timeout) + + +## Datastore + +Kong will store all of its data (such as APIs, consumers, and plugins) in +either Cassandra or PostgreSQL. + +All Kong nodes belonging to the same cluster must connect themselves to the +same database. + + +### database + +**Default:** `postgres` + +**Description:** + +Determines which of PostgreSQL or Cassandra +this node will use as its datastore. +Accepted values are `postgres` and +`cassandra`. + + +### pg_host + +**Default:** `127.0.0.1 ` + +**Description:** + +The PostgreSQL host to connect to. + + +### pg_port + +**Default:** `5432` + +**Description:** + +The port to connect to. + +### pg_timeout + +**Default:** `5000` + +**Description** + +Defines the timout (in milliseconds) for connecting, reading, and writing. + +### pg_user + +**Default:** `kong` + +**Description:** + +The username to authenticate if required. + + +### pg_password + +**Default:** `nil` + +**Description:** + +The password to authenticate if required. + + +### pg_database + +**Default:** `kong` + +**Description:** + +The database name to connect to. + + +### pg_ssl + +**Default:** `off` + +**Description:** + +Toggles client-server TLS connections +between Kong and PostgreSQL. + + +### pg_ssl_verify + +**Default:** `off` + +**Description:** + +Toggles server certificate verification if +`pg_ssl` is enabled. See the `lua_ssl_trusted_certificate` +setting to specify a certificate authority. + +### cassandra_contact_points + +**Default:** `127.0.0.1` + +**Description:** + +A comma-separated list of contact points to your cluster. + + +### cassandra_port + +**Default:** `9042` + +**Description:** + +The port on which your nodes are listening on. All your nodes and contact +points must listen on the same port. + + +### cassandra_keyspace + +**Default:** `kong` + +**Description:** + +The keyspace to use in your cluster. + + +### cassandra_timeout + +**Default:** `5000` + +**Description:** + +Defines the timeout (in ms), for reading and writing. + + +### cassandra_ssl + +**Default:** `off` + +**Description:** + +Toggles client-to-node TLS connections between Kong and Cassandra. + + +### cassandra_ssl_verify + +**Default:** `off` + +**Description:** + +Toggles server certificate verification if +`cassandra_ssl` is enabled. +See the `lua_ssl_trusted_certificate` +setting to specify a certificate authority. + + +### cassandra_username + +**Default:** `kong` + +**Description:** + +Username when using the `PasswordAuthenticator` scheme. + + +### cassandra_password + +**Default:** `nil` + +**Description:** + +Password when using the `PasswordAuthenticator` scheme. + + +### cassandra_consistency + +**Default:** `ONE` + +**Description:** + +Consistency setting to use when reading/writing to the Cassandra cluster. + +### cassandra_lb_policy + +**Default:** `RequestRoundRobin` + +**Description:** + +Load balancing policy to use when +distributing queries across your Cassandra +cluster. +Accepted values are: +`RoundRobin`, `RequestRoundRobin`, +`DCAwareRoundRobin`, and +`RequestDCAwareRoundRobin`. +Prefer the later if and only if you are +using a multi-datacenter cluster. + + +### cassandra_local_datacenter + +**Default:** `nil` + +**Description:** + +When using the `DCAwareRoundRobin` +or `RequestDCAwareRoundRobin` load +balancing policy, you must specify the name +of the local (closest) datacenter for this +Kong node. + + +### cassandra_repl_strategy + +**Default:** `SimpleStrategy` + +**Description:** + +When migrating for the first time, +Kong will use this setting to +create your keyspace. +Accepted values are +`SimpleStrategy` and +`NetworkTopologyStrategy`. + +### cassandra_repl_factor + +**Default:** `1` + +**Description:** + +When migrating for the first time, Kong +will create the keyspace with this +replication factor when using the +`SimpleStrategy`. + + +### cassandra_data_centers + +**Default:** `dc1:2,dc2:3` + +**Description:** + +When migrating for the first time, +will use this setting when using the +`NetworkTopologyStrategy`. +The format is a comma-separated list +made of :. + + +### cassandra_schema_consensus_timeout + +**Default:** `10000` + +**Description:** + +Defines the timeout (in ms) for +the waiting period to reach a +schema consensus between your +Cassandra nodes. +This value is only used during +migrations. + + +## Datastore Cache + +In order to avoid unecessary communication with the datastore, Kong caches +entities (e.g., APIs, Consumers, Credentials) for a configurable period +of time. It also handles invalidations if such an entity is updated. + +This section allows for configuring the behavior of Kong regarding the +caching of such configuration entities. + + +### db_update_frequency + +**Default:** `5` + +**Description:** + +Frequency (in seconds) at which to check for +updated entities with the datastore. +When a node creates, updates, or deletes an +entity via the Admin API, other nodes need +to wait for the next poll (configured by +this value) to eventually purge the old +cached entity and start using the new one. + + +### db_update_propagation + +**Default:** `0` + +**Description:** + +Time (in seconds) taken for an entity in the +datastore to be propagated to replica nodes +of another datacenter. +When in a distributed environment such as +a multi-datacenter Cassandra cluster, this +value should be the maximum number of +seconds taken by Cassandra to propagate a +row to other datacenters. +When set, this property will increase the +time taken by Kong to propagate the change +of an entity. +Single-datacenter setups or PostgreSQL +servers should suffer no such delays, and +this value can be safely set to 0. + + +### db_cache_ttl + +**Default:** `0` + +**Description:** + +Time-to-live (in seconds) of an entity from +the datastore when cached by this node. +Database misses (no entity) are also cached +according to this setting. +If set to 0, such cached entities/misses +never expire. + +### db_resurrect_ttl + +**Default:** `30` + +**Description** + +Time (in seconds) for which stale entities from the datastore should be +resurrected for when they cannot be refreshed (e.g., the datastore is +unreachable). When this TTL expires, a new attempt to refresh the stale +entities will be made. + + +### db_cache_warmup_entities + +**Default:** `services, plugins` + +**Description** + +Entities to be pre-loaded from the datastore into the in-memory cache at Kong +start-up. +This speeds up the first access of endpoints that use the given entities. +When the `services` entity is configured for warmup, the DNS entries for values +in its `host` attribute are pre-resolved asynchronously as well. +Cache size set in `mem_cache_size` should be set to a value large enough to +hold all instances of the specified entities. +If the size is insufficient, Kong will log a warning. + + +## DNS Resolver + +By default the DNS resolver will use the standard configuration files +`/etc/hosts` and `/etc/resolv.conf`. The settings in the latter file will be +overridden by the environment variables `LOCALDOMAIN` and `RES_OPTIONS` if +they have been set. + + +### dns_resolver + +**Default:** `nil` + +**Description:** + +Comma separated list of nameservers, each +entry in `ip[:port]` format to be used by +Kong. If not specified the nameservers in +the local `resolv.conf` file will be used. +Port defaults to 53 if omitted. Accepts +both IPv4 and IPv6 addresses. + + +### dns_hostsfile + +**Default:** `/etc/hosts` + +**Description:** + +The hosts file to use. This file is read +once and its content is static in memory. +To read the file again after modifying it, +Kong must be reloaded. + + +### dns_order + +**Default:** `LAST,SRV,A,CNAME` + +**Description:** + +The order in which to resolve different +record types. The `LAST` type means the +type of the last successful lookup (for the +specified name). The format is a (case +insensitive) comma separated list. + +### dns_valid_ttl + +**Default:** `nil` + +**Description:** + +By default, DNS records are cahced using the TTL value of a response. If this +property recevies a value (in seconds), it will override the TTL for all records. + +### dns_state_ttl + +**Default:** `4` + +**Description:** + + Defines, in seconds, how long a record will +remain in cache past its TTL. This value +will be used while the new DNS record is +fetched in the background. +Stale data will be used from expiry of a +record until either the refresh query +completes, or the `dns_stale_ttl` number of +seconds have passed. + + +### dns_not_found_ttl + +**Default:** `30` + +**Description:** + +TTL in seconds for empty DNS responses and "(3) name error" responses. + + +### dns_error_ttl + +**Default:** `1` + +**Description:** + +TTL in seconds for error responses. + + +### dns_no_sync + +**Default:** `off` + +**Description:** + +If enabled, then upon a cache-miss every +request will trigger its own dns query. +When disabled multiple requests for the +same name/type will be synchronised to a +single query. + + +## Development & Miscellaneous + +Additional settings inherited from lua-nginx-module allowing for more +flexibility and advanced usage. + +See the lua-nginx-module documentation for more informations: +https://github.com/openresty/lua-nginx-module + + +### lua_ssl_trusted_certificate + +**Default:** `nil` + +**Description:** + +Absolute path to the certificate +authority file for Lua cosockets in PEM +format. This certificate will be the one +used for verifying Kong's database +connections, when `pg_ssl_verify` or +`cassandra_ssl_verify` are enabled. + + +### lua_ssl_verify_depth + +**Default:** `1` + +**Description:** + +Sets the verification depth in the server +certificates chain used by Lua cosockets, +set by `lua_ssl_trusted_certificate`. +This includes the certificates configured +for Kong's database connections. + + +### lua_package_path + +**Default:** `./?.lua;./?/init.lua` + +**Description:** + +Sets the Lua module search path (LUA_PATH). +Useful when developing or using custom +plugins not stored in the default search +path. + + +### lua_package_cpath + +**Default:** `nil` + +**Description:** + +Sets the Lua C module search path (LUA_CPATH). + + +### lua_socket_pool_size + +**Default:** `30` + +**Description:** + +Specifies the size limit for every cosocket +connection pool associated with every remote +server. + + +### enforce_rbac + +**Default:** `off` + +**Description:** + +Specifies whether Admin API RBAC is enforced; +accepts one of 'entity', 'both', 'on', or +'off'. When 'on' is passed, only +endpoint-level authorization is enforced; +when 'entity' is passed, entity-level +authorization applies; 'both' enables both +endpoint and entity-level authorization; +'off' disables both. When enabled, Kong will +deny requests to the Admin API when a +nonexistent or invalid RBAC authorization +token is passed, or the RBAC user with which +the token is associated does not have +permissions to access/modify the requested +resource. + + +### rbac_auth_header + +**Default:** `Kong-Admin-Token` + +**Description:** + +Defines the name of the HTTP request header from which the Admin +API will attempt to identify the RBAC user. + + +## Kong Manager + + +### admin_gui_listen + +**Default:** `0.0.0.0:8002, 0.0.0.0:8445 ssl` + +**Description:** +Comma-separated list of addresses and ports on which + +Kong will expose the Admin GUI. This web application +lets you configure and manage Kong, and therefore +should be kept private and secured. + +Suffixes can be specified for each pair, similarly to +the `admin_listen` directive. + +**Example:** + +``` +admin_gui_listen = 0.0.0.0:8002, 0.0.0.0:8445 ssl +``` + + +### admin_gui_url + +**Default:** `NONE` + +**Description:** + +Here you may provide the lookup, or balancer, +address for your admin application. + +Accepted format (items in parenthesis are optional): + +``` +://(:(/)) +``` + +**Examples:** +``` +- http://127.0.0.1:8003 +- https://kong-admin.test +- http://dev-machine/dev-285 +``` + +**Default:** +The application will use the window request host and +append the resolved listener port depending on the +requested protocol. + +``` +admin_gui_url = https://kong-admin.test +``` + + +### admin_gui_ssl_cert + +**Default:** `NONE` (auto generated) + +**Description:** + +The absolute path to the SSL certificate for +`admin_gui_listen` values with SSL enabled. + +**Example:** + +``` +admin_gui_ssl_cert = /path/to/admin_gui_ssl.cert +``` + + +### admin_gui_ssl_cert_key + +**Default:** `NONE` (auto-generated) + +**Description:** + +The absolute path to the SSL key for `admin_gui_listen` values with SSL +enabled. + +**Example:** + +``` +admin_gui_ssl_key = /path/to/admin_gui_ssl.key +``` + + +### admin_gui_flags + +**Default:** `{}` + +**Description:** + +Alters the layout Admin GUI (JSON) + + +### admin_gui_access_log + +**Default:** `logs/admin_gui_access.log` + +**Description:** + +Here you can set an absolute or relative path for the +Kong Manager access logs. When the path is relative, +logs are placed in the `prefix` location. + +Setting this value to `off` disables access logs +for Kong Manager. + + +### admin_gui_error_log + +**Default:** `logs/admin_gui_error.log` + +**Description:** + +Here you can set an absolute or relative path for your +Portal API access logs. When the path is relative, +logs are placed in the `prefix` location. + +Setting this value to `off` disables error logs for +Kong Manager. + +Granularity can be adjusted through the `log_level` +directive. + + +### admin_gui_auth + +**Default:** `nil` + +**Description:** + +Here you may specify the configuration for the +authentication plugin you have chosen. + +* For Basic Authentication, set the value to `basic-auth` +* For LDAP Authentication, set the value to `ldap-auth-advanced` +* For OpenID Connect, set the value to `openid-connect` + +### admin_gui_auth_conf + +**Default:** `nil` + +**Description:** + +Here you may specify the configuration for the +authentication plugin you have chosen. + +For information about Plugin Configuration consult +the associated plugin documentation. + +**Example (for Basic Auth):** + +``` +admin_gui_auth_conf = { "hide_credentials": true } +``` + +### admin_gui_session_conf + +**Default:** `nil` + +**Description:** + +Session Plugin Config (JSON) +Here you may specify the configuration for the Session plugin as used by +Kong Manager. + +**Example:** + +``` +admin_gui_session_conf = { "cookie_name": "kookie", "secret": "changeme"} +``` + +### admin_gui_auth_header + +**Default:** `Kong-Admin-User` + +**Description:** + +Defines the name of the HTTP request header from which the Admin API will +attempt to identify the Kong Admin user. + +## Vitals + + +### vitals + +**Default:** `on` + +**Description:** + +When enabled, Kong will store and report metrics about its performance. +When running Kong in a multi-node setup, `vitals` entails two +separate meanings depending on the node. + +On a Proxy-only node, `vitals` determines whether to collect data +for Vitals. + +On an Admin-only node, `vitals` determines whether to display +Vitals metrics and visualizations on the dashboard. + + +### vitals_strategy + +**Default:** `database` + +**Description:** + +Determines whether to use the Kong database +(either PostgreSQL or Cassandra, as defined +by the 'database' config value above), or a +separate storage engine, for Vitals metrics. + +Accepted values are 'database', 'prometheus', +or 'influxdb'. + + +### vitals_tsdb_address + +**Default:** `nil` + +**Description:** + +Defines the host and port of the TSDB server +to which Vitals data is written and read. +This value is only applied when the +'vitals_strategy` option is set to +'prometheus' or 'influxdb'. This value +accepts IPv4, IPv6, and hostname values. +If the 'vitals_strategy' is set to +'prometheus', this value determines the +address of the Prometheus server from which +Vitals data will be read. For 'influxdb' +strategies, this value controls both the read +and write source for Vitals data. + + +### vitals_statsd_address + +**Default:** `nil` + +**Description:** + +Defines the host and port (and an optional +protocol) of the StatsD server to which +Kong should write Vitals metics. This value +is only applied when the 'vitals_strategy' is +set to 'prometheus'. This value accepts IPv4, +IPv6, and, hostnames. Additionally, the suffix +'tcp' can be specified; doing so will result +in Kong sending StatsD metrics via TCP +instead of the UDP (default). + + +### vitals_statsd_prefix + +**Default:** `kong` + +**Description:** + +Defines the prefix value attached to all +Vitals StatsD events. This prefix is useful +when writing metrics to a multi-tenant StatsD +exporter or server. + + +### vitals_statsd_udp_packet_size + +**Default:** `1024` + +**Description:** + +Defines the maximum buffer size in +which Vitals statsd metrics will be +held and sent in batches. +This value is defined in bytes. + + +### vitals_prometheus_scrape_interval + +**Default:** `5` + +**Description:** + +Defines the scrape_interval query +parameter sent to the Prometheus +server when reading Vitals data. +This should be same as the scrape +interval (in seconds) of the +Prometheus server. + + +## Dev Portal + + +### portal + +**Default:** `off` + +**Description:** + +Enable or disable the Dev Portal Interface and API + +When enabled, Kong will expose the Kong Dev Portal Files endpoint and the +public Dev Portal Files API. + +**Example:** + +``` +portal = on +``` + + +### portal_gui_listen + +**Default:** `0.0.0.0:8003, 0.0.0.0:8446 ssl` + +**Description:** + +Comma-separated list of addresses on which Kong will +expose the Kong Dev Portal GUI. Suffixes can be +specified for each pair, similar to the `admin_listen` +directive. + +**Example:** + +``` +portal_gui_listen = 0.0.0.0:8003, 0.0.0.0:8446 ssl +``` + + +### portal_gui_protocol + +**Default:** `http` + +**Description:** + +The Dev Portal URL protocol + +Provide the protocol used in conjunction with portal_gui_host to construct the +lookup, or balancer address for Kong Proxy nodes. + +**Example:** + +``` +portal_gui_protocol = http +``` + + +### portal_gui_host + +**Default** `127.0.0.1:8003` + +**Description** + +Dev Portal GUI Host + +Provide the host unsed in conjunction with portal_gui_protocol to construct the +lookup, or balancer address for Kong Proxy nodes. + +**Example:** + +``` +portal_gui_host = localhost:8003 +``` + +### portal_cors_origins + +**Default:** `nil` + +**Description:** + +A comma separated list of allowed domains for `Access-Control-Allow-Origin` +header. This can be used to resolve CORS issues in custom networking +environments. + +**Example:** + +``` +portal_cors_origins = http://localhost:8003, https://localhost:8004 +``` + +### portal_gui_use_subdomains + +**Default** `Off` + +**Description** + +Enable workspaced Dev Portals to use subdomains + +By default the Dev Portal will use the first namespace in the request path to +determine the workspace. By enabling subdomains, the Dev Portal will expect the +workspace to be included in the request url as a subdomain + +**Example** + +``` +portal_gui_use_subdomains = off + - ://// + - http://kong-portal.com/example-workspace/index + +portal_gui_use_subdomains = on + - ://. + - http://example-workspace.kong-portal.com/index +``` + + +### portal_gui_ssl_cert + +**Default:** `NONE` (auto generated) + +**Description:** + +The absolute path to the SSL certificate for `portal_gui_listen` values with +SSL enabled. + +**Example:** + +``` +portal_gui_ssl_cert = /path/to/portal_gui_ssl.cert +``` + + +### portal_gui_ssl_cert_key + +**Default:** `NONE` (auto-generated) + +**Description:** + +The absolute path to the SSL key for `portal_gui_listen` values with SSL +enabled. + +**Example:** + +``` +portal_gui_ssl_key = /path/to/portal_gui_ssl.key +``` + + +### portal_api_listen + +**Default:** `0.0.0.0:8004, 0.0.0.0:8447 ssl` + +**Description:** +Comma-separated list of addresses on which Kong will +expose the Dev Portal API. Suffixes can be +specified for each pair, similarly to +the `admin_listen` directive. + +``` +portal_api_listen = 0.0.0.0:8004, 0.0.0.0:8447 ssl +``` + + +### portal_api_url + +**Default:** `nil` + +**Description:** + +The address on which the Dev Portal API is accessible by Kong. + +When not provided, Kong will use the listeners defined on `portal_api_listen` as +the value. + +**Example:** + +``` +portal_api_url = https://portal-api.domain.tld +``` + + +### portal_api_ssl_cert + +**Default:** `NONE` (auto generated) + +**Description:** + +Dev Portal API SSL Certificate. + +The absolute path to the SSL certificate for +`portal_api_listen` values with SSL enabled. + +**Example:** + +``` +portal_api_ssl_cert = /path/to/portal_api_ssl.cert +``` + + +### portal_api_ssl_cert_key + +**Default:** `NONE` (auto generated) + +**Description:** + +Dev Portal API SSL Certificate Key. + +The absolute path to the SSL key for +`portal_api_listen` values with SSL enabled. + +**Example:** + +``` +portal_api_ssl_cert_key = /path/to/portal_api_ssl_cert.key +``` + + +### portal_api_access_log + +**Default:** `logs/portal_api_access.log` + +**Description:** + +Location of log containing all calls made to the Portal API. + +`portal_api_access.log` location can be absolute or relative. When using +relative pathing, logs will be placed under the `prefix` location. + +Setting this value to `off` will disable logging +Portal API access logs. + +**Example:** + +``` +portal_api_access_log = logs/portal_api_access.log +``` + + +### portal_api_error_log + +**Default:** `logs/error.log` + +**Description:** + +Developer Portal API Error Log location. + +Here you can set an absolute or relative path for your +Portal API access logs. + +Setting this value to `off` will disable logging +Portal API access logs. + +When using relative pathing, logs will be placed under +the `prefix` location. + +Granularity can be adjusted through the `log_level` +directive. + +### portal_is_legacy + +**Default:** `off` + +**Description:** + +Developer Portal legacy support + +Setting this value to `on` causes all new +portals to render using the legacy rendering system by default. + +Setting this value to `off` causes all new +portals to render using the current rendering system. + + +## Default Dev Portal Authentication + +Referenced on workspace creation to set Dev Portal authentication defaults +in the database for that particular workspace. + + +### portal_auth + +**Default:** `nil` + +**Description:** + +Use `portal_auth` to specify the authentication plugin +to apply to your Dev Portal. Developers +will use the specified form of authentication +to request access, register, and login to your +Dev Portal. + +**Example (Basic Auth):** + +``` +portal_auth = basic-auth +``` + +### portal_auth_password_complexity + +**Default:** `nil` + +**Description:** + +Dev Portals that are authenticated with the **Basic Auth** plugin support password complexity enforcement using either a predned Kong preset or custom rules. + +Kong's Preset requires passwords contain characters from at least three of the following categories: + +1. Uppercase characters (A through Z) +2. Lowercase characters (a through z) +3. Base-10 digits (0 through 9) +4. Special characters (&, $, #, % etc) + +To write your own rules, see (https://manpages.debian.org/jessie/passwdqc/passwdqc.conf.5.en.html) + +>NOTE: Only the keywords "min", "max", and "passphrase" + +**Examples:** + +``` +portal_auth_password_complexity = { "kong-preset": "min_8"} +``` + +``` +portal_auth_password_complexity = { "min": "12", max: "24"} +``` + + +### portal_auth_conf + +**Default:** `nil` + +**Description:** + +Here you can specify authentication plugin configuration +via JSON Object format to be applied to your Developer +Portal auth plugin. For information about Plugin Configuration +consult the associated plugin documentation. + +**Example (Basic Auth):** + +``` +portal_auth_conf = { "hide_credentials": true } +``` + +### portal_auth_login_attempts + +**Default:** 0 + +**Description:** + +Dictates the number of times a user can attempt to log into the Developer Portal before the password must be reset. + +The default value of '0' allows infinite attempts. + +>NOTE: This configuration only applies to Developer Portals using `Basic Auth` for authentication. + + +### portal_auto_approve + +**Default:** `off` + +**Description:** + +When this flag is set to 'on', a developer will automatically be marked as +"approved" after completing registration. Access can still be revoked through the +Kong Manager or Admin API. + + +### portal_session_conf + +**Default:** `nil` + +**Description:** + +Portal Session Plugin Config (JSON) + +Here you may specify the configuration for the Session plugin as use by Kong +Dev Portal. + +**Example:** +``` +portal_session_conf= {"cookie_name": "portal_session", "secret":"changeme", "storage":"kong"} +``` + + +### portal_token_exp + +**Default:** `21600` + +**Description:** + +Duration in seconds for the expiration of the Dev Portal reset password token. +Default `21600` is six hours. + +### portal_email_verification + +**Default:** `off` + +**Description:** + +When enabled, Developers receive an email upon +registration to verify their account. Developers are +not able to use the Developer Portal until they +verify their account. + +Note: SMTP must be turned on in order to use this feature. + +## Default Dev Portal SMTP Configuration + +Referenced on workspace creation to set SMTP defaults in the database +for that particular workspace. + + +### portal_invite_email + +**Default:** `on` + +**Description:** + +When enabled, Admins will be able to invite Developers to a Dev Portal by +using the "Invite" button in the Kong Manager. + + +### portal_access_request_email + +**Default:** `on` + +**Description:** + +When enabled, Admins specified by `smtp_admin_emails` will receive an email +when a Developer requests access to a Dev Portal. + + +### portal_approved_email + +**Default:** `on` + +**Description:** + +When enabled, Developers will receive an email when access to a Dev Portal has +been approved. + + +### portal_reset_email + +**Default:** `on` + +**Description:** + +When enabled, Developers will be able to use the "Reset Password" flow on a +Dev Portal and will receive an email with password reset instructions. + +When disabled, Developers will *not* be able to reset their account passwords. + + +### portal_reset_success_email + +**Default:** `on` + +**Description:** + +When enabled, Developers will receive an email after successfully reseting +their Dev Portal account password. + +When disabled, Developers will still be able to reset their account passwords, +but will not recieve a confirmation email. + + +### portal_emails_from + +**Default:** `nil` + +**Description:** + +The name and email address for the 'From' header included in all Dev Portal emails. + +**Example :** + +``` +portal_emails_from = Your Name +``` + +⚠️ **IMPORTANT:** Some SMTP servers may require valid email addresses + + +### portal_emails_reply_to + +**Default:** `nil` + +**Description:** + +The email address for the 'Reply-To' header included in all Dev Portal emails. + +**Example :** + +``` +portal_emails_reply_to: noreply@example.com +``` + +⚠️ **IMPORTANT:** Some SMTP servers may require valid email addresses + + +## Admin SMTP Configuration + + +### admin_emails_from + +**Default:** `""` + +**Description:** + +The email address for the 'From' header included in Admin emails + +**Example :** + +``` +admin_emails_from = "example@example.com" +``` + + +### admin_emails_reply_to + +**Default:** `nil` + +**Description:** + +The email address for the 'Reply-To' header included in Admin emails + +**Example :** + +``` +admin_emails_reply_to = admin@example.com +``` + + +### admin_invitation_expiry + +**Default:** `259200` + +**Description:** + +Expiration time in seconds for Admin invitation links. Set to zero for no +expiration. + + +## General SMTP Configuration + + +### smtp_mock + +**Default:** `on` + +**Description:** + +When enabled this flag will only mock the sending of emails and will not +attempt to send actual emails. This can be used for testing before the SMTP +client is fully configured. + +**Examples:** + +`smtp_mock = on` Emails will NOT attempt send. +`smtp_mock = off` Emails will attempt send. + + +### smtp_host + +**Default:** `nil` + +**Description:** +The host of the SMTP server to connect to. + + +### smtp_port + +**Default:** `nil` + +**Description:** + +The port number on SMTP server to connect to. + + +### smtp_starttls + +**Default:** `nil` + +**Description:** + +When set to `on`, STARTTLS is used to encrypt communication with the SMTP +server. This is normally used in conjunction with port 587. + + +### smtp_username + +**Default:** `nil` + +**Description:** + +Username used for authentication with the SMTP server. + + +### smtp_password + +**Default:** `nil` + +**Description:** + +Password used for authentication with the SMTP server. + + +### smtp_ssl + +**Default:** `nil` + +**Description:** + +When set to `on` SMTPS is used to encrypt communication with the SMTP server. +This is normally used in conjunction with port 465. + + +### smtp_auth_type + +**Default:** `nil` + +**Description:** + +The method used to authenticate with the SMTP server. Valid options are +`plain`, `login`, or `nil`. + + +### smtp_domain + +**Default:** `localhost.localdomain` + +**Description:** + +The domain used in the `EHLO` connect and part of the `Message-ID` header. + + +### smtp_timeout_connect + +**Default:** `60000` + +**Description:** + +The timeout in milliseconds for connecting to the SMTP server. + + +### smtp_timeout_send + +**Default:** `60000` + +**Description:** + +The timeout in milliseconds for sending data to the SMTP server. + + +### smtp_timeout_read + +**Default:** `60000` + +**Description:** + +The timeout in milliseconds for reading data from the SMTP server. + + +### smtp_admin_emails + +**Default:** `nil` + +**Description:** + +Comma separated list of Admin emails to receive notifications. + +**Example :** + +``` +smtp_admin_emails = admin1@example.com, admin2@example.com +``` + + +## Data & Admin Audit + +When enabled, Kong will store detailed audit data regarding Admin API and +database access. In most cases, updates to the database are associated with +Admin API requests. As such, database object audit log data is tied to a +given HTTP via a unique identifier, providing built-in association of Admin +API and database traffic. + + +### audit_log + +**Default:** `off` + +**Description:** + +When enabled, Kong will log information about Admin API access and database +row insertions, updates, and deletes. + + +### audit_log_ignore_methods + +**Default:** `nil` + +**Description:** + +Comma-separated list of HTTP methods that will not generate audit log entries. +By default, all HTTP requests will be logged. + + +### audit_log_ignore_paths + +**Default:** `nil` + +**Description:** + +Comma-separated list of request paths that will not generate audit log entries. +By default, all HTTP requests will be logged. + + +### audit_log_ignore_tables + +**Default:** `nil` + +**Description:** + +Comma-separated list of database tables that will not generate audit log +entries. By default, updates to all database tables will be logged (the +term "updates" refers to the creation, update, or deletion of a row). + + +### audit_log_record_ttl + +**Default:** `2592000` + +**Description:** + +Length, in seconds, of the TTL for audit log records. Records in the database +older than their TTL are automatically purged. + + +### audit_log_signing_key + +**Default:** `nil` + +**Description:** + +Defines the path to a private RSA signing key that can be used to insert a +signature of audit records, adjacent to the record. The corresponding public +key should be stored offline, and can be used the validate audit entries in +the future. If this value is undefined, no signature will be generated. + +## Granular Tracing + +Granular tracing offers a mechanism to expose metrics and detailed debug data +about the lifecycle of Kong in a human, or machine, consumable format. + +### tracing + +**Default:** `off` + +**Description:** + +When enable, Kong will generate granular debug data about various portions of the +request lifecycle, such as DB or DNS queries, plugin execution, core handler timing, +etc. + +### tracing_write_strategy + +**Default:** `file` + +**Description** + +Defines how Kong will write tracing data at the conclusion of the request. The + default option, `file`, writes a human-readable depiction of tracing data to a + configurable location on the node's file system. Other strategies write tracing + data as a JSON document to the configured endpoint. Valid entries for this + option are `file`, `file_raw`, `http`, `tcp`, `tls`, and `udp`. + +### tracing_write_endpoint + +**Default:** `nil` + +**Description:** + +Defines the endpoint to which tracing data will be written. For the 'file' and +'file_raw' tracing write strategies, this value must be a valid location on the +node's file system to which Kong must have write access. + +For the `tcp`, `tls`, and `udp` strategies, this value is defined as a string in +the form of: + +``` + : +``` + + For the `http` strategy, this value is defined in the form of: +``` + ://(:(/)) +``` + Traces sent via HTTP are delivered via POST method with an `application/json` + Content-Type. + +### tracing_time_threshold + +**Default:** `0` + +**Description:** + +The minimum time, in microseconds, over which a trace must execute in order to + write the trace data to the configured endpoint. This configuration can be used + to lower the noise present in trace data by removing trace objects that are not + interesting from a timing perspective. The default value of '0' removes this + limitation, causing traces of any duration to be written. + +### tracing_types + +**Default:** `all` + +**Description:** + +Defines the types of traces that are written. Trace types not defined in this +list are ignored, regardless of their lifetime. The default special value of +'all' results in all trace types being written, regardless of type. Included +trace types are: `query`,`legacy_query`, `router`, `balancer.getPeer`, ` +balancer.toip`, `connect.toip`, `access.before`, and `access.after` +`cassandra_iterate`, and `plugin`. + +### tracing_debug_header + +**Default:** `nil` + +**Description:** + +Defines the name of the HTTP request header that must be present in order to +generate traces within a request. Setting this value provides a mechanism to +selectively generate request traces at the client's request. Note that the value +of the header does not matter, only that the header is present in the request. +When this value is not set and tracing is enabled, Kong will generate trace data +for all requests flowing through the proxy and Admin API. + +Note: Data from certificate handling phases is not logged when this setting is enabled. + +### generate_trace_details + +**Default:** `off` + +**Description:** + +When enabled, Kong will write context-specific details into traces. Trace details +offer more data about the context of the trace. This can significantly increase +the size of trace reports. Note also that trace details may contain potentially +sensitive information, such as raw SQL queries; care should be taken to store +traces properly when this option is enabled. + + +## Route Collision Detection and Prevention + +### route_validation_strategy + +**Default:** `smart` + +The strategy used to validate +routes when creating or updating them. +Different strategies are available to tune +how to enforce splitting traffic of +workspaces. + +- 'smart' is the default option and uses the algorithm described in +- 'off' disables any check +- 'path' enforces routes to comply with the pattern described in config enforce_route_path_pattern + +### enforce_route_path_pattern + +**Default:** `nil` + +Here you can specify Lua pattern to enforce +on a `path` attributes of a route object. You can also add a +placeholder for workspace in pattern to render during runtime based +on the workspace to which the `route` belongs. It is a +field if 'route_validation_strategy' is set to 'path' + +**Example:** +For Pattern '/$(workspace)/v%d/.*' valid path are: + +1. '/group1/v1/' if route belongs to workspace 'group1'. +2. '/group2/v1/some_path' if route belongs to workspace 'group2'. + + +## Workspaces + + +### route_validation_strategy + +**Default:** `smart` + +The strategy used to validate routes when creating or updating them. +Different strategies are available to tune how to enforce splitting +traffic of workspaces. + +- `smart` is the default option and uses the algorithm described in [this example](https://docs.konghq.com/enterprise/0.37-x/workspaces/examples/#important-note-conflicting-apis-or-routes-in-workspaces) + +- `off` disables all checks. + +- `path` enforces routes to comply with the pattern described in +config enforce_route_path_pattern. + +### enforce_route_path_pattern + +**Default:** `nil` + +Here you can specify Lua pattern which will be enforced on a `path` +attributes of a route object. You can also add a placeholder for +workspace in pattern, which will be rendered during runtime based on +workspace to which `route` belongs to. It a field if +'route_validation_strategy' is set to 'path' + +Example: + +For Pattern `/$(workspace)/v%d/.*` valid path are: +1. `/group1/v1/` if route belongs to workspace 'group1'. +2. `/group2/v1/some_path` if route belongs to workspace 'group2'. diff --git a/app/enterprise/1.3-x/proxy.md b/app/enterprise/1.3-x/proxy.md new file mode 100644 index 000000000000..090e753c5c35 --- /dev/null +++ b/app/enterprise/1.3-x/proxy.md @@ -0,0 +1,1130 @@ +--- +title: Proxy Reference +--- + +## Introduction + +In this document we will cover Kong's **proxying capabilities** by explaining +its routing capabilities and internal workings in details. + +Kong exposes several interfaces which can be tweaked by two configuration +properties: + +- `proxy_listen`, which defines a list of addresses/ports on which Kong will + accept **public traffic** from clients and proxy it to your upstream services + (`8000` by default). +- `admin_listen`, which also defines a list of addresses and ports, but those + should be restricted to only be accessed by administrators, as they expose + Kong's configuration capabilities: the **Admin API** (`8001` by default). + +
+

Note: Starting with Kong 1.0.0 and Kong Enterprise 0.35, the API entity has been removed. +This document will cover proxying with the new Routes and +Services entities.

+

See an older version of this document if you are using 0.12 or +below.

+
+ +## Terminology + +- `client`: Refers to the *downstream* client making requests to Kong's + proxy port. +- `upstream service`: Refers to your own API/service sitting behind Kong, to + which client requests are forwarded. +- `Service`: Service entities, as the name implies, are abstractions of each of + your own upstream services. Examples of Services would be a data + transformation microservice, a billing API, etc. +- `Route`: This refers to the Kong Routes entity. Routes are entrypoints into + Kong, and defining rules for a request to be matched, and routed to a given + Service. +- `Plugin`: This refers to Kong "plugins", which are pieces of business logic + that run in the proxying lifecycle. Plugins can be configured through the + Admin API - either globally (all incoming traffic) or on specific Routes + and Services. + +[Back to TOC](#table-of-contents) + +## Overview + +From a high-level perspective, Kong listens for HTTP traffic on its configured +proxy port(s) (`8000` and `8443` by default). Kong will evaluate any incoming +HTTP request against the Routes you have configured and try to find a matching +one. If a given request matches the rules of a specific Route, Kong will +process proxying the request. Because each Route is linked to a Service, Kong +will run the plugins you have configured on your Route and its associated +Service, and then proxy the request upstream. + +You can manage Routes via Kong's Admin API. The `hosts`, `paths`, and `methods` +attributes of Routes define rules for matching incoming HTTP requests. + +If Kong receives a request that it cannot match against any of the configured +Routes (or if no Routes are configured), it will respond with: + +```http +HTTP/1.1 404 Not Found +Content-Type: application/json +Server: kong/ + +{ + "message": "no route and no Service found with those values" +} +``` + +[Back to TOC](#table-of-contents) + +## Reminder: How to configure a Service + +The [Configuring a Service][configuring-a-service] quickstart guide explains +how Kong is configured via the [Admin API][API]. + +Adding a Service to Kong is done by sending an HTTP request to the Admin API: + +```bash +$ curl -i -X POST http://localhost:8001/services/ \ + -d 'name=foo-service' \ + -d 'url=http://foo-service.com' +HTTP/1.1 201 Created +... + +{ + "connect_timeout": 60000, + "created_at": 1515537771, + "host": "foo-service.com", + "id": "d54da06c-d69f-4910-8896-915c63c270cd", + "name": "foo-service", + "path": "/", + "port": 80, + "protocol": "http", + "read_timeout": 60000, + "retries": 5, + "updated_at": 1515537771, + "write_timeout": 60000 +} +``` + +This request instructs Kong to register a Service named "foo-service", which +points to `http://foo-service.com` (your upstream). + +**Note:** the `url` argument is a shorthand argument to populate the +`protocol`, `host`, `port`, and `path` attributes at once. + +Now, in order to send traffic to this Service through Kong, we need to specify +a Route, which acts as an entrypoint to Kong: + +```bash +$ curl -i -X POST http://localhost:8001/routes/ \ + -d 'hosts[]=example.com' \ + -d 'paths[]=/foo' \ + -d 'service.id=d54da06c-d69f-4910-8896-915c63c270cd' +HTTP/1.1 201 Created +... + +{ + "created_at": 1515539858, + "hosts": [ + "example.com" + ], + "id": "ee794195-6783-4056-a5cc-a7e0fde88c81", + "methods": null, + "paths": [ + "/foo" + ], + "preserve_host": false, + "priority": 0, + "protocols": [ + "http", + "https" + ], + "service": { + "id": "d54da06c-d69f-4910-8896-915c63c270cd" + }, + "strip_path": true, + "updated_at": 1515539858 +} +``` + +We have now configured a Route to match incoming requests matching the given +`hosts` and `paths`, and forward them to the `foo-service` we configured, thus +proxying this traffic to `http://foo-service.com`. + +Kong is a transparent proxy, and it will by default forward the request to your +upstream service untouched, with the exception of various headers such as +`Connection`, `Date`, and others as required by the HTTP specifications. + +[Back to TOC](#table-of-contents) + +## Routes and matching capabilities + +Let's now discuss how Kong matches a request against the configured `hosts`, +`paths` and `methods` properties (or fields) of a Route. Note that all three of +these fields are **optional**, but at least **one of them** must be specified. + +For a request to match a Route: + +- The request **must** include **all** of the configured fields +- The values of the fields in the request **must** match at least one of the + configured values (While the field configurations accepts one or more values, + a request needs only one of the values to be considered a match) + +Let's go through a few examples. Consider a Route configured like this: + +```json +{ + "hosts": ["example.com", "foo-service.com"], + "paths": ["/foo", "/bar"], + "methods": ["GET"] +} +``` + +Some of the possible requests matching this Route would look like: + +```http +GET /foo HTTP/1.1 +Host: example.com +``` + +```http +GET /bar HTTP/1.1 +Host: foo-service.com +``` + +```http +GET /foo/hello/world HTTP/1.1 +Host: example.com +``` + +All three of these requests satisfy all the conditions set in the Route +definition. + +However, the following requests would **not** match the configured conditions: + +```http +GET / HTTP/1.1 +Host: example.com +``` + +```http +POST /foo HTTP/1.1 +Host: example.com +``` + +```http +GET /foo HTTP/1.1 +Host: foo.com +``` + +All three of these requests satisfy only two of configured conditions. The +first request's path is not a match for any of the configured `paths`, same for +the second request's HTTP method, and the third request's Host header. + +Now that we understand how the `hosts`, `paths`, and `methods` properties work +together, let's explore each property individually. + +[Back to TOC](#table-of-contents) + +### Request Host header + +Routing a request based on its Host header is the most straightforward way to +proxy traffic through Kong, especially since this is the intended usage of the +HTTP Host header. Kong makes it easy to do via the `hosts` field of the Route +entity. + +`hosts` accepts multiple values, which must be comma-separated when specifying +them via the Admin API: + +`hosts` accepts multiple values, which is straightforward to represent in a +JSON payload: + +```bash +$ curl -i -X POST http://localhost:8001/routes/ \ + -H 'Content-Type: application/json' \ + -d '{"hosts":["example.com", "foo-service.com"]}' +HTTP/1.1 201 Created +... +``` + +But since the Admin API also supports form-urlencoded content types, you +can specify an array via the `[]` notation: + +```bash +$ curl -i -X POST http://localhost:8001/routes/ \ + -d 'hosts[]=example.com' \ + -d 'hosts[]=foo-service.com' +HTTP/1.1 201 Created +... +``` + +To satisfy the `hosts` condition of this Route, any incoming request from a +client must now have its Host header set to one of: + +``` +Host: example.com +``` + +or: + +``` +Host: foo-service.com +``` + +[Back to TOC](#table-of-contents) + +#### Using wildcard hostnames + +To provide flexibility, Kong allows you to specify hostnames with wildcards in +the `hosts` field. Wildcard hostnames allow any matching Host header to satisfy +the condition, and thus match a given Route. + +Wildcard hostnames **must** contain **only one** asterisk at the leftmost +**or** rightmost label of the domain. Examples: + +- `*.example.com` would allow Host values such as `a.example.com` and + `x.y.example.com` to match. +- `example.*` would allow Host values such as `example.com` and `example.org` + to match. + +A complete example would look like this: + +```json +{ + "hosts": ["*.example.com", "service.com"] +} +``` + +Which would allow the following requests to match this Route: + +```http +GET / HTTP/1.1 +Host: an.example.com +``` + +```http +GET / HTTP/1.1 +Host: service.com +``` + +[Back to TOC](#table-of-contents) + +#### The `preserve_host` property + +When proxying, Kong's default behavior is to set the upstream request's Host +header to the hostname specified in the Service's `host`. The +`preserve_host` field accepts a boolean flag instructing Kong not to do so. + +For example, when the `preserve_host` property is not changed and a Route is +configured like so: + +```json +{ + "hosts": ["service.com"], + "service": { + "id": "..." + } +} +``` + +A possible request from a client to Kong could be: + +```http +GET / HTTP/1.1 +Host: service.com +``` + +Kong would extract the Host header value from the Service's `host` property, , +and would send the following upstream request: + +```http +GET / HTTP/1.1 +Host: +``` + +However, by explicitly configuring a Route with `preserve_host=true`: + +```json +{ + "hosts": ["service.com"], + "preserve_host": true, + "service": { + "id": "..." + } +} +``` + +And assuming the same request from the client: + +```http +GET / HTTP/1.1 +Host: service.com +``` + +Kong would preserve the Host on the client request and would send the following +upstream request instead: + +```http +GET / HTTP/1.1 +Host: service.com +``` + +[Back to TOC](#table-of-contents) + +### Request path + +Another way for a Route to be matched is via request paths. To satisfy this +routing condition, a client request's path **must** be prefixed with one of the +values of the `paths` attribute. + +For example, with a Route configured like so: + +```json +{ + "paths": ["/service", "/hello/world"] +} +``` + +The following requests would be matched: + +```http +GET /service HTTP/1.1 +Host: example.com +``` + +```http +GET /service/resource?param=value HTTP/1.1 +Host: example.com +``` + +```http +GET /hello/world/resource HTTP/1.1 +Host: anything.com +``` + +For each of these requests, Kong detects that their URL path is prefixed with +one of the Routes's `paths` values. By default, Kong would then proxy the +request upstream without changing the URL path. + +When proxying with path prefixes, **the longest paths get evaluated first**. +This allow you to define two Routes with two paths: `/service` and +`/service/resource`, and ensure that the former does not "shadow" the latter. + +[Back to TOC](#table-of-contents) + +#### Using regexes in paths + +Kong supports regular expression pattern matching for an Route's `paths` field +via [PCRE](http://pcre.org/) (Perl Compatible Regular Expression). You can +assign paths as both prefixes and regexes to a Route at the same time. + +For example, if we consider the following Route: + +```json +{ + "paths": ["/users/\d+/profile", "/following"] +} +``` + +The following requests would be matched by this Route: + +```http +GET /following HTTP/1.1 +Host: ... +``` + +```http +GET /users/123/profile HTTP/1.1 +Host: ... +``` + +The provided regexes are evaluated with the `a` PCRE flag (`PCRE_ANCHORED`), +meaning that they will be constrained to match at the first matching point +in the path (the root `/` character). + +[Back to TOC](#table-of-contents) + +##### Evaluation order + +As previously mentioned, Kong evaluates prefix paths by length: the longest +prefix paths are evaluated first. However, Kong will evaluate regex paths based +on the `regex_priority` attribute of Routes from highest priority to lowest. +Regex paths are furthermore evaluated before prefix paths. + +Consider the following Routes: + +```json +[ + { + "paths": ["/status/\d+"], + "regex_priority": 0 + }, + { + "paths": ["/version/\d+/status/\d+"], + "regex_priority": 6 + }, + { + "paths": ["/version"], + }, + { + "paths": ["/version/any/"], + } +] +``` + +In this scenario, Kong will evaluate incoming requests against the following +defined URIs, in this order: + +1. `/version/\d+/status/\d+` +2. `/status/\d+` +3. `/version/any/` +4. `/version` + +Take care to avoid writing regex rules that are overly broad and may consume +traffic intended for a prefix rule. Adding a rule with the path `/version/.*` to +the ruleset above would likely consume some traffic intended for the `/version` +prefix path. If you see unexpected behavior, sending `X-Kong-Debug: 1` in your +request headers will indicate the matched Route ID in the response headers for +troubleshooting purposes. + +As usual, a request must still match a Route's `hosts` and `methods` properties +as well, and Kong will traverse your Routes until it finds one that [matches +the most rules](#matching-priorities). + +[Back to TOC](#table-of-contents) + +##### Capturing groups + +Capturing groups are also supported, and the matched group will be extracted +from the path and available for plugins consumption. If we consider the +following regex: + +``` +/version/(?\d+)/users/(?\S+) +``` + +And the following request path: + +``` +/version/1/users/john +``` + +Kong will consider the request path a match, and if the overall Route is +matched (considering the `hosts` and `methods` fields), the extracted capturing +groups will be available from the plugins in the `ngx.ctx` variable: + +```lua +local router_matches = ngx.ctx.router_matches + +-- router_matches.uri_captures is: +-- { "1", "john", version = "1", user = "john" } +``` + +[Back to TOC](#table-of-contents) + +##### Escaping special characters + +Next, it is worth noting that characters found in regexes are often +reserved characters according to +[RFC 3986](https://tools.ietf.org/html/rfc3986) and as such, +should be percent-encoded. **When configuring Routes with regex paths via the +Admin API, be sure to URL encode your payload if necessary**. For example, +with `curl` and using an `application/x-www-form-urlencoded` MIME type: + +```bash +$ curl -i -X POST http://localhost:8001/routes \ + --data-urlencode 'uris[]=/status/\d+' +HTTP/1.1 201 Created +... +``` + +Note that `curl` does not automatically URL encode your payload, and note the +usage of `--data-urlencode`, which prevents the `+` character to be URL decoded +and interpreted as a space ` ` by Kong's Admin API. + +[Back to TOC](#table-of-contents) + +#### The `strip_path` property + +It may be desirable to specify a path prefix to match a Route, but not +include it in the upstream request. To do so, use the `strip_path` boolean +property by configuring a Route like so: + +```json +{ + "paths": ["/service"], + "strip_path": true, + "service": { + "id": "..." + } +} +``` + +Enabling this flag instructs Kong that when matching this Route, and proceeding +with the proxying to a Service, it should **not** include the matched part of +the URL path in the upstream request's URL. For example, the following +client's request to the above Route: + +```http +GET /service/path/to/resource HTTP/1.1 +Host: ... +``` + +Will cause Kong to send the following upstream request: + +```http +GET /path/to/resource HTTP/1.1 +Host: ... +``` + +The same way, if a regex path is defined on a Route that has `strip_path` +enabled, the entirety of the request URL matching sequence will be stripped. +Example: + +```json +{ + "paths": ["/version/\d+/service"], + "strip_path": true, + "service": { + "id": "..." + } +} +``` + +The following HTTP request matching the provided regex path: + +```http +GET /version/1/service/path/to/resource HTTP/1.1 +Host: ... +``` + +Will be proxied upstream by Kong as: + +```http +GET /path/to/resource HTTP/1.1 +Host: ... +``` + +[Back to TOC](#table-of-contents) + +### Request HTTP method + +The `methods` field allows matching the requests depending on their HTTP +method. It accepts multiple values. Its default value is empty (the HTTP +method is not used for routing). + +The following Route allows routing via `GET` and `HEAD`: + +```json +{ + "methods": ["GET", "HEAD"], + "service": { + "id": "..." + } +} +``` + +Such a Route would be matched with the following requests: + +```http +GET / HTTP/1.1 +Host: ... +``` + +```http +HEAD /resource HTTP/1.1 +Host: ... +``` + +But it would not match a `POST` or `DELETE` request. This allows for much more +granularity when configuring plugins on Routes. For example, one could imagine +two Routes pointing to the same service: one with unlimited unauthenticated +`GET` requests, and a second one allowing only authenticated and rate-limited +`POST` requests (by applying the authentication and rate limiting plugins to +such requests). + +[Back to TOC](#table-of-contents) + +## Matching priorities + +A Route may define matching rules based on its `hosts`, `paths`, and `methods` +fields. For Kong to match an incoming request to a Route, all existing fields +must be satisfied. However, Kong allows for quite some flexibility by allowing +two or more Routes to be configured with fields containing the same values - +when this occurs, Kong applies a priority rule. + +The rule is: **when evaluating a request, Kong will first try to match the +Routes with the most rules**. + +For example, if two Routes are configured like so: + +```json +{ + "hosts": ["example.com"], + "service": { + "id": "..." + } +}, +{ + "hosts": ["example.com"], + "methods": ["POST"], + "service": { + "id": "..." + } +} +``` + +The second Route has a `hosts` field **and** a `methods` field, so it will be +evaluated first by Kong. By doing so, we avoid the first Route "shadowing" +calls intended for the second one. + +Thus, this request will match the first Route + +```http +GET / HTTP/1.1 +Host: example.com +``` + +And this request will match the second one: + +```http +POST / HTTP/1.1 +Host: example.com +``` + +Following this logic, if a third Route was to be configured with a `hosts` +field, a `methods` field, and a `uris` field, it would be evaluated first by +Kong. + +[Back to TOC](#table-of-contents) + +## Proxying behavior + +The proxying rules above detail how Kong forwards incoming requests to your +upstream services. Below, we detail what happens internally between the time +Kong *matches* an HTTP request with a registered Route, and the actual +*forwarding* of the request. + +[Back to TOC](#table-of-contents) + +### 1. Load balancing + +Kong implements load balancing capabilities to distribute proxied +requests across a pool of instances of an upstream service. + +You can find more information about configuring load balancing by consulting +the [Load Balancing Reference][load-balancing-reference]. + +[Back to TOC](#table-of-contents) + +### 2. Plugins execution + +Kong is extensible via "plugins" that hook themselves in the request/response +lifecycle of the proxied requests. Plugins can perform a variety of operations +in your environment and/or transformations on the proxied request. + +Plugins can be configured to run globally (for all proxied traffic) or on +specific Routes and Services. In both cases, you must create a [plugin +configuration][plugin-configuration-object] via the Admin API. + +Once a Route has been matched (and its associated Service entity), Kong will +run plugins associated to either of those entities. Plugins configured on a +Route run before plugins configured on a Service, but otherwise, the usual +rules of [plugins association][plugin-association-rules] apply. + +These configured plugins will run their `access` phase, which you can find more +information about in the [Plugin development guide][plugin-development-guide]. + +[Back to TOC](#table-of-contents) + +### 3. Proxying & upstream timeouts + +Once Kong has executed all the necessary logic (including plugins), it is ready +to forward the request to your upstream service. This is done via Nginx's +[ngx_http_proxy_module][ngx-http-proxy-module]. You can configure the desired +timeouts for the connection between Kong and a given upstream, via the following +properties of a Service: + +- `upstream_connect_timeout`: defines in milliseconds the timeout for + establishing a connection to your upstream service. Defaults to `60000`. +- `upstream_send_timeout`: defines in milliseconds a timeout between two + successive write operations for transmitting a request to your upstream + service. Defaults to `60000`. +- `upstream_read_timeout`: defines in milliseconds a timeout between two + successive read operations for receiving a request from your upstream + service. Defaults to `60000`. + +Kong will send the request over HTTP/1.1, and set the following headers: + +- `Host: `, as previously described in this document. +- `Connection: keep-alive`, to allow for reusing the upstream connections. +- `X-Real-IP: `, where `$remote_addr` is the variable bearing + the same name provided by + [ngx_http_core_module][ngx-remote-addr-variable]. Please note that the + `$remote_addr` is likely overridden by + [ngx_http_realip_module][ngx-http-realip-module]. +- `X-Forwarded-For:
`, where `
` is the content of + `$realip_remote_addr` provided by + [ngx_http_realip_module][ngx-http-realip-module] appended to the request + header with the same name. +- `X-Forwarded-Proto: `, where `` is the protocol used by + the client. In the case where `$realip_remote_addr` is one of the **trusted** + addresses, the request header with the same name gets forwarded if provided. + Otherwise, the value of the `$scheme` variable provided by + [ngx_http_core_module][ngx-scheme-variable] will be used. +- `X-Forwarded-Host: `, where `` is the host name sent by + the client. In the case where `$realip_remote_addr` is one of the **trusted** + addresses, the request header with the same name gets forwarded if provided. + Otherwise, the value of the `$host` variable provided by + [ngx_http_core_module][ngx-host-variable] will be used. +- `X-Forwarded-Port: `, where `` is the port of the server which + accepted a request. In the case where `$realip_remote_addr` is one of the + **trusted** addresses, the request header with the same name gets forwarded + if provided. Otherwise, the value of the `$server_port` variable provided by + [ngx_http_core_module][ngx-server-port-variable] will be used. + +All the other request headers are forwarded as-is by Kong. + +One exception to this is made when using the WebSocket protocol. If so, Kong +will set the following headers to allow for upgrading the protocol between the +client and your upstream services: + +- `Connection: Upgrade` +- `Upgrade: websocket` + +More information on this topic is covered in the +[Proxy WebSocket traffic][proxy-websocket] section. + +[Back to TOC](#table-of-contents) + +### 4. Errors & retries + +Whenever an error occurs during proxying, Kong will use the underlying +Nginx [retries][ngx-http-proxy-retries] mechanism to pass the request on to +the next upstream. + +There are two configurable elements here: + +1. The number of retries: this can be configured per Service using the + `retries` property. See the [Admin API][API] for more details on this. + +2. What exactly constitutes an error: here Kong uses the Nginx defaults, which + means an error or timeout occurring while establishing a connection with the + server, passing a request to it, or reading the response headers. + +The second option is based on Nginx's +[proxy_next_upstream][proxy_next_upstream] directive. This option is not +directly configurable through Kong, but can be added using a custom Nginx +configuration. See the [configuration reference][configuration-reference] for +more details. + +[Back to TOC](#table-of-contents) + +### 5. Response + +Kong receives the response from the upstream service and sends it back to the +downstream client in a streaming fashion. At this point Kong will execute +subsequent plugins added to the Route and/or Service that implement a hook in +the `header_filter` phase. + +Once the `header_filter` phase of all registered plugins has been executed, the +following headers will be added by Kong and the full set of headers be sent to +the client: + +- `Via: kong/x.x.x`, where `x.x.x` is the Kong version in use +- `X-Kong-Proxy-Latency: `, where `latency` is the time in milliseconds + between Kong receiving the request from the client and sending the request to + your upstream service. +- `X-Kong-Upstream-Latency: `, where `latency` is the time in + milliseconds that Kong was waiting for the first byte of the upstream service + response. + +Once the headers are sent to the client, Kong will start executing +registered plugins for the Route and/or Service that implement the +`body_filter` hook. This hook may be called multiple times, due to the +streaming nature of Nginx. Each chunk of the upstream response that is +successfully processed by such `body_filter` hooks is sent back to the client. +You can find more information about the `body_filter` hook in the [Plugin +development guide][plugin-development-guide]. + +[Back to TOC](#table-of-contents) + +## Configuring a fallback Route + +As a practical use-case and example of the flexibility offered by Kong's +proxying capabilities, let's try to implement a "fallback Route", so that in +order to avoid Kong responding with an HTTP `404`, "no route found", we can +catch such requests and proxy them to a special upstream service, or apply a +plugin to it (such a plugin could, for example, terminate the request with a +different status code or response without proxying the request). + +Here is an example of such a fallback Route: + +```json +{ + "paths": ["/"], + "service": { + "id": "..." + } +} +``` + +As you can guess, any HTTP request made to Kong would actually match this +Route, since all URIs are prefixed by the root character `/`. As we know from +the [Request path][proxy-request-path] section, the longest URL paths are +evaluated first by Kong, so the `/` path will eventually be evaluated last by +Kong, and effectively provide a "fallback" Route, only matched as a last +resort. You can then send traffic to a special Service or apply any plugin you +wish on this Route. + +[Back to TOC](#table-of-contents) + +## Configuring SSL for a Route + +Kong provides a way to dynamically serve SSL certificates on a per-connection +basis. SSL certificates are directly handled by the core, and configurable via +the Admin API. Clients connecting to Kong over TLS must support the [Server +Name Indication][SNI] extension to make use of this feature. + +SSL certificates are handled by two resources in the Kong Admin API: + +- `/certificates`, which stores your keys and certificates. +- `/snis`, which associates a registered certificate with a Server Name + Indication. + +You can find the documentation for those two resources in the +[Admin API Reference][API]. + +Here is how to configure an SSL certificate on a given Route: first, upload +your SSL certificate and key via the Admin API: + +```bash +$ curl -i -X POST http://localhost:8001/certificates \ + -F "cert=@/path/to/cert.pem" \ + -F "key=@/path/to/cert.key" \ + -F "snis=*.ssl-example.com,other-ssl-example.com" +HTTP/1.1 201 Created +... +``` + +The `snis` form parameter is a sugar parameter, directly inserting an SNI and +associating the uploaded certificate to it. + +Note that one of the SNI names defined in `snis` above contains a wildcard +(`*.ssl-example.com`). An SNI may contain a single wildcard in the leftmost (prefix) or +rightmost (suffix) postion. This can be useful when maintaining multiple subdomains. A +single `sni` configured with a wildcard name can be used to match multiple +subdomains, instead of creating an SNI for each. + +Valid wildcard positions are `mydomain.*`, `*.mydomain.com`, and `*.www.mydomain.com`. + +Matching of `snis` respects the following priority: + + 1. plain (no wildcard) + 2. prefix + 3. suffix + +You must now register the following Route within Kong. We will match requests +to this Route using only the Host header for convenience: + +```bash +$ curl -i -X POST http://localhost:8001/routes \ + -d 'hosts=prefix.ssl-example.com,other-ssl-example.com' \ + -d 'service.id=d54da06c-d69f-4910-8896-915c63c270cd' +HTTP/1.1 201 Created +... +``` + +You can now expect the Route to be served over HTTPS by Kong: + +```bash +$ curl -i https://localhost:8443/ \ + -H "Host: prefix.ssl-example.com" +HTTP/1.1 200 OK +... +``` + +When establishing the connection and negotiating the SSL handshake, if your +client sends `prefix.ssl-example.com` as part of the SNI extension, Kong will serve +the `cert.pem` certificate previously configured. + +[Back to TOC](#table-of-contents) + +### Restricting the client protocol (HTTP/HTTPS/TCP/TLS) + +Routes have a `protocols` property to restrict the client protocol they should +listen for. This attribute accepts a set of values, which can be `"http"`, +`"https"`, `"tcp"` or `"tls"`. + +A Route with `http` and `https` will accept traffic in both protocols. + +```json +{ + "hosts": ["..."], + "paths": ["..."], + "methods": ["..."], + "protocols": ["http", "https"], + "service": { + "id": "..." + } +} +``` + +Not specifying any protocol has the same effect, since routes default to +`["http", "https"]`. + +However, a Route with *only* `https` would _only_ accept traffic over HTTPS. It +would _also_ accept unencrypted traffic _if_ SSL termination previously +occurred from a trusted IP. SSL termination is considered valid when the +request comes from one of the configured IPs in +[trusted_ips][configuration-trusted-ips] and if the `X-Forwarded-Proto: https` +header is set: + +```json +{ + "hosts": ["..."], + "paths": ["..."], + "methods": ["..."], + "protocols": ["https"], + "service": { + "id": "..." + } +} +``` + +If a Route such as the above matches a request, but that request is in +plain-text without valid prior SSL termination, Kong responds with: + +```http +HTTP/1.1 426 Upgrade Required +Content-Type: application/json; charset=utf-8 +Transfer-Encoding: chunked +Connection: Upgrade +Upgrade: TLS/1.2, HTTP/1.1 +Server: kong/x.y.z + +{"message":"Please use HTTPS protocol"} +``` + +Since Kong 1.0 and Kong Enterprise 0.35, it's possible to create routes for raw TCP (not necessarily HTTP) +connections by using `"tcp"` in the `protocols` attribute: + +```json +{ + "hosts": ["..."], + "paths": ["..."], + "methods": ["..."], + "protocols": ["tcp"], + "service": { + "id": "..." + } +} +``` + +Similarly, we can create routes which accept raw TLS traffic (not necessarily HTTPS) with +the `"tls"` value: + +```json +{ + "hosts": ["..."], + "paths": ["..."], + "methods": ["..."], + "protocols": ["tls"], + "service": { + "id": "..." + } +} +``` + +A Route with *only* `TLS` would _only_ accept traffic over TLS. + +It is also possible to accept both TCP and TLS simultaneously: + +``` +{ + "hosts": ["..."], + "paths": ["..."], + "methods": ["..."], + "protocols": ["tcp", "tls"], + "service": { + "id": "..." + } +} + +``` + + +[Back to TOC](#table-of-contents) + +## Proxy WebSocket traffic + +Kong supports WebSocket traffic thanks to the underlying Nginx implementation. +When you wish to establish a WebSocket connection between a client and your +upstream services *through* Kong, you must establish a WebSocket handshake. +This is done via the HTTP Upgrade mechanism. This is what your client request +made to Kong would look like: + +```http +GET / HTTP/1.1 +Connection: Upgrade +Host: my-websocket-api.com +Upgrade: WebSocket +``` + +This will make Kong forward the `Connection` and `Upgrade` headers to your +upstream service, instead of dismissing them due to the hop-by-hop nature of a +standard HTTP proxy. + +[Back to TOC](#table-of-contents) + +### WebSocket and TLS + +Kong will accept `ws` and `wss` connections on its respective `http` and +`https` ports. To enforce TLS connections from clients, set the `protocols` +property of the [Route][route-entity] to `https` only. + +When setting up the [Service][service-entity] to point to your upstream +WebSocket service, you should carefully pick the protocol you want to use +between Kong and the upstream. If you want to use TLS (`wss`), then the +upstream WebSocket service must be defined using the `https` protocol in the +Service `protocol` property, and the proper port (usually 443). To connect +without TLS (`ws`), then the `http` protocol and port (usually 80) should be +used in `protocol` instead. + +If you want Kong to terminate SSL/TLS, you can accept `wss` only from the +client, but proxy to the upstream service over plain text, or `ws`. + +[Back to TOC](#table-of-contents) + +## Conclusion + +Through this guide, we hope you gained knowledge of the underlying proxying +mechanism of Kong, from how does a request match a Route to be routed to its +associated Service, on to how to allow for using the WebSocket protocol or +setup dynamic SSL certificates. + +This website is Open-Source and can be found at +[github.com/Kong/docs.konghq.com](https://github.com/Kong/docs.konghq.com/). +Feel free to provide feedback to this document there, or propose improvements! + +If you haven't already, we suggest that you also read the [Load balancing +Reference][load-balancing-reference], as it closely relates to the topic we +just covered. + +[Back to TOC](#table-of-contents) + +[plugin-configuration-object]: /enterprise/{{page.kong_version}}/admin-api#plugin-object +[plugin-development-guide]: /enterprise/{{page.kong_version}}/plugin-development +[plugin-association-rules]: /enterprise/{{page.kong_version}}/admin-api/#precedence +[load-balancing-reference]: /enterprise/{{page.kong_version}}/loadbalancing +[configuration-reference]: /enterprise/{{page.kong_version}}/property-reference +[configuration-trusted-ips]: /enterprise/{{page.kong_version}}/property-reference/#trusted_ips +[configuring-a-service]: /enterprise/{{page.kong_version}}/getting-started/add-service +[API]: /enterprise/{{page.kong_version}}/admin-api +[service-entity]: /enterprise/{{page.kong_version}}/admin-api/#add-service +[route-entity]: /enterprise/{{page.kong_version}}/admin-api/#add-route + +[ngx-http-proxy-module]: http://nginx.org/en/docs/http/ngx_http_proxy_module.html +[ngx-http-realip-module]: http://nginx.org/en/docs/http/ngx_http_realip_module.html +[ngx-remote-addr-variable]: http://nginx.org/en/docs/http/ngx_http_core_module.html#var_remote_addr +[ngx-scheme-variable]: http://nginx.org/en/docs/http/ngx_http_core_module.html#var_scheme +[ngx-host-variable]: http://nginx.org/en/docs/http/ngx_http_core_module.html#var_host +[ngx-server-port-variable]: http://nginx.org/en/docs/http/ngx_http_core_module.html#var_server_port +[ngx-http-proxy-retries]: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream_tries +[SNI]: https://en.wikipedia.org/wiki/Server_Name_Indication diff --git a/app/enterprise/1.3-x/secure-admin-api.md b/app/enterprise/1.3-x/secure-admin-api.md new file mode 100644 index 000000000000..8986a17b7116 --- /dev/null +++ b/app/enterprise/1.3-x/secure-admin-api.md @@ -0,0 +1,159 @@ +--- +title: Securing the Admin API +--- + +## Introduction + +Kong's Admin API provides a RESTful interface for administration and +configuration of Services, Routes, Plugins, Consumers, and Credentials. Because this +API allows full control of Kong, it is important to secure this API against +unwanted access. This document describes a few possible approaches to securing +the Admin API. + +## Network Layer Access Restrictions + +### Minimal Listening Footprint + +By default since its 0.12.0 release, Kong will only accept requests from the +local interface, as specified in its default `admin_listen` value: + +``` +admin_listen = 127.0.0.1:8001 +``` + +If you change this value, always ensure to keep the listening footprint to a +minimum, in order to avoid exposing your Admin API to third-parties, which +could seriously compromise the security of your Kong cluster as a whole. +For example, **avoid binding Kong to all of your interfaces**, by using +values such as `0.0.0.0:8001`. + +[Back to TOC](#table-of-contents) + +### Layer 3/4 Network Controls + +In cases where the Admin API must be exposed beyond a localhost interface, +network security best practices dictate that network-layer access be restricted +as much as possible. Consider an environment in which Kong listens on a private +network interface, but should only be accessed by a small subset of an IP range. +In such a case, host-based firewalls (e.g. iptables) are useful in limiting +input traffic ranges. For example: + + +```bash +# assume that Kong is listening on the address defined below, as defined as a +# /24 CIDR block, and only a select few hosts in this range should have access + +$ grep admin_listen /etc/kong/kong.conf +admin_listen 10.10.10.3:8001 + +# explicitly allow TCP packets on port 8001 from the Kong node itself +# this is not necessary if Admin API requests are not sent from the node +$ iptables -A INPUT -s 10.10.10.3 -m tcp -p tcp --dport 8001 -j ACCEPT + +# explicitly allow TCP packets on port 8001 from the following addresses +$ iptables -A INPUT -s 10.10.10.4 -m tcp -p tcp --dport 8001 -j ACCEPT +$ iptables -A INPUT -s 10.10.10.5 -m tcp -p tcp --dport 8001 -j ACCEPT + +# drop all TCP packets on port 8001 not in the above IP list +$ iptables -A INPUT -m tcp -p tcp --dport 8001 -j DROP + +``` + +Additional controls, such as similar ACLs applied at a network device level, are +encouraged, but fall outside the scope of this document. + +[Back to TOC](#table-of-contents) + +## Kong API Loopback + +Kong's routing design allows it to serve as a proxy for the Admin API itself. In +this manner, Kong itself can be used to provide fine-grained access control to +the Admin API. Such an environment requires bootstrapping a new Service that defines +the `admin_listen` address as the Service's `url`. For example: + +```bash +# assume that Kong has defined admin_listen as 127.0.0.1:8001, and we want to +# reach the Admin API via the url `/admin-api` + +$ curl -X POST http://localhost:8001/services \ + --data name=admin-api \ + --data host=localhost \ + --data port=8001 + +$ curl -X POST http://localhost:8001/services/admin-api/routes \ + --data paths[]=/admin-api + +# we can now transparently reach the Admin API through the proxy server +$ curl localhost:8000/admin-api/apis +{ + "data":[ + { + "uris":[ + "\/admin-api" + ], + "id":"653b21bd-4d81-4573-ba00-177cc0108dec", + "upstream_read_timeout":60000, + "preserve_host":false, + "created_at":1496351805000, + "upstream_connect_timeout":60000, + "upstream_url":"http:\/\/localhost:8001", + "strip_uri":true, + "https_only":false, + "name":"admin-api", + "http_if_terminated":true, + "upstream_send_timeout":60000, + "retries":5 + } + ], + "total":1 +} +``` + +From here, simply apply desired Kong-specific security controls (such as +[basic][basic-auth] or [key authentication][key-auth], +[IP restrictions][ip-restriction], or [access control lists][acl]) as you would +normally to any other Kong API. + +[Back to TOC](#table-of-contents) + +## Custom Nginx Configuration + +Kong is tightly coupled with Nginx as an HTTP daemon, and can thus be integrated +into environments with custom Nginx configurations. In this manner, use cases +with complex security/access control requirements can use the full power of +Nginx/OpenResty to build server/location blocks to house the Admin API as +necessary. This allows such environments to leverage native Nginx authorization +and authentication mechanisms, ACL modules, etc., in addition to providing the +OpenResty environment on which custom/complex security controls can be built. + +For more information on integrating Kong into custom Nginx configurations, see +[Custom Nginx configuration & embedding Kong][custom-configuration]. + +[Back to TOC](#table-of-contents) + +## Role Based Access Control ## + +
+ Enterprise-Only This feature is only available with an + Enterprise Subscription. +
+ +Enterprise users can configure role-based access control to secure access to the +Admin API. RBAC allows for fine-grained control over resource access based on +a model of user roles and permissions. Users are assigned to one or more roles, +which each in turn possess one or more permissions granting or denying access +to a particular resource. In this way, fine-grained control over specific Admin +API resources can be enforced, while scaling to allow complex, case-specific +uses. + +If you are not a Kong Enterprise customer, you can inquire about our +Enterprise offering by [contacting us](/enterprise). + +[Back to TOC](#table-of-contents) + + +[acl]: /plugins/acl +[basic-auth]: /plugins/basic-authentication/ +[custom-configuration]: /enterprise/{{page.kong_version}}/property-reference/#custom-nginx-configuration +[ip-restriction]: /plugins/ip-restriction +[key-auth]: /plugins/key-authentication diff --git a/app/enterprise/1.3-x/systemd.md b/app/enterprise/1.3-x/systemd.md new file mode 100644 index 000000000000..d826fba3b457 --- /dev/null +++ b/app/enterprise/1.3-x/systemd.md @@ -0,0 +1,106 @@ +--- +title: Control Kong Enterprise through systemd +toc: false +--- + +### Introduction + +This document includes instructions on how to integrate Kong Enterprise with systemd for Debian and RPM based packages. Note that some of the supported GNU/Linux distributions for Kong Enterprise may not have adopted systemd as their default init system (for example, CentOS 6 and RHEL 6). For the following instructions, it is assumed that Kong Enterprise has already been [installed and configured](https://docs.konghq.com/enterprise/latest/deployment/installation/overview/) on a systemd-supported GNU/Linux distribution. + +## Start Kong Enterprise + +``` +$ sudo systemctl start kong-enterprise-edition +``` + +## Stop Kong Enterprise + +``` +$ sudo systemctl stop kong-enterprise-edition +``` + +## Start Kong Enterprise automatically at system boot + +To enable Kong Enterprise to automatically start at system boot: + +``` +$ sudo systemctl enable kong-enterprise-edition +``` + +To disable Kong Enterprise from automatically starting at system boot: + +``` +$ sudo systemctl disable kong-enterprise-edition +``` + +## Restart Kong Enterprise + +``` +$ sudo systemctl restart kong-enterprise-edition +``` + +## Query Kong Enterprise status + +``` +$ sudo systemctl status kong-enterprise-edition +``` + +## Customize the Kong Enterprise unit file + +The official systemd service is located at `/lib/systemd/system/kong-enterprise-edition.service`. For scenarios where customizations are needed (for example, configuring Kong or modifying the service file behavior), we recommend to create another service at `/etc/systemd/system/kong-enterprise-edition.service` to avoid conflicts upon reinstalling or upgrading Kong Enterprise. + +All environment variables prefixed with `KONG_` and capitalized will override the settings specified in the `/etc/kong/kong.conf.default` file. For example: `log_level = debug` in the .conf file translates to the `KONG_LOG_LEVEL=debug` environment variable. + +There is also the possibility of opting to _not_ use environment variables in the service file but instead use a configuration file. In this case, modify the `ExecStartPre` systemd directive to execute `kong prepare` with the `-c` argument to point to your configuration file. For example, if you have a custom configuration file at `/etc/kong/kong.conf`, modify the `ExecStartPre` directive as follows: + +``` +ExecStartPre=/usr/local/bin/kong prepare -p /usr/local/kong -c /etc/kong/kong.conf +``` + +When linking non environment files using the `EnvironmentFile` systemd directive, note that the systemd parser will only recognize environment variables assignments. For example, if one of the Kong's default configuration files are linked (`/etc/kong/kong.conf.default` and `/etc/kong.conf`), non environment variables assignments in the file could lead to systemd errors. In this case, systemd will not allow the Kong service to be started. For this reason, we recommend specifying an `EnvironmentFile` other than the default ones: + +``` +EnvironmentFile=/etc/kong/kong_env.conf +``` + +### Logging to syslog and journald + +In this case, adding the below `Environment` systemd directives to your customized systemd service file at `/etc/systemd/system/kong-enterprise-edition.service` will do it: + +``` +Environment=KONG_PROXY_ACCESS_LOG=syslog:server=unix:/dev/log +Environment=KONG_PROXY_ERROR_LOG=syslog:server=unix:/dev/log +Environment=KONG_ADMIN_ACCESS_LOG=syslog:server=unix:/dev/log +Environment=KONG_ADMIN_ERROR_LOG=syslog:server=unix:/dev/log +``` + +To view the journald logs: + `journalctl -u kong-enterprise-edition` + +To view the syslog logs: + `tail -F /var/log/syslog` + +### Customize Kong's Nginx instance [using the Nginx directive injection system](https://docs.konghq.com/latest/configuration/#injecting-individual-nginx-directives) + +To use the injection system, add the below `Environment` systemd directive to your custom service at `/etc/systemd/system/kong-enterprise-edition.service` if environment variables are preferred. Note the quoting rules defined by systemd to specify an environment variable containing spaces: + +``` +Environment="KONG_NGINX_HTTP_OUTPUT_BUFFERS=4 64k" +``` + +### Customize Kong's Nginx instance [using `--nginx-conf`](https://docs.konghq.com/latest/configuration/#custom-nginx-templates) + +To use the `--nginx-conf` argument, modify the `ExecStartPre` systemd directive to execute `kong prepare` with the `--nginx-conf` argument. For example, if you have a custom template at `/usr/local/kong/custom-nginx.template`, modify the `ExecStartPre` directive as follows: + +``` +ExecStartPre=/usr/local/bin/kong prepare -p /usr/local/kong --nginx-conf /usr/local/kong/custom-nginx.template +``` + +### Customize Kong's Nginx instance [including files via the injected Nginx directives](https://docs.konghq.com/1.0.x/configuration/#including-files-via-injected-nginx-directives) + +To include files via the injected Nginx directives, add the below `Environment` systemd directive to your custom service at `/etc/systemd/system/kong-enterprise-edition.service` if environment variables are preferred: + +``` +Environment=KONG_NGINX_HTTP_INCLUDE=/path/to/your/my-server.kong.conf +``` + diff --git a/app/enterprise/changelog.md b/app/enterprise/changelog.md index 6f0ee804eebc..afb9d1a8d746 100644 --- a/app/enterprise/changelog.md +++ b/app/enterprise/changelog.md @@ -3,6 +3,386 @@ title: Kong Enterprise Changelog layout: changelog --- +## 1.3 +**Release Date:** 2019/11/05 + +### Kong Gateway +- **Kong Enterprise 1.3** inherits the following changes from **Kong Gateway 1.3**: + +#### Changes + +###### Dependencies + +- The required OpenResty version has been bumped to + [1.15.8.1](http://openresty.org/en/changelog-1015008.html). If you are + installing Kong from one of our distribution packages, you are not affected + by this change. See [#4382](https://github.com/Kong/kong/pull/4382). + With this new version comes a number of improvements: + 1. The new [ngx\_http\_grpc\_module](https://nginx.org/en/docs/http/ngx_http_grpc_module.html). + 2. Configurable of upstream keepalive connections by timeout or number of + requests. + 3. Support for ARM64 architectures. + 4. LuaJIT GC64 mode for x86_64 architectures, raising the LuaJIT GC-managed + memory limit from 2GB to 128TB and producing more predictable GC + performance. +- From this version on, the new + [lua-kong-nginx-module](https://github.com/Kong/lua-kong-nginx-module) Nginx + module is **required** to be built into OpenResty for Kong to function + properly. This new module allows Kong to support new features such as mutual + TLS authentication. If you are installing Kong from one of our distribution + packages, you are not affected by this change. + [openresty-build-tools#26](https://github.com/Kong/openresty-build-tools/pull/26) + +**Note:** if you are not using one of our distribution packages and compiling +OpenResty from source, you must still apply Kong's [OpenResty +patches](https://github.com/kong/openresty-patches) (and, as highlighted above, +compile OpenResty with the new lua-kong-nginx-module). Our new +[openresty-build-tools](https://github.com/Kong/openresty-build-tools) +repository will allow you to do both easily. + +###### Core + +- Bugfixes in the router *may, in some edge-cases*, result in + different Routes being matched. It was reported to us that the router behaved + incorrectly in some cases when configuring wildcard Hosts and regex paths + (e.g. [#3094](https://github.com/Kong/kong/issues/3094)). It may be so that + you are subject to these bugs without realizing it. Please ensure that + wildcard Hosts and regex paths Routes you have configured are matching as + expected before upgrading. + See [9ca4dc0](https://github.com/Kong/kong/commit/9ca4dc09fdb12b340531be8e0f9d1560c48664d5), + [2683b86](https://github.com/Kong/kong/commit/2683b86c2f7680238e3fe85da224d6f077e3425d), and + [6a03e1b](https://github.com/Kong/kong/commit/6a03e1bd95594716167ccac840ff3e892ed66215) + for details. +- Upstream connections are now only kept-alive for 100 requests or 60 seconds + (idle) by default. Previously, upstream connections were not actively closed + by Kong. This is a (non-breaking) change in behavior, inherited from Nginx + 1.15, and configurable via new configuration properties (see below). + +###### Configuration + +- The `upstream_keepalive` configuration property is deprecated, and + replaced by the new `nginx_http_upstream_keepalive` property. Its behavior is + almost identical, but the notable difference is that the latter leverages the + [injected Nginx + directives](https://konghq.com/blog/kong-ce-nginx-injected-directives/) + feature added in Kong 0.14.0. + In future releases, we will gradually increase support for injected Nginx + directives. We have high hopes that this will remove the occasional need for + custom Nginx configuration templates. + [#4382](https://github.com/Kong/kong/pull/4382) + +#### Additions + +###### Core + +- **Native gRPC proxying.** Two new protocol types; `grpc` and + `grpcs` correspond to gRPC over h2c and gRPC over h2. They can be specified + on a Route or a Service's `protocol` attribute (e.g. `protocol = grpcs`). + When an incoming HTTP/2 request matches a Route with a `grpc(s)` protocol, + the request will be handled by the + [ngx\_http\_grpc\_module](https://nginx.org/en/docs/http/ngx_http_grpc_module.html), + and proxied to the upstream Service according to the gRPC protocol + specifications. :warning: Note that not all Kong plugins are compatible with + gRPC requests yet. [#4801](https://github.com/Kong/kong/pull/4801) +- **Mutual TLS** handshake with upstream services. The Service + entity now has a new `client_certificate` attribute, which is a foreign key + to a Certificate entity. If specified, Kong will use the Certificate as a + client TLS cert during the upstream TLS handshake. + [#4800](https://github.com/Kong/kong/pull/4800) +- **Route by any request header**. The router now has the ability + to match Routes by any request header (not only `Host`). The Route entity now + has a new `headers` attribute, which is a map of headers names and values. + E.g. `{ "X-Forwarded-Host": ["example.org"], "Version": ["2", "3"] }`. + [#4758](https://github.com/Kong/kong/pull/4758) +- **Least-connection load-balancing**. A new `algorithm` attribute + has been added to the Upstream entity. It can be set to `"round-robin"` + (default), `"consistent-hashing"`, or `"least-connections"`. + [#4528](https://github.com/Kong/kong/pull/4528) +- Healthchecks now use the combination of IP + Port + Hostname when storing + upstream health information. Previously, only IP + Port were used. This means + that different virtual hosts served behind the same IP/port will be treated + differently with regards to their health status. New endpoints were added to + the Admin API to manually set a Target's health status. + [#4792](https://github.com/Kong/kong/pull/4792) + +###### Configuration + +- A new section in the `kong.conf` file describes [injected Nginx + directives](https://konghq.com/blog/kong-ce-nginx-injected-directives/) + (added to Kong 0.14.0) and specifies a few default ones. + In future releases, we will gradually increase support for injected Nginx + directives. We have high hopes that this will remove the occasional need for + custom Nginx configuration templates. + [#4382](https://github.com/Kong/kong/pull/4382) +- New configuration properties allow for controling the behavior of + upstream keepalive connections. `nginx_http_upstream_keepalive_requests` and + `nginx_http_upstream_keepalive_timeout` respectively control the maximum + number of proxied requests and idle timeout of an upstream connection. + [#4382](https://github.com/Kong/kong/pull/4382) +- New flags have been added to the `*_listen` properties: `deferred`, `bind`, + and `reuseport`. + [#4692](https://github.com/Kong/kong/pull/4692) + +##### Admin API + +- Many endpoints now support more levels of nesting for ease of access. + For example: `/services/:services/routes/:routes` is now a valid API + endpoint. + [#4713](https://github.com/Kong/kong/pull/4713) +- The API now accepts `form-urlencoded` payloads with deeply nested data + structures. Previously, it was only possible to send such data structures + via JSON payloads. + [#4768](https://github.com/Kong/kong/pull/4768) + +##### Plugins + +- jwt-auth: The new `header_names` property accepts an array of header names + the JWT plugin should inspect when authenticating a request. It defaults to + `["Authorization"]`. + [#4757](https://github.com/Kong/kong/pull/4757) +- [azure-functions](https://github.com/Kong/kong-plugin-azure-functions): + Bumped to 0.4 for minor fixes and performance improvements. +- [kubernetes-sidecar-injector](https://github.com/Kong/kubernetes-sidecar-injector): + The plugin is now more resilient to Kubernetes schema changes. Note that it is + now deprecated, and that Kong recommends using kuma.io instead. +- [serverless-functions](https://github.com/Kong/kong-plugin-serverless-functions): + - Bumped to 0.3 for minor performance improvements. + - Functions can now have upvalues. +- [prometheus](https://github.com/Kong/kong-plugin-prometheus): Bumped to + 0.4.1 for minor performance improvements. +- cors: add OPTIONS, TRACE and CONNECT to default allowed methods + [#4899](https://github.com/Kong/kong/pull/4899) + Thanks to [@eshepelyuk](https://github.com/eshepelyuk) for the patch! + +##### PDK + +- New function `kong.service.set_tls_cert_key()`. This functions sets the + client TLS certificate used while handshaking with the upstream service. + [#4797](https://github.com/Kong/kong/pull/4797) + +#### Fixes + +##### Core + +- Router: Fixed a bug causing invalid matches when configuring two or more + Routes with a plain `hosts` attribute shadowing another Route's wildcard + `hosts` attribute. Details of the issue can be seen in + [01b1cb8](https://github.com/Kong/kong/pull/4775/commits/01b1cb871b1d84e5e93c5605665b68c2f38f5a31). + [#4775](https://github.com/Kong/kong/pull/4775) +- Router: Ensure regex paths always have priority over plain paths. Details of + the issue can be seen in + [2683b86](https://github.com/Kong/kong/commit/2683b86c2f7680238e3fe85da224d6f077e3425d). + [#4775](https://github.com/Kong/kong/pull/4775) +- Cleanup of expired rows in PostgreSQL is now much more efficient thanks to a + new query plan. + [#4716](https://github.com/Kong/kong/pull/4716) +- Improved various query plans against Cassandra instances by increasing the + default page size. + [#4770](https://github.com/Kong/kong/pull/4770) + +##### Plugins + +- cors: ensure non-preflight OPTIONS requests can be proxied. + [#4899](https://github.com/Kong/kong/pull/4899) + Thanks to [@eshepelyuk](https://github.com/eshepelyuk) for the patch! +- Consumer references in various plugin entities are now + properly marked as required, avoiding credentials that map to no Consumer. + [#4879](https://github.com/Kong/kong/pull/4879) +- hmac-auth: Correct the encoding of HTTP/1.0 requests. + [#4839](https://github.com/Kong/kong/pull/4839) +- oauth2: empty client_id wasn't checked, causing a server error. + [#4884](https://github.com/Kong/kong/pull/4884) +- response-transformer: preserve empty arrays correctly. + [#4901](https://github.com/Kong/kong/pull/4901) + +##### CLI + +- Fixed an issue when running `kong restart` and Kong was not running, + causing stdout/stderr logging to turn off. + [#4772](https://github.com/Kong/kong/pull/4772) + +##### Admin API + +- Ensure PUT works correctly when applied to plugin configurations. + [#4882](https://github.com/Kong/kong/pull/4882) + +##### PDK + +- Prevent PDK calls from failing in custom content blocks. + This fixes a misbehavior affecting the Prometheus plugin. + [#4904](https://github.com/Kong/kong/pull/4904) +- Ensure `kong.response.add_header` works in the `rewrite` phase. + [#4888](https://github.com/Kong/kong/pull/4888) + +### Enterprise-Exclusives + +#### Changes + +- Kong Service Mesh is transitioned and upgraded to our next-generation service mesh offering named “Kuma”. Go to kuma.io for more information about using Kuma. +- Phone home logging now uses a new shared dict: lua_shared_dict kong_reports_workspaces 1m; If you use a custom nginx template, make sure it's there if you use phl. + +#### Features + +##### Kong Enterprise Gateway + +- gRPC support + +- Upstream mTLS support (API-only) + +- DB-export (API-only) + +- Routing by header + +- Cassandra - refresh cluster topology + +- RPM packages are now signed with our own GPG keys. You can download our public key at https://bintray.com/user/downloadSubjectPublicKey?username=kong + +- Route validation strategy now configurable and can enforce a route pattern by configuration + +- OpenID Connect Library: + - Add support for ES256 signing and key generation + - Add support for ES384 signing and key generation + - Add support for ES512 signing and key generation + - Add support for PS256 signing and key generation + - Add support for PS384 signing and key generation + - Add support for PS512 signing and key generation + - Add support for EdDSA signing, key generation and verification + - Update `lua-resty-nettle` dependency to 1.0 + +##### Docker + +- Improved security by allowing the CentOS and Alpine images to run as the `kong` user. + +##### Kong Manager + +- RBAC User Management (manage Admin API access within Kong Manager) + +- Service Directory Group to Kong Role Mapping (map AD groups or other service directory systems to roles & permission sets within Kong) + +- Service Map + + - View requests flowing through Kong + - View Immunity notifications within Service Map, click to alert section + +- Immunity alert management & detail section + + - Filterable by entity, severity + - Links through to alerted entities + +- Admin Password Strength Configuration + - Configure and enforce strong Admin passwords +- Admin Login Attempts + - Configure allowed login attempts to the Kong Manager + +##### Dev Portal + +- Easy theming within Kong Manager + + - Easily set your color scheme, logo/branding, and go + +- Developer Permissions + + - Decide what specs or content different sets of developers can access. + +- Separation of templates and user content + + - Enable content editors to make changes with no coding required + - Easier future release/upgrades path + +- Flat file system + + - Full access to JS/assets, customers can load a single page app, or serverside rendered portal we offer out of the box + +- Full serverside rendering + + - No need to hit the API via ajax for additional information in relationship to Kong, templating data object allows access to Kong data directly at load + + - Enables more extensive caching of pages/assets + +- Declarative configuration out of the box + + - Allows for more UI integrations + + - Conf files allow for source controlled configuration of your dev portal, including + + - Routing + + - Auth config + + - Permissions + + - Theming (colors, logos, meta info) + +- Developer Password Strength Configuration + - Configure and enforce strong Developer passwords + +- Developer Login Attempts + - Configure allowed login attempts to the Developer Portal + +##### Plugins + +- gRPC support, API & Kong Manager + +- Upstream mTLS support + +- DB export, API-only + +- Routing by header + +- Request Size Limiting - enhanced units on size limit +- Request Transformer Advanced - Support for filtering JSON body with new configration `config.whitelist.body` +- Response Transformer Advanced: + - Support for filtering JSON body with new configration config.whitelist.body, Support arbitrary transformations via Lua functions + - Fixed a bug where the plugin was returning an empty body in the response for status codes outside of those specified in `config.replace.if_status`. For example, if we specified a `config.replace.if_status=404` and a body `config.replace.body=test` and the status code was 200, the response would be empty. + +- Route Transformer Advanced - New +- GraphQL Proxy Cache Advanced - New +- GraphQL Rate Limiting Advanced - New +- Degraphql - New +- Exit Transformer - New +- Kafka Log - New +- Kafka Upstream - New +- mTLS Auth: + - Update cert request logic ask client cert when: + - To every route irrespective of workspace when plugin enabled in global scope + - To every route irrespective of workspace when plugin applied at service level but not all its routes have SNIs set + - To every route irrespective of workspace when plugin applied at route level but SNIs not set on route + - To specific route only when plugin applied at route level and it has SNIs set + - skip_consumer_lookup config to skip consumer lookup if request has trusted client certificate. + - authenticated_group_by config to block/allow validated certificate using ACL plugi +- Key-Auth keys now support a ttl property and can expire +- AWS Lambda plugin supports IAM roles +- Session plugin can now store authenticated groups from other authentication plugins.  + +##### CLI +- Adds runner + +#### Fixes + +##### Plugins + +###### OpenID Connect + +- Fix issue when discovery did not return issuer information (against OpenID Connect specification), and which could lead to 500 error on 401 and 403 responses. + +###### LDAP Auth Advanced + +- LDAP Auth Advanced - fixed issue where plugin tries to start a secure connection on an existing pooled connection from previous requests + +###### Request Transformer Advanced + +- Fixed a bug where the plugin was returning an empty body in the response for status codes outside of those specified in `config.replace.if_status`. For example, if we specified a `config.replace.if_status=404` and a body `config.replace.body=test` and the status code was 200, the response would be empty. + +##### Kong Enterprise Gateway + +- Fix: audit log entries did not include timestamps indicating when the event occurred. +- Fix: allow put requests to nonexistent foreign entities. +- Fix: granular tracing did not work when certain plugins (for example, the key-auth) were used. + +##### Docker + +- Fix: centos and alpine images did not work on some OpenShift setups with relaxed anyuid SCC settings. + ## 0.36-2 ### Notifications diff --git a/app/free-trial/guide/index.html b/app/free-trial/guide/index.html index 071436b71400..e4c62203d798 100644 --- a/app/free-trial/guide/index.html +++ b/app/free-trial/guide/index.html @@ -268,14 +268,14 @@

Step 2: Proxy API traffic

Step 3: Add a Plugin on the Service

Add a Kong Plugin to extend the functionality of Kong Enterprise. Kong’s Plugin architecture supports a broad range of functionality, such as logging, rate-limiting, authentication, and more.
-
For this trial, set up Kong’s Rate Limiting EE Plugin (Rate Limiting Advanced Plugin) to rate-limit how many HTTP requests a developer can make in a given period of seconds, minutes, hours, days, months or years. Plugins come pre-installed +
For this trial, set up Kong’s Rate Limiting Advanced Plugin to rate-limit how many HTTP requests a developer can make in a given period of seconds, minutes, hours, days, months or years. Plugins come pre-installed on Kong Enterprise, so all you need to do is enable and configure the Plugin.
-
1. Enable the Rate Limiting EE Plugin. +
1. Enable the Rate Limiting Advanced Plugin.

a. On the Plugins tab at the bottom of the page, click Add Plugin. The Add New Plugin page displays. -
b. Scroll down to the Traffic Control section and find the Rate Limiting EE plugin. Click Enable. The Create new rate-limiting-advanced plugin page displays with fields partially pre-populated. While there are +
b. Scroll down to the Traffic Control section and find the Rate Limiting Advanced plugin. Click Enable. The Create new rate-limiting-advanced plugin page displays with fields partially pre-populated. While there are many configuration parameters you can add to this Plugin, as defined in the Rate Limiting Advanced Plugin documentation, in this trial we’ll use the following to configure the Plugin:
c. Scroll to config.limit and enter 10, 100 @@ -369,7 +369,7 @@

Navigating Kong Manager

- +
@@ -380,18 +380,18 @@

Navigating Kong Manager

- +
•  -

From the Organization tab, you can invite and manage users, as well as assign Workspace roles and permissions.

+

From the Teams tab, you can invite and manage admins and users, as well as assign Workspace roles and permissions.

-