diff --git a/app/1.2.x/1.1.x/admin-api.md b/app/1.2.x/1.1.x/admin-api.md new file mode 100644 index 000000000000..3495d0e69d86 --- /dev/null +++ b/app/1.2.x/1.1.x/admin-api.md @@ -0,0 +1,2737 @@ +--- +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. + `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"], + "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"], + "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"], + "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. + +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. + `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 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"} + }], + +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, +and the status of the database connection. + +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 +{ + "server": { + "total_requests": 3, + "connections_active": 1, + "connections_accepted": 1, + "connections_handled": 1, + "connections_reading": 0, + "connections_writing": 1, + "connections_waiting": 0 + }, + "database": { + "reachable": true + } +} +``` + +* `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 +``` + +#### Response + +``` 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/private key pair for an SSL +certificate. These objects are used by Kong to handle SSL/TLS termination for +encrypted requests. 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 +``` + + +--- + +## 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 + } + ] +} +``` + + +--- + +[clustering]: /{{page.kong_version}}/clustering +[cli]: /{{page.kong_version}}/cli +[active]: /{{page.kong_version}}/health-checks-circuit-breakers/#active-health-checks +[healthchecks]: /{{page.kong_version}}/health-checks-circuit-breakers +[secure-admin-api]: /{{page.kong_version}}/secure-admin-api +[proxy-reference]: /{{page.kong_version}}/proxy +[db-less-admin-api]: /{{page.kong_version}}/db-less-admin-api diff --git a/app/1.2.x/1.1.x/auth.md b/app/1.2.x/1.1.x/auth.md new file mode 100644 index 000000000000..f190620128e8 --- /dev/null +++ b/app/1.2.x/1.1.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/1.2.x/1.1.x/cli.md b/app/1.2.x/1.1.x/cli.md new file mode 100644 index 000000000000..3246e3004c76 --- /dev/null +++ b/app/1.2.x/1.1.x/cli.md @@ -0,0 +1,307 @@ +--- +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. + + 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. + +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 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]: /{{page.kong_version}}/configuration diff --git a/app/1.2.x/1.1.x/clustering.md b/app/1.2.x/1.1.x/clustering.md new file mode 100644 index 000000000000..429b41c229af --- /dev/null +++ b/app/1.2.x/1.1.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]: /{{page.kong_version}}/configuration/#db_update_frequency +[db_update_propagation]: /{{page.kong_version}}/configuration/#db_update_propagation +[db_cache_ttl]: /{{page.kong_version}}/configuration/#db_cache_ttl diff --git a/app/1.2.x/1.1.x/configuration.md b/app/1.2.x/1.1.x/configuration.md new file mode 100644 index 000000000000..2d59b3ef2b43 --- /dev/null +++ b/app/1.2.x/1.1.x/configuration.md @@ -0,0 +1,1264 @@ +--- +title: Configuration Reference +--- + +## Configuration loading + +Kong comes with a default configuration file that can be found at +`/etc/kong/kong.conf.default` if you installed Kong via one of the official +packages. To start configuring Kong, you can copy this file: + +```bash +$ cp /etc/kong/kong.conf.default /etc/kong/kong.conf +``` + +Kong will operate with default settings should all the values in your +configuration be commented out. Upon starting, Kong looks for several +default locations that might contain a configuration file: + +``` +/etc/kong/kong.conf +/etc/kong.conf +``` + +You can override this behavior by specifying a custom path for your +configuration file using the `-c / --conf` argument in the CLI: + +```bash +$ kong start --conf /path/to/kong.conf +``` + +The configuration format is straightforward: simply uncomment any property +(comments are defined by the `#` character) and modify it to your needs. +Boolean values can be specified as `on`/`off` or `true`/`false` for convenience. + +## Verifying your configuration + +You can verify the integrity of your settings with the `check` command: + +```bash +$ kong check +configuration at is valid +``` + +This command will take into account the environment variables you have +currently set, and will error out in case your settings are invalid. + +Additionally, you can also use the CLI in debug mode to have more insight +as to what properties Kong is being started with: + +```bash +$ kong start -c --vv +2016/08/11 14:53:36 [verbose] no config file found at /etc/kong.conf +2016/08/11 14:53:36 [verbose] no config file found at /etc/kong/kong.conf +2016/08/11 14:53:36 [debug] admin_listen = "0.0.0.0:8001" +2016/08/11 14:53:36 [debug] database = "postgres" +2016/08/11 14:53:36 [debug] log_level = "notice" +[...] +``` + +## Environment variables + +When loading properties out of a configuration file, Kong will also look for +environment variables of the same name. This allows you to fully configure Kong +via environment variables, which is very convenient for container-based +infrastructures, for example. + +To override a setting using an environment variable, declare an environment +variable with the name of the setting, prefixed with `KONG_` and capitalized. + +For example: + +``` +log_level = debug # in kong.conf +``` + +can be overridden with: + +```bash +$ export KONG_LOG_LEVEL=error +``` + +## Injecting Nginx directives + +Tweaking the Nginx configuration of your Kong instances allows you to optimize +its performance for your infrastructure. + +When Kong starts, it builds an Nginx configuration file. You can inject custom +Nginx directives to this file directly via your Kong configuration. + +### Injecting individual Nginx directives + +Any entry added to your `kong.conf` file that is prefixed by `nginx_http_`, +`nginx_proxy_` or `nginx_admin_` will be converted into an equivalent Nginx +directive by removing the prefix and added to the appropriate section of the +Nginx configuration: + +- Entries prefixed with `nginx_http_` will be injected to the overall `http` +block directive. + +- Entries prefixed with `nginx_proxy_` will be injected to the `server` block +directive handling Kong's proxy ports. + +- Entries prefixed with `nginx_admin_` will be injected to the `server` block +directive handling Kong's Admin API ports. + +For example, if you add the following line to your `kong.conf` file: + +``` +nginx_proxy_large_client_header_buffers=16 128k +``` + +it will add the following directive to the proxy `server` block of Kong's +Nginx configuration: + +``` + large_client_header_buffers 16 128k; +``` + +Like any other entry in `kong.conf`, these directives can also be specified +using [environment variables](#environment-variables) as shown above. For +example, if you declare an environment variable like this: + +```bash +$ export KONG_NGINX_HTTP_OUTPUT_BUFFERS="4 64k" +``` + +This will result in the following Nginx directive being added to the `http` +block: + +``` + output_buffers 4 64k; +``` + +As always, be mindful of your shell's quoting rules specifying values +containing spaces. + +For more details on the Nginx configuration file structure and block +directives, see https://nginx.org/en/docs/beginners_guide.html#conf_structure. + +For a list of Nginx directives, see https://nginx.org/en/docs/dirindex.html. +Note however that some directives are dependent of specific Nginx modules, +some of which may not be included with the official builds of Kong. + +### Including files via injected Nginx directives + +For more complex configuration scenarios, such as adding entire new +`server` blocks, you can use the method described above to inject an +`include` directive to the Nginx configuration, pointing to a file +containing your additional Nginx settings. + +For example, if you create a file called `my-server.kong.conf` with +the following contents: + +``` +# custom server +server { + listen 2112; + location / { + # ...more settings... + return 200; + } +} +``` + +You can make the Kong node serve this port by adding the following +entry to your `kong.conf` file: + +``` +nginx_http_include = /path/to/your/my-server.kong.conf +``` + +or, alternatively, by configuring it via an environment variable: + +```bash +$ export KONG_NGINX_HTTP_INCLUDE="/path/to/your/my-server.kong.conf" +``` + +Now, when you start Kong, the `server` section from that file will be added to +that file, meaning that the custom server defined in it will be responding, +alongside the regular Kong ports: + +```bash +$ curl -I http://127.0.0.1:2112 +HTTP/1.1 200 OK +... +``` + +Note that if you use a relative path in an `nginx_http_include` property, that +path will be interpreted relative to the value of the `prefix` property of +your `kong.conf` file (or the value of the `-p` flag of `kong start` if you +used it to override the prefix when starting Kong). + +## Custom Nginx templates & embedding Kong + +For the vast majority of use-cases, using the Nginx directive injection system +explained above should be sufficient for customizing the behavior of Kong's +Nginx instance. This way, you can manage the configuration and tuning of your +Kong node from a single `kong.conf` file (and optionally your own included +files), without having to deal with custom Nginx configuration templates. + +There are two scenarios in which you may want to make use of custom Nginx +configuration templates directly: + +- In the rare occasion that you may need to modify some of Kong's default +Nginx configuration that are not adjustable via its standard `kong.conf` +properties, you can still modify the template used by Kong for producing its +Nginx configuration and launch Kong using your customized template. + +- If you need to embed Kong in an already running OpenResty instance, you +can reuse Kong's generated configuration and include it in your existing +configuration. + +### Custom Nginx templates + +Kong can be started, reloaded and restarted with an `--nginx-conf` argument, +which must specify an Nginx configuration template. Such a template uses the +[Penlight][Penlight] [templating engine][pl.template], which is compiled using +the given Kong configuration, before being dumped in your Kong prefix +directory, moments before starting Nginx. + +The default template can be found at: +https://github.com/kong/kong/tree/master/kong/templates. It is split in two +Nginx configuration files: `nginx.lua` and `nginx_kong.lua`. The former is +minimalistic and includes the latter, which contains everything Kong requires +to run. When `kong start` runs, right before starting Nginx, it copies these +two files into the prefix directory, which looks like so: + +``` +/usr/local/kong +├── nginx-kong.conf +└── nginx.conf +``` + +If you must tweak global settings that are defined by Kong but not adjustable +via the Kong configuration in `kong.conf`, you can inline the contents of the +`nginx_kong.lua` configuration template into a custom template file (in this +example called `custom_nginx.template`) 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 logs/error.log ${{ "{{LOG_LEVEL" }}}}; # can be set by kong.conf + +events { + use epoll; # a custom setting + multi_accept on; +} + +http { + + # contents of the nginx_kong.lua template follow: + + resolver ${{ "{{DNS_RESOLVER" }}}} ipv6=off; + charset UTF-8; + error_log logs/error.log ${{ "{{LOG_LEVEL" }}}}; + access_log logs/access.log; + + ... # etc +} +``` + +You can then start Kong with: + +```bash +$ kong start -c kong.conf --nginx-conf custom_nginx.template +``` + +## Embedding Kong in OpenResty + +If you are running your own OpenResty servers, you can also easily embed Kong +by including the Kong Nginx sub-configuration using the `include` directive. +If you have an existing Nginx configuration, you can simply include the +Kong-specific portion of the configuration which is output by Kong in a separate +`nginx-kong.conf` file: + +``` +# my_nginx.conf + +# ...your nginx settings... + +http { + include 'nginx-kong.conf'; + + # ...your nginx settings... +} +``` + +You can then start your Nginx instance like so: + +```bash +$ nginx -p /usr/local/openresty -c my_nginx.conf +``` + +and Kong will be running in that instance (as configured in `nginx-kong.conf`). + +## Serving both a website and your APIs from Kong + +A common use case for API providers is to make Kong serve both a website +and the APIs themselves over the Proxy port — `80` or `443` in +production. For example, `https://example.net` (Website) and +`https://example.net/api/v1` (API). + +To achieve this, we cannot simply declare a new virtual server block, +like we did in the previous section. A good solution is to use a custom +Nginx configuration template which inlines `nginx_kong.lua` and adds a new +`location` block serving the website alongside the Kong Proxy `location` +block: + +``` +# --------------------- +# 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 {} + +http { + # here, we inline the contents of nginx_kong.lua + charset UTF-8; + + # any contents until Kong's Proxy server block + ... + + # Kong's Proxy server block + server { + server_name kong; + + # any contents until the location / block + ... + + # here, we declare our custom location serving our website + # (or API portal) which we can optimize for serving static assets + location / { + root /var/www/example.net; + index index.htm index.html; + ... + } + + # Kong's Proxy location / has been changed to /api/v1 + location /api/v1 { + set $upstream_host nil; + set $upstream_scheme nil; + set $upstream_uri nil; + + # Any remaining configuration for the Proxy location + ... + } + } + + # Kong's Admin server block goes below + # ... +} +``` + +## Properties reference + +### General section + +#### prefix + +Working directory. Equivalent to Nginx's prefix path, containing temporary +files and logs. + +Each Kong process must have a separate working directory. + +Default: `/usr/local/kong/` + +--- + +#### log_level + +Log level of the Nginx server. Logs are found at `/logs/error.log`. + +See http://nginx.org/en/docs/ngx_core_module.html#error_log for a list of +accepted values. + +Default: `notice` + +--- + +#### proxy_access_log + +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. + +Default: `logs/access.log` + +--- + +#### proxy_error_log + +Path for proxy port request error logs. The granularity of these logs is +adjusted by the `log_level` directive. + +Default: `logs/error.log` + +--- + +#### admin_access_log + +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. + +Default: `logs/admin_access.log` + +--- + +#### admin_error_log + +Path for Admin API request error logs. The granularity of these logs is +adjusted by the `log_level` directive. + +Default: `logs/error.log` + +--- + +#### plugins + +Comma-separated list of plugins this node should load. By default, only plugins +bundled in official distributions are loaded via the `bundled` keyword. + +Loading a plugin does not enable it by default, but only instructs Kong to load +its source code, and allows to configure the plugin via the various related +Admin API endpoints. + +The specified name(s) will be substituted as such in the Lua namespace: +`kong.plugins.{name}.*`. + +When the `off` keyword is specified as the only value, no plugins will be +loaded. + +`bundled` and plugin names can be mixed together, as the following examples +suggest: + +- `plugins = bundled,custom-auth,custom-log` will include the bundled plugins + plus two custom ones +- `plugins = custom-auth,custom-log` will *only* include the `custom-auth` and + `custom-log` plugins. +- `plugins = off` will not include any plugins + +**Note:** Kong will not start if some plugins were previously configured (i.e. +have rows in the database) and are not specified in this list. + +Before disabling a plugin, ensure all instances of it are removed before +restarting Kong. + +**Note:** Limiting the amount of available plugins can improve P99 latency when +experiencing LRU churning in the database cache (i.e. when the configured +`mem_cache_size`) is full. + +Default: `bundled` + +--- + +#### anonymous_reports + +Send anonymous usage data such as error stack traces to help improve Kong. + +Default: `on` + +--- + + +### NGINX section + +#### proxy_listen + +Comma-separated list of addresses and ports on which the proxy server should +listen for HTTP/HTTPS traffic. + +The proxy server is the public entry point 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` 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. +- `proxy_protocol` will enable usage of the PROXY protocol for a given + address/port. +- `transparent` will cause kong to listen to, and respond from, any and all IP + addresses and ports you configure in iptables. + +This value can be set to `off`, thus disabling the HTTP/HTTPS proxy port for +this node. + +If stream_listen is also set to `off`, this enables 'control-plane' mode for +this node (in which all traffic proxying capabilities are disabled). This node +can then be used only to configure a cluster of Kong nodes connected to the same +datastore. + +Example: `proxy_listen = 0.0.0.0:443 ssl, 0.0.0.0:444 http2 ssl` + +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. + +See https://www.nginx.com/resources/admin-guide/proxy-protocol/ for more +details about the `proxy_protocol` parameter. + +Not all `*_listen` values accept all formats specified in nginx's +documentation. + +Default: `0.0.0.0:8000, 0.0.0.0:8443 ssl` + +--- + +#### stream_listen + +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` will enable usage of the PROXY protocol for a given + address/port. +- `transparent` will cause kong to listen to, and respond from, any and all IP + addresses and ports you configure in iptables. + +**Note:** The `ssl` suffix is not supported, and each address/port will accept +TCP with or without TLS enabled. + +Examples: + +``` +stream_listen = 127.0.0.1:7000 +stream_listen = 0.0.0.0:989, 0.0.0.0:20 +stream_listen = [::1]:1234 +``` + +By default this value is set to `off`, thus disabling the stream proxy port for +this node. + +See http://nginx.org/en/docs/stream/ngx_stream_core_module.html#listen for a +description of the formats that Kong might accept in stream_listen. + +Default: `off` + +--- + +#### admin_listen + +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. + +Example: `stream_listen = 127.0.0.1:8444 http2 ssl` + +Default: `127.0.0.1:8001, 127.0.0.1:8444 ssl` + +--- + +#### nginx_user + +Defines user and group credentials used by worker processes. If group is +omitted, a group whose name equals that of user is used. + +Example: `nginx_user = nginx www` + +Default: `nobody nobody` + +--- + +#### nginx_worker_processes + +Determines the number of worker processes spawned by Nginx. + +See http://nginx.org/en/docs/ngx_core_module.html#worker_processes for detailed +usage of this directive and a description of accepted values. + +Default: `auto` + +--- + +#### nginx_daemon + +Determines whether Nginx will run as a daemon or as a foreground process. +Mainly useful for development or when running Kong inside a Docker environment. + +See http://nginx.org/en/docs/ngx_core_module.html#daemon. + +Default: `on` + +--- + +#### mem_cache_size + +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. + +Default: `128m` + +--- + +#### ssl_cipher_suite + +Defines the TLS ciphers served by Nginx. + +Accepted values are `modern`, `intermediate`, `old`, or `custom`. + +See https://wiki.mozilla.org/Security/Server_Side_TLS for detailed descriptions +of each cipher suite. + +Default: `modern` + +--- + +#### ssl_ciphers + +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`. + +Default: none + +--- + +#### ssl_cert + +The absolute path to the SSL certificate for `proxy_listen` values with SSL +enabled. + +Default: none + +--- + +#### ssl_cert_key + +The absolute path to the SSL key for `proxy_listen` values with SSL enabled. + +Default: none + +--- + +#### client_ssl + +Determines if Nginx should send client-side SSL certificates when proxying +requests. + +Default: `off` + +--- + +#### client_ssl_cert + +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. + +Default: none + +--- + +#### client_ssl_cert_key + +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. + +Default: none + +--- + +#### admin_ssl_cert + +The absolute path to the SSL certificate for `admin_listen` values with SSL +enabled. + +Default: none + +--- + +#### admin_ssl_cert_key + +The absolute path to the SSL key for `admin_listen` values with SSL enabled. + +Default: none + +--- + +#### upstream_keepalive + +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 `0` will disable this behavior altogether, forcing each upstream +request to open a new connection. + +Default: `60` + +--- + +#### headers + +Comma-separated list of headers Kong should inject in client responses. + +Accepted values are: + +- `Server`: Injects `Server: kong/x.y.z` on Kong-produced response (e.g. Admin + API, rejected requests from auth plugin, etc...). +- `Via`: Injects `Via: kong/x.y.z` for successfully proxied requests. +- `X-Kong-Proxy-Latency`: Time taken (in milliseconds) by Kong to process a + request and run all plugins before proxying the request upstream. +- `X-Kong-Upstream-Latency`: Time taken (in milliseconds) by the upstream + service to send response headers. +- `X-Kong-Upstream-Status`: The HTTP status code returned by the upstream + service. This is particularly useful for clients to distinguish upstream + statuses if the response is rewritten by a plugin. +- `server_tokens`: Same as specifying both `Server` and `Via`. +- `latency_tokens`: Same as specifying both `X-Kong-Proxy-Latency` and + `X-Kong-Upstream-Latency`. + +In addition to those, this value can be set to `off`, which prevents Kong from +injecting any of the above headers. Note that this does not prevent plugins from +injecting headers of their own. + +Example: `headers = via, latency_tokens` + +Default: `server_tokens, latency_tokens` + +--- + +#### trusted_ips + +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. + +See http://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from +for examples of accepted values. + +Default: none + +--- + +#### real_ip_header + +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 this value receives `proxy_protocol`: + +- at least one of the `proxy_listen` entries must have the `proxy_protocol` + flag enabled. +- the `proxy_protocol` parameter will be appended to the `listen` directive of + the Nginx template. + +See http://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header +for a description of this directive. + +Default: `X-Real-IP` + +--- + +#### real_ip_recursive + +This value sets the ngx_http_realip_module directive of the same name in the +Nginx configuration. + +See http://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_recursive +for a description of this directive. + +Default: `off` + +--- + +#### client_max_body_size + +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. + +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. + +Default: `0` + +--- + +#### client_body_buffer_size + +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. + +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. + +Default: `8k` + +--- + +#### error_default_type + +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`. + +Default: `text/plain` + +--- + + +### Datastore section + +Kong will store all of its data (such as Routes, Services, Consumers, and +Plugins) in either Cassandra or PostgreSQL, and all Kong nodes belonging to the +same cluster must connect themselves to the same database. + +Kong supports the following database versions: + +- **PostgreSQL**: 9.5 and above. +- **Cassandra**: 2.2 and above. + +--- + +#### database + +Determines which of PostgreSQL or Cassandra this node will use as its +datastore. + +Accepted values are `postgres` and `cassandra`. + +Default: `postgres` + +--- + + +#### Postgres settings + +name | description | default +-------|--------------|---------- +**pg_host** | Host of the Postgres server. | `127.0.0.1` +**pg_port** | Port of the Postgres server. | `5432` +**pg_timeout** | Defines the timeout (in ms), for connecting, reading and writing. | `5000` +**pg_user** | Postgres user. | `kong` +**pg_password** | Postgres user's password. | none +**pg_database** | The database name to connect to. | `kong` +**pg_schema** | The database schema to use. If unspecified, Kong will respect the `search_path` value of your PostgreSQL instance. | none +**pg_ssl** | Toggles client-server TLS connections between Kong and PostgreSQL. | `off` +**pg_ssl_verify** | Toggles server certificate verification if `pg_ssl` is enabled. See the `lua_ssl_trusted_certificate` setting to specify a certificate authority. | `off` + +#### Cassandra settings + +name | description | default +-------|--------------|---------- +**cassandra_contact_points** | A comma-separated list of contact points to your cluster. You may specify IP addresses or hostnames. Note that the port component of SRV records will be ignored in favor of `cassandra_port`. When connecting to a multi-DC cluster, ensure that contact points from the local datacenter are specified first in this list. | `127.0.0.1` +**cassandra_port** | The port on which your nodes are listening on. All your nodes and contact points must listen on the same port. Will be created if it doesn't exist. | `9042` +**cassandra_keyspace** | The keyspace to use in your cluster. | `kong` +**cassandra_consistency** | Consistency setting to use when reading/ writing to the Cassandra cluster. | `ONE` +**cassandra_timeout** | Defines the timeout (in ms) for reading and writing. | `5000` +**cassandra_ssl** | Toggles client-to-node TLS connections between Kong and Cassandra. | `off` +**cassandra_ssl_verify** | Toggles server certificate verification if `cassandra_ssl` is enabled. See the `lua_ssl_trusted_certificate` setting to specify a certificate authority. | `off` +**cassandra_username** | Username when using the `PasswordAuthenticator` scheme. | `kong` +**cassandra_password** | Password when using the `PasswordAuthenticator` scheme. | none +**cassandra_lb_policy** | Load balancing policy to use when distributing queries across your Cassandra cluster. Accepted values are: `RoundRobin`, `RequestRoundRobin`, `DCAwareRoundRobin`, and `RequestDCAwareRoundRobin`. Policies prefixed with "Request" make efficient use of established connections throughout the same request. Prefer "DCAware" policies if and only if you are using a multi-datacenter cluster. | `RequestRoundRobin` +**cassandra_local_datacenter** | When using the `DCAwareRoundRobin` or `RequestDCAwareRoundRobin` load balancing policy, you must specify the name of the local (closest) datacenter for this Kong node. | none +**cassandra_repl_strategy** | When migrating for the first time, Kong will use this setting to create your keyspace. Accepted values are `SimpleStrategy` and `NetworkTopologyStrategy`. | `SimpleStrategy` +**cassandra_repl_factor** | When migrating for the first time, Kong will create the keyspace with this replication factor when using the `SimpleStrategy`. | `1` +**cassandra_data_centers** | When migrating for the first time, will use this setting when using the `NetworkTopologyStrategy`. The format is a comma-separated list made of `:`. | `dc1:2,dc2:3` +**cassandra_schema_consensus_timeout** | 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. | `10000` + +### Datastore Cache section + +In order to avoid unnecessary communication with the datastore, Kong caches +entities (such as 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 + +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. + +Default: `5` + +--- + +#### db_update_propagation + +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. + +Default: `0` + +--- + +#### db_cache_ttl + +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 (default), such cached entities or misses never expire. + +Default: `0` + +--- + +#### db_resurrect_ttl + +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. + +Default: `30` + +--- + + +### DNS Resolver section + +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. + +Kong will resolve hostnames as either `SRV` or `A` records (in that order, and +`CNAME` records will be dereferenced in the process). + +In case a name was resolved as an `SRV` record it will also override any given +port number by the `port` field contents received from the DNS server. + +The DNS options `SEARCH` and `NDOTS` (from the `/etc/resolv.conf` file) will be +used to expand short names to fully qualified ones. So it will first try the +entire `SEARCH` list for the `SRV` type, if that fails it will try the `SEARCH` +list for `A`, etc. + +For the duration of the `ttl`, the internal DNS resolver will loadbalance each +request it gets over the entries in the DNS record. For `SRV` records the +`weight` fields will be honored, but it will only use the lowest `priority` +field entries in the record. + +--- + +#### dns_resolver + +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. + +Default: none + +--- + +#### dns_hostsfile + +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. + +Default: `/etc/hosts` + +--- + +#### dns_order + +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. + +Default: `LAST,SRV,A,CNAME` + +--- + +#### dns_valid_ttl + +By default, DNS records are cached using the TTL value of a response. If this +property receives a value (in seconds), it will override the TTL for all +records. + +Default: none + +--- + +#### dns_stale_ttl + +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. + +Default: `4` + +--- + +#### dns_not_found_ttl + +TTL in seconds for empty DNS responses and "(3) name error" responses. + +Default: `30` + +--- + +#### dns_error_ttl + +TTL in seconds for error responses. + +Default: `1` + +--- + +#### dns_no_sync + +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. + +Default: `off` + +--- + + +### Development & Miscellaneous section + +Additional settings inherited from lua-nginx-module allowing for more +flexibility and advanced usage. + +See the lua-nginx-module documentation for more information: +https://github.com/openresty/lua-nginx-module + +--- + +#### lua_ssl_trusted_certificate + +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. + +See https://github.com/openresty/lua-nginx-module#lua_ssl_trusted_certificate + +Default: none + +--- + +#### lua_ssl_verify_depth + +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. + +See https://github.com/openresty/lua-nginx-module#lua_ssl_verify_depth + +Default: `1` + +--- + +#### lua_package_path + +Sets the Lua module search path (LUA_PATH). Useful when developing or using +custom plugins not stored in the default search path. + +See https://github.com/openresty/lua-nginx-module#lua_package_path + +Default: `./?.lua;./?/init.lua;` + +--- + +#### lua_package_cpath + +Sets the Lua C module search path (LUA_CPATH). + +See https://github.com/openresty/lua-nginx-module#lua_package_cpath + +Default: none + +--- + +#### lua_socket_pool_size + +Specifies the size limit for every cosocket connection pool associated with +every remote server. + +See https://github.com/openresty/lua-nginx-module#lua_socket_pool_size + +Default: `30` + +--- + + +### Additional Configuration + +#### origins + +The origins configuration can be useful in complex networking configurations, +and is typically required when Kong is used in a service mesh. + +`origins` is a comma-separated list of pairs of origins, with each half of the +pair separated by an `=` symbol. The origin on the left of each pair is +overridden by the origin on the right. This override occurs after the access +phase, and before upstream resolution. It has the effect of causing Kong to +send traffic that would have gone to the left origin to the right origin instead. + +The term origin (singular) refers to a particular scheme/host or IP address/port +triple, as described in RFC 6454 (https://tools.ietf.org/html/rfc6454#section-3.2). +In Kong's `origins` configuration, the scheme *must* be one of `http`, `https`, +`tcp`, or `tls`. In each pair of origins, the scheme *must* be of similar type - +thus `http` can pair with `https`, and `tcp` can pair with `tls`, but `http` and +`https` cannot pair with `tcp` and `tls`. + +When an encrypted scheme like `tls` or `https` in the left origin is paired with +an unencrypted scheme like `tcp` or `http` in the right origin, Kong will +terminate TLS on incoming connections matching the left origin, and will then +route traffic unencrypted to the specified right origin. This is useful when +connections will be made to the Kong node over TLS, but the local service (for +which Kong is proxying traffic) doesn't or can't terminate TLS. Similarly, if +the left origin is `tcp` or `http` and the right origin is `tls` or `https`, +Kong will accept unencrypted incoming traffic, and will then wrap that traffic +in TLS as it is routed outbound. This capability is an important enabler of Kong Mesh. + +Like all Kong configuration settings, the `origins` setting *can* be declared in +the `Kong.conf` file - however **it is recommended that Kong administrators +avoid doing so**. Instead, `origins` should be set on a per-node basis using +[environment variables](https://docs.konghq.com/{{page.kong_version}}/configuration/#environment-variables). +As such, `origins` is not present in [`kong.conf.default`](https://github.com/Kong/kong/blob/0.15.0/kong.conf.default). + +In Kubernetes deployments, it is recommended that `origins` not be configured +and maintained "by hand" - instead, `origins` for each Kong node should be +managed by the Kubernetes Identity Module (KIM). + +Default: none + +##### Examples + +If a given Kong node has the following configuration for `origins`: + +``` +http://upstream-foo-bar:1234=http://localhost:5678 +``` + +That Kong node will not attempt to resolve `upstream-foo-bar` - instead, that +Kong node will route traffic to `localhost:5678`. In a service mesh deployment +of Kong, this override would be necessary to cause a Kong sidecar adjacent to +an instance of the `upstream-foo-bar` application to route traffic to that +local instance, rather than trying to route traffic back across the network to +a non-local instance of `upstream-foo-bar`. + +--- + +In another typical sidecar deployment, in which the Kong node is deployed on +the same host, virtual machine, or Kubernetes Pod as one instance of a service +for which Kong is acting as a proxy, `origins` would be configured like: + +``` +https://service-b:9876=http://localhost:5432 +``` + +This arrangement would cause this Kong node to accept _only_ HTTPS connections +on port 9876, terminate TLS, then forward the now-unencrypted traffic to +localhost port 5432. + +--- + +Following is an example consisting of two pairs, demonstrating the correct use +of the `,` separator with no space: + +``` +https://foo.bar.com:443=http://localhost:80,tls://dog.cat.org:9999=tcp://localhost:8888 +``` + +This configuration would result in Kong accepting _only_ HTTPS traffic on port +443, and _only_ TLS traffic on port 9999, terminating TLS in both cases, then +forwarding the traffic to localhost ports 80 and 8888 respectively. Assuming +that the localhost ports 80 and 8888 are each associated with a separate +service, this configuration could occur when Kong is acting as a node proxy, +which is a local proxy that is acting on behalf of multiple services (which +differs from a sidecar proxy, in which a local proxy acts on behalf of only a +_single_ local service). + + +[Penlight]: http://stevedonovan.github.io/Penlight/api/index.html +[pl.template]: http://stevedonovan.github.io/Penlight/api/libraries/pl.template.html diff --git a/app/1.2.x/1.1.x/db-less-admin-api.md b/app/1.2.x/1.1.x/db-less-admin-api.md new file mode 100644 index 000000000000..bb3ed2718f94 --- /dev/null +++ b/app/1.2.x/1.1.x/db-less-admin-api.md @@ -0,0 +1,1723 @@ +--- +title: Admin API for DB-less Mode + +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. + `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"], + "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"], + "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"], + "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": {"minute":20, "hour":500}, + "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": {"minute":20, "hour":500}, + "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": {"minute":20, "hour":500}, + "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. + +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. + `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 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"} + }], + +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. +In [DB-less mode][db-less], this Admin API can be used to load a new declarative +configuration, and for inspecting the current configuration. In DB-less mode, +the Admin API for each node functions independently, reflecting the memory state +of that particular Kong node. This is the case because there is no database +coordination between Kong 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 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** +- **application/json** + +--- + +## 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, +and the status of the database connection. + +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 +{ + "server": { + "total_requests": 3, + "connections_active": 1, + "connections_accepted": 1, + "connections_handled": 1, + "connections_reading": 0, + "connections_writing": 1, + "connections_waiting": 0 + }, + "database": { + "reachable": true + } +} +``` + +* `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. + + +--- + +## Declarative Configuration + +Loading the declarative configuration of entities into Kong +can be done in two ways: at start-up, through the `declarative_config` +property, or at run-time, through the Admin API using the `/config` +endpoint. + +To get started using declarative configuration, you need a file +(in YAML or JSON format) containing entity definitions. You can +generate a sample declarative configuration with the command: + +``` +kong config init +``` + +It generates a file named `kong.yml` in the current directory, +containing the appropriate structure and examples. + + +### Reload Declarative Configuration + +This endpoint allows resetting a DB-less Kong with a new +declarative configuration data file. All previous contents +are erased from memory, and the entities specified in the +given file take their place. + +To learn more about the file format, please read the +[declarative configuration][db-less] documentation. + + +
/config
+ +Attributes | Description +---:| --- +`config`
**required** | The config data (in YAML or JSON format) to be loaded. + + +*Response* + +``` +HTTP 200 OK +``` + +``` json +{ + { "services": [], + "routes": [] + } +} +``` + +The response contains a list of all the entities that were parsed from the +input file. + + +--- + +## 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 }} +``` + +### 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 }} +``` + + +--- + +## 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 }} +``` + +### 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 }} +``` + + +--- + +## 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 }} +``` + +### 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 }} +``` + + +--- + +## 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. + + +### 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 }} +``` + + +--- + +### 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/private key pair for an SSL +certificate. These objects are used by Kong to handle SSL/TLS termination for +encrypted requests. 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 }} +``` + +### 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 }} +``` + + +--- + +## 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 }} +``` + +### 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 }} +``` + + +--- + +## 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 }} +``` + +### 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 }} +``` + + +--- + +### 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 }} +``` + +### 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" +} +``` + + +--- + +### 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 + } + ] +} +``` + + +--- + +[clustering]: /{{page.kong_version}}/clustering +[cli]: /{{page.kong_version}}/cli +[active]: /{{page.kong_version}}/health-checks-circuit-breakers/#active-health-checks +[healthchecks]: /{{page.kong_version}}/health-checks-circuit-breakers +[secure-admin-api]: /{{page.kong_version}}/secure-admin-api +[proxy-reference]: /{{page.kong_version}}/proxy +[db-less]: /{{page.kong_version}}/db-less-and-declarative-config +[admin-api]: /{{page.kong_version}}/admin-api diff --git a/app/1.2.x/1.1.x/db-less-and-declarative-config.md b/app/1.2.x/1.1.x/db-less-and-declarative-config.md new file mode 100644 index 000000000000..09d8ddad4f44 --- /dev/null +++ b/app/1.2.x/1.1.x/db-less-and-declarative-config.md @@ -0,0 +1,321 @@ +--- +title: DB-less and Declarative Configuration +--- + + +## Introduction + +Traditionally, Kong has always required a database, which could be either +Postgres or Cassandra, to store its configured entities such as Routes, +Services and Plugins. Kong uses its configuration file, `kong.conf`, to +specify the use of Postgres and Cassandra and its various settings. + +Kong 1.1 added the capability to run Kong without a database, using only +in-memory storage for entities: we call this **DB-less mode**. When running +Kong DB-less, the configuration of entities is done in a second configuration +file, in YAML or JSON, using **declarative configuration**. + +The combination of DB-less mode and declarative configuration has a number +of benefits: + +* Reduced number of dependencies: no need to manage a database installation + if the entire setup for your use-cases fits in memory +* it is a good fit for automation in CI/CD scenarios: configuration for + entities can be kept in a single source of truth managed via a Git + repository +* It enables more deployment options for Kong: for example, DB-less Kong + is a natural fit for a lightweight sidecar in a Service Mesh scenario + +## What Is Declarative Configuration + +If you are already familiar with the concept of declarative configuration you +may skip this section. + +The key idea in declarative configuration is, as its name shows, the notion +that it is *declarative*, as opposed to an *imperative* style of +configuration. "Imperative" means that a configuration is given as a series of +orders: "do this, then to that". "Declative" means that the configuration is +given all at once: "I declare this to be the state of the world". + +The Kong Admin API is an example of an imperative configuration tool: the +final state of the configuration is obtain through a sequence of API calls: +one call to create a Service, another call to create a Route, another call to +add a Plugin, and so on. + +Performing the configuration incrementally like this has the undesirable +side-effect that *intermediate states* happen. In the above example, there is +a window of time in between creating a Route and adding the Plugin in which +the Route did not have the Plugin applied. + +A declarative configuration file, on the other hand, will contain the settings +for all desired entities in a single file, and once that file is loaded into +Kong, it replaces the entire configuration. When incremental changes are +desired, they are made to the declarative configuration file, which is then +reloaded in its entirety. At all times, the configuration described in the +file loaded into Kong is the configured state of the system. + +## Setting Up Kong in DB-less mode + +To use Kong in DB-less mode, set the `database` directive of `kong.conf` +to `off`. As usual, you can do this by editing `kong.conf` and setting +`database=off` or via environment variables. You can then start Kong +as usual: + +``` +$ export KONG_DATABASE=off +$ kong start -c kong.conf +``` + +Once Kong starts, access the `/` endpoint of the Admin API to verify that it +is running without a database. It will return the entire Kong configuration; +verify that `database` is set to `off`: + +``` +$ http :8001/ + +HTTP/1.1 200 OK +Access-Control-Allow-Origin: * +Connection: keep-alive +Content-Length: 6342 +Content-Type: application/json; charset=utf-8 +Date: Wed, 27 Mar 2019 15:24:58 GMT +Server: kong/1.1.0 +{ + "configuration:" { + ... + "database": "off", + ... + }, + ... + "version": "1.1.0" +} +``` + +Kong is running, but no declarative configuration was loaded yet. This +means that the configuration of this node is empty. There are no Routes, +Services or entities of any kind: + +``` +$ http :8001/routes + +HTTP/1.1 200 OK +Access-Control-Allow-Origin: * +Connection: keep-alive +Content-Length: 23 +Content-Type: application/json; charset=utf-8 +Date: Wed, 27 Mar 2019 15:30:02 GMT +Server: kong/1.1.0 + +{ + "data": [], + "next": null +} +``` + +## Creating a Declarative Configuration File + +To load entities into DB-less Kong, we need a declarative configuration +file. The following command will create a skeleton file to get you +started: + +``` +$ kong config -c kong.conf init +``` + +This command creates a `kong.yml` file in the current directory, +containing examples of the syntax for declaring entities and their +relationships. All examples in the generated file are commented-out +by default. You can experiment by uncommenting the examples +(removing the `#` markers) and modifying their values. + +## The Declarative Configuration Format + +The Kong declarative configuration format consists of lists of +entities and their attributes. This is a small, yet, complete +example, which illustrates a number of features: + +```yaml +_format_version: "1.1" + +services: +- name: my-service + url: https://example.com + plugins: + - name: key-auth + routes: + - name: my-route + paths: + - / + +consumers: +- username: my-user + keyauth_credentials: + - key: my-key +``` + +The only mandatory piece of metadata is `_format_version: "1.1"`, which +specifies the version number of the declarative configuration syntax format. +This also matches the minimum version of Kong required to parse the file. + +At the top level, you can specify any Kong entity, be it a core entity such as +`services` and `consumers` as in the above example, or custom entities created +by Plugins, such as `keyauth_credentials`. (This makes the declarative +configuration format inherently extensible, and it is the reason why `kong +config` commands that process declarative configuration require `kong.conf` to +be available, so that the `plugins` directive is taken into account.) + +When entities have a relationship, such as a Route which points to a Service, +this relationship can be specified via nesting. + +Only one-to-one relationships can be specified by nesting: a Plugin that is +applied to a Service can have its relationship depicted via nesting, as in the +example above. Relationships involving more than two entities, such as a +Plugin that is applied to both a Service and a Consumer must be done via a +top-level entry, where the entities can be identified by their primary keys +or identifying names (the same identifiers that can be used to refer to them +in the Admin API). This is an example of a plugin applied to a Service and +a Consumer: + +```yml +plugins: +- name: syslog + consumer: my-user + service: my-service +``` + +## Checking The Declarative Configuration File + +Once you are done editing the file, it is possible to check the syntax +for any errors before attempting to load it into Kong: + +``` +$ kong config -c kong.conf parse kong.yml + +parse successful +``` + +## Loading The Declarative Configuration File + +There are two ways to load a declarative configuration into Kong: via +`kong.conf` and via the Admin API. + +To load a declarative configuration at Kong start-up, use the +`declarative_config` directive in `kong.conf` (or, as usual to all `kong.conf` +entries, the equivalent `KONG_DECLARATIVE_CONFIG` environment variable). + +``` +$ export KONG_DATABASE=off +$ export KONG_DECLARATIVE_CONFIG=kong.yml +$ kong start -c kong.conf +``` + +Alternatively, you can load a declarative configuration into a running +Kong node via its Admin API, using the `/config` endpoint. The +following example loads `kong.yml` using HTTPie: + +``` +$ http :8001/config config=@kong.yml +``` + +The `/config` endpoint replaces the entire set of entities in memory +with the ones specified in the given file. + +## Using Kong in DB-less Mode + +There are a number of things to be aware of when using Kong in DB-less +mode. + +#### Memory Cache Requirements + +The entire configuration of entities must fit inside the Kong +cache. Make sure that the in-memory cache is configured appropriately: +see the `mem_cache_size` directive in `kong.conf`. + +#### No Central Database Coordination + +Since there is no central database, multiple Kong nodes have no +central coordination point and no cluster propagation of data: +nodes are completely independent of each other. + +This means that the declarative configuration should be loaded into each node +independently. Using the `/config` endpoint does not affect other Kong +nodes, since they have no knowledge of each other. + +#### Read-Only Admin API + +Since the only way to configure entities is via declarative configuration, +the endpoints for CRUD operations on entities are effectively read-only +in the Admin API when running Kong in DB-less mode. `GET` operations +for inspecting entities work as usual, but attempts to `POST`, `PATCH` +`PUT` or `DELETE` in endpoints such as `/services` or `/plugins` will return +`HTTP 405 Not Allowed`. + +This restriction is limited to what would be otherwise database operations. In +particular, using `POST` to set the health state of Targets is still enabled, +since this is a node-specific in-memory operation. + +#### Plugin Compatibility + +Not all Kong plugins are compatible with DB-less mode, since some of them +by design require a central database coordination and/or dynamic creation of +entities. + +##### Fully Compatible + +The following plugins only read from the database (most of them just to read +their initial config) so they are fully compatible with DB-less: + +* `aws-lambda` +* `azure-functions` +* `bot-detection` +* `correlation-id` +* `cors` +* `datadog` +* `file-log` +* `http-log` +* `tcp-log` +* `udp-log` +* `syslog` +* `ip-restriction` +* `prometheus` +* `zipkin` +* `request-transformer` +* `response-transformer` +* `request-termination` +* `kubernetes-sidecar-injector` + +##### Partial Compatibility + +Authentication plugins can be used insofar as the set of credentials +used is static and specified as part of the declarative configuration. +Admin API endpoints to dynamically create, update or delete credentials +are not available in DB-less mode. Plugins that fall into this +category are: + +* `acl` +* `basic-auth` +* `hmac-auth` +* `jwt` +* `key-auth` + +Rate limiting plugins bundled with Kong offer different policies for +storing and coordinating counters: a `local` policy which stores counters +the Nodes's memory, applying limits in a per-node fashion; a `redis` +policy which uses Redis as an external key-value store for coordinating +counters across nodes; and a `cluster` policy which uses the Kong database +as a central coordination point for cluster-wide limits. In DB-less mode +the `local` and `redis` policies are available, and `cluster` cannot be +used. Plugins that fall into this category are: + +* `rate-limiting` +* `response-ratelimiting` + +The `pre-function` and `post-function` plugins for serverless can be used +in DB-less mode, with the caveat that if any configured functions attempt to +write to the database, the writes will fail. + +##### Not Compatible + +* `oauth2` - For its regular work, the plugin needs to both generate and delete + tokens, and commit those changes to the database, which is not compatible with + DB-less. diff --git a/app/1.2.x/1.1.x/getting-started/adding-consumers.md b/app/1.2.x/1.1.x/getting-started/adding-consumers.md new file mode 100644 index 000000000000..4b3488cbe3b6 --- /dev/null +++ b/app/1.2.x/1.1.x/getting-started/adding-consumers.md @@ -0,0 +1,97 @@ +--- +title: Adding Consumers +--- + +
+ Before you start: +
    +
  1. Make sure you've installed Kong — It should only take a minute!
  2. +
  3. Make sure you've started Kong.
  4. +
  5. Also, make sure you've configured your Service in Kong.
  6. +
+
+ +In the last section, we learned how to add plugins to Kong, in this section +we're going to learn how to add consumers to your Kong instances. Consumers are +associated to individuals using your Service, and can be used for tracking, access +management, and more. + +**Note:** This section assumes you have [enabled][enabling-plugins] the +[key-auth][key-auth] plugin. If you haven't, you can either [enable the +plugin][enabling-plugins] or skip steps two and three. + +## 1. Create a Consumer through the RESTful API + +Lets create a user named `Jason` by issuing the following request: + +```bash +$ curl -i -X POST \ + --url http://localhost:8001/consumers/ \ + --data "username=Jason" +``` + +You should see a response similar to the one below: + +```http +HTTP/1.1 201 Created +Content-Type: application/json +Connection: keep-alive + +{ + "username": "Jason", + "created_at": 1428555626000, + "id": "bbdf1c48-19dc-4ab7-cae0-ff4f59d87dc9" +} +``` + +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 key credentials for your Consumer + +Now, we can create a key for our recently created consumer `Jason` by +issuing the following request: + +```bash +$ curl -i -X POST \ + --url http://localhost:8001/consumers/Jason/key-auth/ \ + --data 'key=ENTER_KEY_HERE' +``` + +## 3. Verify that your Consumer credentials are valid + +We can now issue the following request to verify that the credentials of +our `Jason` Consumer is valid: + +```bash +$ curl -i -X GET \ + --url http://localhost:8000 \ + --header "Host: example.com" \ + --header "apikey: ENTER_KEY_HERE" +``` + +## Next Steps + +Now that we've covered the basics of adding Services, Routes, Consumers and enabling +Plugins, feel free to read more on Kong in one of the following documents: + +- [Configuration file Reference][configuration] +- [CLI Reference][CLI] +- [Proxy Reference][proxy] +- [Admin API Reference][API] +- [Clustering Reference][cluster] + +Questions? Issues? Contact us on one of the [Community Channels](/community) +for help! + +[key-auth]: /plugins/key-authentication +[API-consumers]: /{{page.kong_version}}/admin-api#create-consumer +[enabling-plugins]: /{{page.kong_version}}/getting-started/enabling-plugins +[configuration]: /{{page.kong_version}}/configuration +[CLI]: /{{page.kong_version}}/cli +[proxy]: /{{page.kong_version}}/proxy +[API]: /{{page.kong_version}}/admin-api +[cluster]: /{{page.kong_version}}/clustering diff --git a/app/1.2.x/1.1.x/getting-started/configuring-a-service.md b/app/1.2.x/1.1.x/getting-started/configuring-a-service.md new file mode 100644 index 000000000000..6c1f819c0068 --- /dev/null +++ b/app/1.2.x/1.1.x/getting-started/configuring-a-service.md @@ -0,0 +1,137 @@ +--- +title: Configuring a Service +--- + +
+ Before you start: +
    +
  1. Make sure you've installed Kong — It should only take a minute!
  2. +
  3. Make sure you've started Kong.
  4. +
+
+ +In this section, you'll be adding an API to Kong. In order to do this, you'll +first need to add a _Service_; that is the name Kong uses to refer to the upstream APIs and microservices +it manages. + +For the purpose of this guide, we'll create a Service pointing to the [Mockbin API][mockbin]. Mockbin is +an "echo" type public website which returns the requests it gets back to the requester, as responses. This +makes it helpful for learning how Kong proxies your API requests. + +Before you can start making requests against the Service, you will need to add a _Route_ to it. +Routes specify how (and _if_) requests are sent to their Services after they reach Kong. A single +Service can have many Routes. + +After configuring the Service and the Route, you'll be able to make requests through Kong using them. + +Kong exposes a [RESTful Admin API][API] on port `:8001`. Kong's configuration, including adding Services and +Routes, is made via requests on that API. + +## 1. Add your Service using the Admin API + +Issue the following cURL request to add your first Service (pointing to the [Mockbin API][mockbin]) +to Kong: + +```bash +$ curl -i -X POST \ + --url http://localhost:8001/services/ \ + --data 'name=example-service' \ + --data 'url=http://mockbin.org' +``` + +You should receive a response similar to: + +```http +HTTP/1.1 201 Created +Content-Type: application/json +Connection: keep-alive + +{ + "host":"mockbin.org", + "created_at":1519130509, + "connect_timeout":60000, + "id":"92956672-f5ea-4e9a-b096-667bf55bc40c", + "protocol":"http", + "name":"example-service", + "read_timeout":60000, + "port":80, + "path":null, + "updated_at":1519130509, + "retries":5, + "write_timeout":60000 +} +``` + + +## 2. Add a Route for the Service + +```bash +$ curl -i -X POST \ + --url http://localhost:8001/services/example-service/routes \ + --data 'hosts[]=example.com' +``` + +The answer should be similar to: + +```http +HTTP/1.1 201 Created +Content-Type: application/json +Connection: keep-alive + +{ + "created_at":1519131139, + "strip_path":true, + "hosts":[ + "example.com" + ], + "preserve_host":false, + "regex_priority":0, + "updated_at":1519131139, + "paths":null, + "service":{ + "id":"79d7ee6e-9fc7-4b95-aa3b-61d2e17e7516" + }, + "methods":null, + "protocols":[ + "http", + "https" + ], + "id":"f9ce2ed7-c06e-4e16-bd5d-3a82daef3f9d" +} +``` + +Kong is now aware of your Service and ready to proxy requests. + +## 3. Forward your requests through Kong + +Issue the following cURL request to verify that Kong is properly forwarding +requests to your Service. Note that [by default][proxy-port] Kong handles proxy +requests on port `:8000`: + +```bash +$ 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 `url` we configured in step #1, +and is forwarding the response back to us. Kong knows to do this through +the header defined in the above cURL request: + +
    +
  • Host: <given host>
  • +
+ +
+ +## Next Steps + +Now that you've added your Service to Kong, let's learn how to enable plugins. + +Go to [Enabling Plugins ›][enabling-plugins] + +[API]: /{{page.kong_version}}/admin-api +[enabling-plugins]: /{{page.kong_version}}/getting-started/enabling-plugins +[proxy-port]: /{{page.kong_version}}/configuration/#nginx-section +[mockbin]: https://mockbin.com/ diff --git a/app/1.2.x/1.1.x/getting-started/enabling-plugins.md b/app/1.2.x/1.1.x/getting-started/enabling-plugins.md new file mode 100644 index 000000000000..36210428c350 --- /dev/null +++ b/app/1.2.x/1.1.x/getting-started/enabling-plugins.md @@ -0,0 +1,74 @@ +--- +title: Enabling Plugins +--- + +
+ Before you start: +
    +
  1. Make sure you've installed Kong - It should only take a minute!
  2. +
  3. Make sure you've started Kong.
  4. +
  5. Also, make sure you've configured your Service in Kong.
  6. +
+
+ +In this section, you'll learn how to configure Kong plugins. One of the core +principles of Kong is its extensibility through [plugins][plugins]. Plugins +allow you to easily add new features to your Service or make it easier to +manage. + +In the steps below you will configure the [key-auth][key-auth] plugin to add +authentication to your Service. Prior to the addition of this plugin, **all** +requests to your Service would be proxied upstream. Once you add and configure this +plugin, **only** requests with the correct key(s) will be proxied - all +other requests will be rejected by Kong, thus protecting your upstream service +from unauthorized use. + + +## 1. Configure the key-auth plugin + +To configure the key-auth plugin for the Service you configured in Kong, +issue the following cURL request: + +```bash +$ curl -i -X POST \ + --url http://localhost:8001/services/example-service/plugins/ \ + --data 'name=key-auth' +``` + +**Note:** This plugin also accepts a `config.key_names` parameter, which +defaults to `['apikey']`. It is a list of headers and parameters names (both +are supported) that are supposed to contain the apikey during a request. + +## 2. Verify that the 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/ \ + --header 'Host: example.com' +``` + +Since you did not specify the required `apikey` header or parameter, the +response should be `401 Unauthorized`: + +```http +HTTP/1.1 401 Unauthorized +... + +{ + "message": "No API key found in request" +} +``` + +## Next Steps + +Now that you've configured the **key-auth** plugin lets learn how to add +consumers to your Service so we can continue proxying requests through Kong. + +Go to [Adding Consumers ›][adding-consumers] + +[key-auth]: /plugins/key-authentication +[plugins]: /plugins +[adding-consumers]: /{{page.kong_version}}/getting-started/adding-consumers diff --git a/app/1.2.x/1.1.x/getting-started/introduction.md b/app/1.2.x/1.1.x/getting-started/introduction.md new file mode 100644 index 000000000000..4a333b9d9414 --- /dev/null +++ b/app/1.2.x/1.1.x/getting-started/introduction.md @@ -0,0 +1,31 @@ +--- +title: Welcome to Kong +--- + +
+ Before you start: Make sure you've installed Kong — It should only take a minute! +
+ +Before going further into Kong, make sure you understand its [purpose and philosophy](/about). Once you are confident with the concept of API Gateways, this guide is going to take you through a quick introduction on how to use Kong and perform basic operations such as: + +- [Running your own Kong instance][quickstart] +- [Adding and consuming Services][configuring-a-service] +- [Installing plugins on Kong][enabling-plugins] + +## What is Kong, technically? + +You’ve probably heard that Kong is built on Nginx, leveraging its stability and efficiency. But how is this possible exactly? + +To be more precise, Kong is a Lua application running in Nginx and made possible by the [lua-nginx-module](https://github.com/openresty/lua-nginx-module). 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. + +This sets the foundations for a pluggable architecture, where Lua scripts (referred to as *”plugins”*) can be enabled and executed at runtime. Because of this, we like to think of Kong as **a paragon of microservice architecture**: at its core, it implements database abstraction, routing and plugin management. Plugins can live in separate code bases and be injected anywhere into the request lifecycle, all in a few lines of code. + +## Next Steps + +Now, lets get familiar with learning how to "start" and "stop" Kong. + +Go to [5-minute quickstart with Kong ›][quickstart] + +[quickstart]: /{{page.kong_version}}/getting-started/quickstart +[configuring-a-service]: /{{page.kong_version}}/getting-started/configuring-a-service +[enabling-plugins]: /{{page.kong_version}}/getting-started/enabling-plugins diff --git a/app/1.2.x/1.1.x/getting-started/quickstart.md b/app/1.2.x/1.1.x/getting-started/quickstart.md new file mode 100644 index 000000000000..2112771250fc --- /dev/null +++ b/app/1.2.x/1.1.x/getting-started/quickstart.md @@ -0,0 +1,80 @@ +--- +title: 5-minute Quickstart +--- + +
+ Before you start: Make sure you've + installed Kong — It should only take a minute! +
+ +In this section, you'll learn how to manage your Kong instance. First, we'll +have you start Kong in order to give you access to the RESTful Admin +interface, through which you manage your Services, Routes, Consumers, and more. Data sent +through the Admin API is stored in Kong's [datastore][datastore-section] (Kong +supports PostgreSQL and Cassandra). + +## 1. Start Kong + +Issue the following command to prepare your datastore by running the Kong +migrations: + +```bash +$ kong migrations bootstrap [-c /path/to/kong.conf] +``` + +You should see a message that tells you Kong has successfully migrated your +database. If not, you probably incorrectly configured your database +connection settings in your configuration file. + +Now let's [start][CLI] Kong: + +```bash +$ 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][configuration-loading]. + +## 2. Verify that Kong has started successfully + +If everything went well, you should see a message (`Kong started`) +informing you that Kong is running. + +By default Kong listens on the following ports: + +- `:8000` on which Kong listens for incoming HTTP traffic from your + clients, and forwards it to your upstream services. +- `:8443` on which Kong listens for incoming HTTPS traffic. This port has a + similar behavior as the `:8000` port, except that it expects HTTPS + traffic only. This port can be disabled via the configuration file. +- `:8001` on which the [Admin API][API] used to configure Kong listens. +- `:8444` on which the Admin API listens for HTTPS traffic. + +## 3. Stop Kong + +As needed you can stop the Kong process by issuing the following +[command][CLI]: + +```bash +$ kong stop +``` + +## 4. Reload Kong + +Issue the following command to [reload][CLI] Kong without downtime: + +```bash +$ kong reload +``` + +## Next Steps + +Now that you have Kong running you can interact with the Admin API. + +To begin, go to [Configuring a Service ›][configuring-a-service] + +[configuration-loading]: /{{page.kong_version}}/configuration/#configuration-loading +[CLI]: /{{page.kong_version}}/cli +[API]: /{{page.kong_version}}/admin-api +[datastore-section]: /{{page.kong_version}}/configuration/#datastore-section +[configuring-a-service]: /{{page.kong_version}}/getting-started/configuring-a-service diff --git a/app/1.2.x/1.1.x/health-checks-circuit-breakers.md b/app/1.2.x/1.1.x/health-checks-circuit-breakers.md new file mode 100644 index 000000000000..18a6f0784aaf --- /dev/null +++ b/app/1.2.x/1.1.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]: /{{page.kong_version}}/loadbalancing#ring-balancer +[ringtarget]: /{{page.kong_version}}/loadbalancing#target +[upstream]: /{{page.kong_version}}/loadbalancing#upstream +[targetobject]: /{{page.kong_version}}/admin-api#target-object +[addupstream]: /{{page.kong_version}}/admin-api#add-upstream +[clustering]: /{{page.kong_version}}/clustering +[upstreamobjects]: /{{page.kong_version}}/admin-api#upstream-objects +[balancercaveats]: /{{page.kong_version}}/loadbalancing#balancing-caveats +[dnscaveats]: /{{page.kong_version}}/loadbalancing#dns-caveats diff --git a/app/1.2.x/1.1.x/index.md b/app/1.2.x/1.1.x/index.md new file mode 100644 index 000000000000..3ef4630e281a --- /dev/null +++ b/app/1.2.x/1.1.x/index.md @@ -0,0 +1,91 @@ +--- +title: Documentation for Kong +--- + +
+
+

Installation

+

You can install Kong on most Linux distributions and macOS. We even provide the source so you can compile yourself.

+ Install Kong → +
+ +
+

5-minute Quickstart

+

Learn how to start Kong, add a Service, enable plugins, and add consumers in under thirty seconds.

+ Start using Kong → +
+ +
+

DB-less & Declarative Configuration

+

Learn how to leverage the declarative configuration format for using Kong without a database, using in-memory storage only.

+ Read the tutorial → +
+ +
+

Streams & Service Mesh

+

Want to use Kong over TCP traffic? Want to start using Service Mesh? Check our tutorial to learn how to do it.

+ Read the tutorial → +
+ +
+

Kubernetes & Service Mesh

+

We have a quick demo repository showing how to run Kong Service Mesh on Kubernetes.

+ Visit the repo → +
+ +
+

Upgrade guide

+

Already using Kong, and wanting to upgrade? Here's the step-by-step guide.

+ Read the upgrade guide → +
+ +
+

Configuration file

+

Want to further optimize your Kong cluster, database, or configure NGINX? Dive into the configuration.

+ Start configuring Kong → +
+ +
+

CLI reference

+

Want a better understanding of the CLI tool and its options? Browse the detailed command reference.

+ Use the CLI → +
+ +
+

Admin API reference

+

Ready to learn the underlying interface? Browse the Admin API reference to learn how to start making requests.

+ Explore the interface → +
+ +
+

Proxy reference

+

Learn every way to configure Kong to proxy your Services, serve them over SSL or use WebSockets.

+ Read the Proxy Reference → +
+ +
+

Load balancing reference

+

Learn how to setup Kong to load balance traffic through replicas of your upstream services.

+ Read the Load balancing Reference → +
+ +
+

Health checks & circuit breakers

+

Let Kong monitor the availability of your services and adjust its load balancing accordingly.

+ Learn about health checks and circuit breakers → +
+ +
+

Clustering

+

If you are starting more than one node, you must use clustering to make sure all the nodes belong to the same Kong cluster.

+ Read the clustering reference → +
+ +
+

Write your own plugins

+

Looking for something Kong does not do for you? Easy: write it as a plugin. Learn how to write your own plugins for Kong.

+ Read the plugin development guide → +
+ + +
diff --git a/app/1.2.x/1.1.x/loadbalancing.md b/app/1.2.x/1.1.x/loadbalancing.md new file mode 100644 index 000000000000..bee0dac7f2c1 --- /dev/null +++ b/app/1.2.x/1.1.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]: /{{page.kong_version}}/admin-api#upstream-object +[target-object-reference]: /{{page.kong_version}}/admin-api#target-object +[dns-order-config]: /{{page.kong_version}}/configuration/#dns_order +[real-ip-config]: /{{page.kong_version}}/configuration/#real_ip_header +[blue-green-canary]: http://blog.christianposta.com/deploy/blue-green-deployments-a-b-testing-and-canary-releases/ diff --git a/app/1.2.x/1.1.x/logging.md b/app/1.2.x/1.1.x/logging.md new file mode 100644 index 000000000000..33008a60099c --- /dev/null +++ b/app/1.2.x/1.1.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](/{{page.kong_version}}/configuration/#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/1.2.x/1.1.x/network.md b/app/1.2.x/1.1.x/network.md new file mode 100644 index 000000000000..0875cfe153d2 --- /dev/null +++ b/app/1.2.x/1.1.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]: /{{page.kong_version}}/configuration/#proxy_listen +[stream_listen]: /{{page.kong_version}}/configuration/#stream_listen +[admin_listen]: /{{page.kong_version}}/configuration/#admin_listen +[secure_admin_api]: /{{page.kong_version}}/secure-admin-api diff --git a/app/1.2.x/1.1.x/pdk/index.md b/app/1.2.x/1.1.x/pdk/index.md new file mode 100644 index 000000000000..2f951970b6c4 --- /dev/null +++ b/app/1.2.x/1.1.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/1.2.x/1.1.x/pdk/kong.client.md b/app/1.2.x/1.1.x/pdk/kong.client.md new file mode 100644 index 000000000000..2528544fad15 --- /dev/null +++ b/app/1.2.x/1.1.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](https://getkong.org/docs/latest/configuration/#trusted_ips) + * [real\_ip\_header](https://getkong.org/docs/latest/configuration/#real_ip_header) + * [real\_ip\_recursive](https://getkong.org/docs/latest/configuration/#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](https://getkong.org/docs/latest/configuration/#trusted_ips) + * [real\_ip\_header](https://getkong.org/docs/latest/configuration/#real_ip_header) + * [real\_ip\_recursive](https://getkong.org/docs/latest/configuration/#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/1.2.x/1.1.x/pdk/kong.ctx.md b/app/1.2.x/1.1.x/pdk/kong.ctx.md new file mode 100644 index 000000000000..c44dc7e8a776 --- /dev/null +++ b/app/1.2.x/1.1.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/1.2.x/1.1.x/pdk/kong.ip.md b/app/1.2.x/1.1.x/pdk/kong.ip.md new file mode 100644 index 000000000000..86c74d21942e --- /dev/null +++ b/app/1.2.x/1.1.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/1.2.x/1.1.x/pdk/kong.log.md b/app/1.2.x/1.1.x/pdk/kong.log.md new file mode 100644 index 000000000000..1914b5d02f3c --- /dev/null +++ b/app/1.2.x/1.1.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/1.2.x/1.1.x/pdk/kong.node.md b/app/1.2.x/1.1.x/pdk/kong.node.md new file mode 100644 index 000000000000..b712a6340fd1 --- /dev/null +++ b/app/1.2.x/1.1.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/1.2.x/1.1.x/pdk/kong.request.md b/app/1.2.x/1.1.x/pdk/kong.request.md new file mode 100644 index 000000000000..6dff1299e3fb --- /dev/null +++ b/app/1.2.x/1.1.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](https://getkong.org/docs/latest/configuration/#trusted_ips) + * [real\_ip\_header](https://getkong.org/docs/latest/configuration/#real_ip_header) + * [real\_ip\_recursive](https://getkong.org/docs/latest/configuration/#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](https://getkong.org/docs/latest/configuration/#trusted_ips) + * [real\_ip\_header](https://getkong.org/docs/latest/configuration/#real_ip_header) + * [real\_ip\_recursive](https://getkong.org/docs/latest/configuration/#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](https://getkong.org/docs/latest/configuration/#trusted_ips) + * [real\_ip\_header](https://getkong.org/docs/latest/configuration/#real_ip_header) + * [real\_ip\_recursive](https://getkong.org/docs/latest/configuration/#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"` and `"2.0."`, or `nil` for + unrecognized values. + +**Phases** + +* rewrite, access, header_filter, body_filter, log, admin_api + +**Returns** + +* `string|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/1.2.x/1.1.x/pdk/kong.response.md b/app/1.2.x/1.1.x/pdk/kong.response.md new file mode 100644 index 000000000000..34e0288186a0 --- /dev/null +++ b/app/1.2.x/1.1.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/1.2.x/1.1.x/pdk/kong.router.md b/app/1.2.x/1.1.x/pdk/kong.router.md new file mode 100644 index 000000000000..c30ceb5fca48 --- /dev/null +++ b/app/1.2.x/1.1.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/1.2.x/1.1.x/pdk/kong.service.md b/app/1.2.x/1.1.x/pdk/kong.service.md new file mode 100644 index 000000000000..dce94eb96192 --- /dev/null +++ b/app/1.2.x/1.1.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/1.2.x/1.1.x/pdk/kong.service.request.md b/app/1.2.x/1.1.x/pdk/kong.service.request.md new file mode 100644 index 000000000000..c47d45e974b6 --- /dev/null +++ b/app/1.2.x/1.1.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/1.2.x/1.1.x/pdk/kong.service.response.md b/app/1.2.x/1.1.x/pdk/kong.service.response.md new file mode 100644 index 000000000000..feede11b266e --- /dev/null +++ b/app/1.2.x/1.1.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/1.2.x/1.1.x/pdk/kong.table.md b/app/1.2.x/1.1.x/pdk/kong.table.md new file mode 100644 index 000000000000..7e62db9eed94 --- /dev/null +++ b/app/1.2.x/1.1.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/1.2.x/1.1.x/plugin-development/access-the-datastore.md b/app/1.2.x/1.1.x/plugin-development/access-the-datastore.md new file mode 100644 index 000000000000..63fab7c8aa5c --- /dev/null +++ b/app/1.2.x/1.1.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]: /{{page.kong_version}}/pdk diff --git a/app/1.2.x/1.1.x/plugin-development/admin-api.md b/app/1.2.x/1.1.x/plugin-development/admin-api.md new file mode 100644 index 000000000000..58184b86690f --- /dev/null +++ b/app/1.2.x/1.1.x/plugin-development/admin-api.md @@ -0,0 +1,174 @@ +--- +title: Plugin Development - Extending the Admin API +book: plugin_dev +chapter: 8 +--- + +
+ Note: This chapter assumes that you have a relative + knowledge of Lapis. +
+ +## Introduction + +Kong can be configured using a REST interface referred to as the [Admin API]. +Plugins can extend it by adding their own endpoints to accommodate custom +entities or other personalized management needs. A typical example of this is +the creation, retrieval, and deletion (commonly referred to as "CRUD +operations") of API keys. + +The Admin API is a [Lapis](http://leafo.net/lapis/) application, and Kong's +level of abstraction makes it easy for you to add endpoints. + +## Module + +``` +kong.plugins..api +``` + +## Adding endpoints to the Admin API + +Kong will detect and load your endpoints if they are defined in a module named: + +``` +"kong.plugins..api" +``` + +This module is bound to return a table with one or more entries with the following structure: + +``` lua +{ + [""] = { + schema = , + methods = { + before = function(self) ... end, + on_error = function(self) ... end, + GET = function(self) ... end, + PUT = function(self) ... end, + ... + } + }, + ... +} +``` + +Where: + +- `` should be a string representing a route like `/users` (See [Lapis routes & URL + Patterns](http://leafo.net/lapis/reference/actions.html#routes--url-patterns)) for details. + Notice that the path can contain interpolation parameters, like `/users/:users/new`. +- `` is a schema definition. Schemas for core and custom plugin entities are available + via `kong.db..schema`. The schema is used to parse certain fields according to their + types; for example if a field is marked as an integer, it will be parsed as such when it is + passed to a function (by default form fields are all strings). +- The `methods` subtable contains functions, indexed by a string. + - The `before` key is optional and can hold a function. If present, the function will be executed + on every request that hits `path`, before any other function is invoked. + - One or more functions can be indexed with HTTP method names, like `GET` or `PUT`. These functions + will be executed when the appropriate HTTP method and `path` is matched. If a `before` function is + present on the `path`, it will be executed first. Keep in mind that `before` functions can + use `kong.response.exit` to finish early, effectively cancelling the "regular" http method function. + - The `on_error` key is optional and can hold a function. If present, the function will be executed + when the code from other functions (either from a `before` or a "http method") throws an error. If + not present, then Kong will use a default error handler to return the errors. + +For example: + +``` lua +local endpoints = require "kong.api.endpoints" + +local credentials_schema = kong.db.keyauth_credentials.schema +local consumers_schema = kong.db.consumers.schema + +return { + ["/consumers/:consumers/key-auth"] = { + schema = credentials_schema, + methods = { + GET = endpoints.get_collection_endpoint( + credentials_schema, consumers_schema, "consumer"), + + POST = endpoints.post_collection_endpoint( + credentials_schema, consumers_schema, "consumer"), + }, + }, +} +``` + +This code will create two Admin API endpoints in `/consumers/:consumers/key-auth`, to +obtain (`GET`) and create (`POST`) credentials associated to a given consumer. On this example +the functions are provided by the `kong.api.endpoints` library. If you want to see a more +complete example, with custom code in functions, see +[the `api.lua` file from the key-auth plugin](https://github.com/Kong/kong/blob/master/kong/plugins/key-auth/api.lua). + +The `endpoints` module currently contains the default implementation for the most usual CRUD +operations used in Kong. This module provides you with helpers for any insert, retrieve, +update or delete operations and performs the necessary DAO operations and replies with +the appropriate HTTP status codes. It also provides you with functions to retrieve parameters from +the path, such as an Service's name or id, or a Consumer's username or id. + +If `endpoints`-provided are functions not enough, a regular Lua function can be used instead. From there you can use: + +- Several functions provided by the `endpoints` module. +- All the functionality provided by the [PDK](../../pdk) +- The `self` parameter, which is the [Lapis request object](http://leafo.net/lapis/reference/actions.html#request-object). +- And of course you can `require` any Lua modules if needed. Make sure they are compatible with OpenResty if you choose this route. + +``` lua +local endpoints = require "kong.api.endpoints" + +local credentials_schema = kong.db.keyauth_credentials.schema +local consumers_schema = kong.db.consumers.schema + +return { + ["/consumers/:consumers/key-auth/:keyauth_credentials"] = { + schema = credentials_schema, + methods = { + before = function(self, db, helpers) + local consumer, _, err_t = endpoints.select_entity(self, db, consumers_schema) + if err_t then + return endpoints.handle_error(err_t) + end + if not consumer then + return kong.response.exit(404, { message = "Not found" }) + end + + self.consumer = consumer + + if self.req.method ~= "PUT" then + local cred, _, err_t = endpoints.select_entity(self, db, credentials_schema) + if err_t then + return endpoints.handle_error(err_t) + end + + if not cred or cred.consumer.id ~= consumer.id then + return kong.response.exit(404, { message = "Not found" }) + end + self.keyauth_credential = cred + self.params.keyauth_credentials = cred.id + end + end, + GET = endpoints.get_entity_endpoint(credentials_schema), + PUT = function(self, db, helpers) + self.args.post.consumer = { id = self.consumer.id } + return endpoints.put_entity_endpoint(credentials_schema)(self, db, helpers) + end, + }, + }, +} +``` + +On the previous example, the `/consumers/:consumers/key-auth/:keyauth_credentials` path gets +three functions: +- The `before` function is a custom Lua function which uses several `endpoints`-provided utilities + (`endpoints.handle_error`) as well as PDK functions (`kong.response.exit`). It also populates + `self.consumer` for the subsequent functions to use. +- The `GET` function is built entirely using `endpoints`. This is possible because the `before` has + "prepared" things in advance, like `self.consumer`. +- The `PUT` function populates `self.args.post.consumer` before calling the `endpoints`-provided + `put_entity_endpoint` function. + +--- + +Next: [Write tests for your plugin]({{page.book.next}}) + +[Admin API]: /{{page.kong_version}}/admin-api/ diff --git a/app/1.2.x/1.1.x/plugin-development/custom-entities.md b/app/1.2.x/1.1.x/plugin-development/custom-entities.md new file mode 100644 index 000000000000..ecde4cd79626 --- /dev/null +++ b/app/1.2.x/1.1.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]: /{{page.kong_version}}/admin-api/ +[Plugin Development Kit]: /{{page.kong_version}}/pdk diff --git a/app/1.2.x/1.1.x/plugin-development/custom-logic.md b/app/1.2.x/1.1.x/plugin-development/custom-logic.md new file mode 100644 index 000000000000..3553c5148400 --- /dev/null +++ b/app/1.2.x/1.1.x/plugin-development/custom-logic.md @@ -0,0 +1,302 @@ +--- +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 +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]: /{{page.kong_version}}/pdk diff --git a/app/1.2.x/1.1.x/plugin-development/distribution.md b/app/1.2.x/1.1.x/plugin-development/distribution.md new file mode 100644 index 000000000000..3b1d6bf66a9c --- /dev/null +++ b/app/1.2.x/1.1.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](/{{page.kong_version}}/configuration/#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/1.2.x/1.1.x/plugin-development/entities-cache.md b/app/1.2.x/1.1.x/plugin-development/entities-cache.md new file mode 100644 index 000000000000..c7ad22f77cd7 --- /dev/null +++ b/app/1.2.x/1.1.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](/{{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](/{{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]: /{{page.kong_version}}/admin-api/ +[Plugin Development Kit]: /{{page.kong_version}}/pdk diff --git a/app/1.2.x/1.1.x/plugin-development/file-structure.md b/app/1.2.x/1.1.x/plugin-development/file-structure.md new file mode 100644 index 000000000000..84f8599232c7 --- /dev/null +++ b/app/1.2.x/1.1.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](/{{page.kong_version}}/configuration/#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](/{{page.kong_version}}/configuration/#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/1.2.x/1.1.x/plugin-development/index.md b/app/1.2.x/1.1.x/plugin-development/index.md new file mode 100644 index 000000000000..a317d734fffd --- /dev/null +++ b/app/1.2.x/1.1.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]: /{{page.kong_version}}/pdk diff --git a/app/1.2.x/1.1.x/plugin-development/plugin-configuration.md b/app/1.2.x/1.1.x/plugin-development/plugin-configuration.md new file mode 100644 index 000000000000..4ba66bb6676b --- /dev/null +++ b/app/1.2.x/1.1.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](http://localhost:3000/docs/0.14.x/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]: /{{page.kong_version}}/admin-api +[Plugin Development Kit]: /{{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/1.2.x/1.1.x/plugin-development/tests.md b/app/1.2.x/1.1.x/plugin-development/tests.md new file mode 100644 index 000000000000..398b641d6150 --- /dev/null +++ b/app/1.2.x/1.1.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/10-key-auth) + +--- + +Next: [Distribute your plugin ›]({{page.book.next}}) diff --git a/app/1.2.x/1.1.x/proxy.md b/app/1.2.x/1.1.x/proxy.md new file mode 100644 index 000000000000..56988c5ea2c7 --- /dev/null +++ b/app/1.2.x/1.1.x/proxy.md @@ -0,0 +1,1109 @@ +--- +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 1.0.0, 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. +This means that considering 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/any/` +2. `/version` +3. `/version/\d+/status/\d+` +4. `/status/\d+` + +Prefix paths are always evaluated before regex paths. + +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 (see [Routing priorities][proxy-routing-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. + +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=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: ssl-example.com" +HTTP/1.1 200 OK +... +``` + +When establishing the connection and negotiating the SSL handshake, if your +client sends `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 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]: /{{page.kong_version}}/admin-api#plugin-object +[plugin-development-guide]: /{{page.kong_version}}/plugin-development +[plugin-association-rules]: /{{page.kong_version}}/admin-api/#precedence +[load-balancing-reference]: /{{page.kong_version}}/loadbalancing +[configuration-reference]: /{{page.kong_version}}/configuration-reference +[configuration-trusted-ips]: /{{page.kong_version}}/configuration/#trusted_ips +[configuring-a-service]: /{{page.kong_version}}/getting-started/configuring-a-service +[API]: /{{page.kong_version}}/admin-api +[service-entity]: /{{page.kong_version}}/admin-api/#add-service +[route-entity]: /{{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/1.2.x/1.1.x/secure-admin-api.md b/app/1.2.x/1.1.x/secure-admin-api.md new file mode 100644 index 000000000000..dcdb40f3e7fb --- /dev/null +++ b/app/1.2.x/1.1.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]: /{{page.kong_version}}/configuration/#custom-nginx-configuration +[ip-restriction]: /plugins/ip-restriction +[key-auth]: /plugins/key-authentication diff --git a/app/1.2.x/1.1.x/streams-and-service-mesh.md b/app/1.2.x/1.1.x/streams-and-service-mesh.md new file mode 100644 index 000000000000..0b44db64f8b5 --- /dev/null +++ b/app/1.2.x/1.1.x/streams-and-service-mesh.md @@ -0,0 +1,643 @@ +--- +title: Streams and Service Mesh +--- + + +## Introduction + +Kong `0.15.0` / `1.0.0` added the capability to proxy and route raw `tcp` and `tls` +streams and deploy Kong using a service-mesh sidecar pattern with mutual +`tls` between Kong nodes. This tutorial walks you trough a basic setup of +a simplified Service Mesh deployment using simple tooling: two servers, +talking with each other via two Kong nodes, in a single host. It introduces +new concepts, configuration settings and tools along the way. In a production +environment, almost all of this should be automated. It is still nice to +know how things work on a lower level. If you are interested in running +Service Mesh with Kubernetes, please head over to our +[Kubernetes and Service Mesh example repo](https://github.com/Kong/kong-mesh-dist-kubernetes). + +Kong supports gradual deployment of a sidecar pattern. It can work both as +a traditional gateway and as a service mesh node at the same time. In Kong +the service mesh is built dynamically, and it only exists when there are +active connections between the Kong nodes. In short it means that Kong nodes +do not have to know about other Kong nodes, and services do not have to +know about Kong. + + +## Prerequisites + +You need **Kong 1.1.0 or later** to run through different deployment scenarios +in this tutorial. It is recommended to use Linux distribution to run +the demos, e.g. a recent version of Ubuntu. You will also need some additional +tools to be installed on your system: + +- `ncat` (usually comes with `nmap`) +- `iptables` (**Linux**) or `pfctl` (**macOS** / **BSD**) +- `curl` + +Your host machine needs to bind `lo0` (or similar) network adapter to these +localhost IPs: + +- `127.0.0.1` (**Host C** running **Kong Control Plane**) +- `127.0.0.2` (**Host A** running **Service A**) +- `127.0.0.3` (**Host A** running **Kong A**) +- `127.0.0.4` (**Host B** running **Kong B**) +- `127.0.0.5` (**Host B** running **Service B**) + +We are running everything in a single host on this tutorial, but you are allowed +to use two separate nodes to run the demos. In such case, please note that there +will be differences in IP addresses in related commands and configurations. +For the sake of simplicity we also configure everything using just IP addresses +instead of using DNS. + +For some of the configuration changes, you may also need **root** privileges on +a target host. + + +## Terms and Definitions + + +**Kong Control Plane** is started on network address `127.0.0.1`. It listens on Kong +Admin API on ports `8001` (`http`), and `8444` (`https`), and it won't proxy any traffic. + +**Service A** represents an imaginary business entity (microservice, app) making the network +connections to **Service B**. On this tutorial **Service A** is modelled by +direct invocations of `ncat` and `curl`. **Service A**'s network address is `127.0.0.2`. + +**Service B** represent a business entity which accepts network connections from **Service A**. +On this tutorial it is implemented via several `ncat` processes, kept open. Its network address +is `127.0.0.5`, and it listens on ports `18000`(`http`), `18443`(`https`), `19000`(`tcp`), and +`19443`(`tls`). + +**Kong A** is the sidecar proxy in-front of **Service A**. It listens on network address +`127.0.0.3` on proxy ports `8000` (`http`), `8443` (`https`), `9000` (`tcp`), and `9443` (`tls`). +It does not listen or provide Kong Admin API. + +**Kong B** is the sidecar proxy in-front of **Service B**. It listens on network address +`127.0.0.4` on proxy ports `8000` (`http`), `8443` (`https`), `9000` (`tcp`), and `9443` (`tls`). +It does not listen or provide Kong Admin API. + +The examples presented here are run directly from a `terminal`, such as `bash` shell. +Please follow each step as it gradually builds the understanding and introduces new +concepts along the way. + + +## Step 1: Start Service B + +As we said before, **Service B** can be modelled as several `ncat` processes. We need +several in order to model all possible Service Mesh combinations. + + +Start **Service B** listening on TCP traffic: + +``` +$ ncat --listen \ + --keep-open \ + --verbose \ + --sh-exec "echo 'Hello from Service B (TCP)'" \ + 127.0.0.5 19000 +``` + +You should see output similar to one below: + +``` +Ncat: Version 7.70 ( https://nmap.org/ncat ) +Ncat: Listening on 127.0.0.5:19000 +``` + +Leave the command running. + + +Open a new console and start **Service B** listening on TLS traffic: + +``` +$ ncat --listen \ + --keep-open \ + --verbose \ + --ssl \ + --sh-exec "echo 'Hello from Service B (TLS)'" \ + 127.0.0.5 19443 +``` + +You should see output similar to one below: + +``` +Ncat: Version 7.70 ( https://nmap.org/ncat ) +Ncat: Listening on 127.0.0.5:19443 +``` + +Leave it running. + + +Open a new console and start **Service B** listening on HTTP traffic: + +``` +ncat --listen \ + --keep-open \ + --verbose \ + --sh-exec "echo 'HTTP/1.1 200 OK\r\n\r\nHello from Service (HTTP)'" \ + 127.0.0.5 18000 +``` + +You should see output similar to one below: + +``` +Ncat: Version 7.70 ( https://nmap.org/ncat ) +Ncat: Listening on 127.0.0.5:18000 +``` + +Again, leave that running. + + +Open a fourth console and start **Service B** listening on HTTPS traffic: + +``` +ncat --listen \ + --keep-open \ + --verbose \ + --ssl \ + --sh-exec "echo 'HTTP/1.1 200 OK\r\n\r\nHello from Service B (HTTPS)'" \ + 127.0.0.5 18443 +``` + +You should see output similar to one below: + +``` +Ncat: Version 7.70 ( https://nmap.org/ncat ) +Ncat: Listening on 127.0.0.5:18443 +``` + +Leave this command running as well. + +At this point you should have four `ncat` processes in 4 consoles, +representing the **Service B** listening with different protocols. + + +## Step 2: Ensure that Service A can connect Service B + +Our **Service A** is just direct invocations of `ncat` and `curl`. + + +Connect with **Service B** using TCP: + +``` +ncat --source 127.0.0.2 --recv-only 127.0.0.5 19000 +``` + +You should see output similar to one below: + +``` +Hello from Service B (TCP) +``` + + +Connect with **Service B** using TLS: + +``` +ncat --source 127.0.0.2 --recv-only --ssl 127.0.0.5 19443 +``` + +You should see output similar to one below: + +``` +Hello from Service B (TLS) +``` + + +Connect with **Service B** using HTTP: + +``` +curl --interface 127.0.0.2 http://127.0.0.5:18000 +``` + +You should see output similar to one below: + +``` +Hello from Service B (HTTP) +``` + + +Connect with **Service B** using HTTPS: + +``` +curl --interface 127.0.0.2 --insecure https://127.0.0.5:18443 +``` + +You should see output similar to one below: + +``` +Hello from Service B (HTTPS) +``` + +At this point you have **Service B** running at `127.0.0.5` and our +**Service A** at `127.0.0.2` can directly and successfully connect +to it. + + +## Step 3: Start Kong Control Plane + +Start a Kong node that only listens to its Kong Admin API: + +``` +$ KONG_PREFIX=kong-c \ + KONG_LOG_LEVEL=debug \ + KONG_STREAM_LISTEN="off" \ + KONG_PROXY_LISTEN="off" \ + KONG_ADMIN_LISTEN="127.0.0.1:8001, 127.0.0.1:8444 ssl" \ + kong start +``` + +You should see this message: + +``` +Kong started +``` + + +## Step 4: Start Kong A + +**Kong A**, will be a Kong instance acting as sidecar for **Service A**. + +Start it like this: + +``` +$ KONG_PREFIX=kong-a \ + KONG_LOG_LEVEL=debug \ + KONG_STREAM_LISTEN="127.0.0.3:9000 transparent, 127.0.0.3:9443 transparent" \ + KONG_PROXY_LISTEN="127.0.0.3:8000 transparent, 127.0.0.3:8443 ssl transparent" \ + KONG_ADMIN_LISTEN="off" \ + KONG_NGINX_PROXY_PROXY_BIND="127.0.0.3" \ + KONG_NGINX_SPROXY_PROXY_BIND="127.0.0.3" \ + kong start +``` + +On `macOS` / `BSD` use this instead: + +``` +$ KONG_PREFIX=kong-a \ + KONG_LOG_LEVEL=debug \ + KONG_STREAM_LISTEN="127.0.0.3:9000, 127.0.0.3:9443" \ + KONG_PROXY_LISTEN="127.0.0.3:8000, 127.0.0.3:8443 ssl" \ + KONG_ADMIN_LISTEN="off" \ + KONG_NGINX_PROXY_PROXY_BIND="127.0.0.3" \ + KONG_NGINX_SPROXY_PROXY_BIND="127.0.0.3" \ + kong start +``` + +You should see this message: + +``` +Kong started +``` + + +### About the `transparent` option + +The `transparent` listen option makes it possible for Kong to answer requests +mangled with `iptables` `PREROUTING` rules, and to read the original destination +address and the port that client tried to connect before `iptables` rules +did `transparently` proxy it to its sidecar proxy. + +**Note:** `transparent` is only supported on `Linux`, and specifying +it may require you to start Kong as a `root` user. If you are **not** running +`Linux` (e.g. `macOS` or `BSD`), the transparent proxying is supported by default. + + +## Step 5: Start Kong B + +**Kong B** will be the sidecar Kong instance for **Service B**. + +``` +$ KONG_PREFIX=kong-b \ + KONG_LOG_LEVEL=debug \ + KONG_STREAM_LISTEN="127.0.0.4:9000 transparent, 127.0.0.4:9443 transparent" \ + KONG_PROXY_LISTEN="127.0.0.4:8000 transparent, 127.0.0.4:8443 transparent ssl" \ + KONG_ADMIN_LISTEN="off" \ + KONG_NGINX_PROXY_PROXY_BIND="127.0.0.4" \ + KONG_NGINX_SPROXY_PROXY_BIND="127.0.0.4" \ + kong start +``` + +On `macOS` / `BSD` use this instead: + +``` +$ KONG_PREFIX=kong-b \ + KONG_LOG_LEVEL=debug \ + KONG_STREAM_LISTEN="127.0.0.4:9000, 127.0.0.4:9443" \ + KONG_PROXY_LISTEN="127.0.0.4:8000, 127.0.0.4:8443 ssl" \ + KONG_ADMIN_LISTEN="off" \ + KONG_NGINX_PROXY_PROXY_BIND="127.0.0.4" \ + KONG_NGINX_SPROXY_PROXY_BIND="127.0.0.4" \ + kong start +``` + +You should see this message if the Kong node starts successfully: + +``` +Kong started +``` + +**Note**: In the real world, you should use `nginx worker user` to make the exceptions +to `iptables` rules (see step 7), but for this simplified demo, we use the `proxy_bind` +for the exceptions on rules. + + +## Step 6: Create Kong Services and Routes + +Create Kong Service for **Service B**'s TCP Traffic: + +``` +$ curl -X PUT \ + -d url=tcp://127.0.0.5:19000 \ + http://127.0.0.1:8001/services/service-b-tcp +``` + +Create one Kong Route for that Kong Service: + +``` +$ curl -X POST \ + -d name=service-b-tcp \ + -d protocols=tcp \ + -d destinations[1].ip=127.0.0.5 \ + -d destinations[1].port=19000 \ + http://127.0.0.1:8001/services/service-b-tcp/routes +``` + +Create a Kong Service for **Service B**'s TLS Traffic: + +``` +$ curl -X PUT \ + -d url=tls://127.0.0.5:19443 \ + http://127.0.0.1:8001/services/service-b-tls +``` + +And one Route for it: + +``` +$ curl -X POST \ + -d name=service-b-tls \ + -d protocols=tls \ + -d destinations[1].ip=127.0.0.5 \ + -d destinations[1].port=19443 \ + http://127.0.0.1:8001/services/service-b-tls/routes +``` + +Create a Kong Service for **Service B**'s HTTP Traffic: + +``` +$ curl -X PUT \ + -d url=http://127.0.0.5:18000 \ + http://127.0.0.1:8001/services/service-b-http +``` + +Create a Kong Route for this Kong Service as well: + +``` +$ curl -X POST \ + -d name=service-b-http \ + -d protocols=http \ + -d hosts=127.0.0.5 \ + http://127.0.0.1:8001/services/service-b-http/routes +``` + +Finally, create a Kong Service for **Service B**'s HTTPS Traffic: + +``` +$ curl -X PUT \ + -d url=https://127.0.0.5:18443/ \ + http://127.0.0.1:8001/services/service-b-https +``` + +And a Kong Route to go with it: + +``` +$ curl -X POST \ + -d name=service-b-https \ + -d protocols=https \ + -d hosts=127.0.0.5 \ + http://127.0.0.1:8001/services/service-b-https/routes +``` + + +## Step 7: Configure Transparent Proxying Rules + +Following `iptables` commands add transparent proxying rules for **Service A**. +They make **Service A** to connect **Kong A** instead of connecting to to **Service B** +directly as we saw on Step 2. + +Configure `iptables` on **Service A**: + +``` +$ sudo iptables --insert PREROUTING \ + --table mangle \ + --protocol tcp \ + --dport 19000 \ + --source 127.0.0.2 \ + --jump TPROXY \ + --on-port=9000 \ + --on-ip=127.0.0.3 + +$ sudo iptables --insert PREROUTING \ + --table mangle \ + --protocol tcp \ + --dport 19443 \ + --source 127.0.0.2 \ + --jump TPROXY \ + --on-port=9443 \ + --on-ip=127.0.0.3 + +$ sudo iptables --insert PREROUTING \ + --table mangle \ + --protocol tcp \ + --dport 18000 \ + --source 127.0.0.2 \ + --jump TPROXY \ + --on-port=8000 \ + --on-ip=127.0.0.3 + +$ sudo iptables --insert PREROUTING \ + --table mangle \ + --protocol tcp \ + --dport 18443 \ + --source 127.0.0.2 \ + --jump TPROXY \ + --on-port=8443 \ + --on-ip=127.0.0.3 +``` + +And then configure more rules for intercepting traffic destined for **Service B**, and send +it to **Kong B** instead: + +``` +$ sudo iptables --append PREROUTING \ + --table mangle \ + --protocol tcp \ + "!" --source 127.0.0.4 \ + --dport 19000 \ + --destination 127.0.0.5 \ + --jump TPROXY \ + --on-port=9000 \ + --on-ip=127.0.0.4 + +$ sudo iptables --append PREROUTING \ + --table mangle \ + --protocol tcp \ + "!" --source 127.0.0.4 \ + --dport 19443 \ + --destination 127.0.0.5 \ + --jump TPROXY \ + --on-port=9443 \ + --on-ip=127.0.0.4 + +$ sudo iptables --append PREROUTING \ + --table mangle \ + --protocol tcp \ + "!" --source 127.0.0.4 \ + --dport 18000 \ + --destination 127.0.0.5 \ + --jump TPROXY \ + --on-port=8000 \ + --on-ip=127.0.0.4 + +$ sudo iptables --append PREROUTING \ + --table mangle \ + --protocol tcp \ + "!" --source 127.0.0.4 \ + --dport 18443 \ + --destination 127.0.0.5 \ + --jump TPROXY \ + --on-port=8443 \ + --on-ip=127.0.0.4 +``` + + +The equivalent `TPROXY` rules with `macOS` or `BSDs` is a bit tricky, so we leave that +to the reader. If we find a simple way to define them, we'll update this article. + + +## Step 8: Start tailing Kong Logs + +We do this so that you can view that the requests on next step do pass both **Kong A** +and **Kong B**. Run this command for **Kong A**: + +``` +$ tail -F kong-a/logs/error.log +``` + +Leave it running, and in another console, run this command for **Kong B**: + +``` +$ tail -F kong-b/logs/error.log +``` + + +## Step 9: Connect Service A to Service B using Two Sidecars + +Connect from **Service A** to **Service B** using TCP: + +``` +ncat --source 127.0.0.2 127.0.0.5 19000 +``` + +**Note:** at the moment you need to write around twenty bytes to +the stream with the client to actually receive the response from +the server (we are working on it). + +You should see output similar to one below: + +``` +Hello from Service B (TCP) +``` + +Connect using TLS: + +``` +ncat --source 127.0.0.2 --recv-only --ssl 127.0.0.5 19443 +``` + +You should see output similar to one below: + +``` +Hello from Service B (TLS) +``` + +Connect using HTTP: + +``` +curl --interface 127.0.0.2 http://127.0.0.5:18000 +``` + +You should see output similar to one below: + +``` +Hello from Service B (HTTP) +``` + +Connect using HTTPS: + +``` +curl --interface 127.0.0.2 --insecure https://127.0.0.5:18443 +``` + +You should see output similar to one below: + +``` +Hello from Service B (HTTPS) +``` + +As you can see, step 9 looks exactly the same as step 2. We did not need to +make any changes to **Service A** or **Service B**, but we introduced a sidecar proxy +to each of them while successfully demonstrating that Kong is capable to proxy +both raw `tcp` and `tls` streams and `http` and `https` traffic. + + +### About Service Mesh + +In Kong we call it Service Mesh only when the connection between the two sidecars, +**Kong A** and **Kong B**, is mutually TLS authenticated. That is not obviously the +case in this document with the `tcp` and `http` demos. But what makes things interesting +is that Kong can automatically update unprotected `tcp` and `http` connections to `tls` +protected connections so that **Kong A** will always talk to **Kong B** using either `tls` +or `https`. And on the other side, **Kong B**, Kong can also downgrade the `tls` and `https` +connections to unprotected `tcp` or `http` before making that final proxy connection +to the local **Service B**. You can adjust these settings by modifying the Service +entities (or adjusting the `KONG_ORIGINS` setting on **Kong B** which we didn't cover +on this tutorial). + +## Step 10: Stop Kong Nodes and Cleanup + +Cleanup the `iptables` rules: + +``` +sudo iptables --table mangle --flush PREROUTING +``` + +Stop **Kong B**: + +``` +KONG_PREFIX=kong-b kong stop +``` + +Stop **Kong A**: + +``` +KONG_PREFIX=kong-a kong stop +``` + +Stop Kong Control Plane: + +``` +KONG_PREFIX=kong-c kong stop +``` + +Stop Tailing Kong Logs: + +``` +pkill tail +``` + +Stop Ncat Servers: + +``` +pkill ncat +``` diff --git a/app/1.2.x/1.1.x/upgrading.md b/app/1.2.x/1.1.x/upgrading.md new file mode 100644 index 000000000000..a019d846f832 --- /dev/null +++ b/app/1.2.x/1.1.x/upgrading.md @@ -0,0 +1,307 @@ +--- +title: Upgrade guide +--- + +
+ Note: What follows is the upgrade guide for 1.0.x. + If you are trying to upgrade to an earlier version of Kong, please read + UPGRADE.md file in the Kong repo +
+ +This guide will inform you about breaking changes you should be aware of +when upgrading, as well as take you through the correct sequence of steps +in order to obtain a **no-downtime** migration in different upgrade +scenarios. + +## Upgrade to `1.0.0` + +This is a major release of Kong, and includes a number of new features +as well as breaking changes. + +This version introduces **a new schema format for plugins**, **changes in +Admin API endpoints**, **database migrations**, **Nginx configuration +changes**, and **removed configuration properties**. + +In this release, the **API entity is removed**, along with its related +Admin API endpoints. + +This section will highlight breaking changes that you need to be aware of +before upgrading and will describe the recommended upgrade path. We recommend +that you consult the full [1.0.0 +Changelog](https://github.com/Kong/kong/blob/master/CHANGELOG.md) for a +complete list of changes and new features. + +## 1. Breaking Changes + +### Dependencies + +- The required OpenResty version is 1.13.6.2, but for a full feature set, + including stream routing and service mesh abilities with mutual TLS, you need + Kong's [openresty-patches](https://github.com/kong/openresty-patches). +- The minimum required OpenSSL version is 1.1.1. If you are building by hand, + make sure all dependencies, including LuaRocks modules, are compiled using + the same OpenSSL version. If you are installing Kong from one of our + distribution packages, you are not affected by this change. + +### Configuration + +- The `custom_plugins` directive is removed (deprecated since 0.14.0). + Use `plugins` instead, which you can use not only to enable + custom plugins, but also to disable bundled plugins. +- The default value for `cassandra_lb_policy` changed from `RoundRobin` + to `RequestRoundRobin`. +- Kong generates a new template file for stream routing, + `nginx-kong-stream.conf`, included in the `stream` block + of its top-level Nginx configuration file. If you use + a custom Nginx configuration and wish to use stream + routing, you can generate this file using `kong prepare`. +- The Nginx configuration file has changed, which means that you need to update + it if you are using a custom template. The changes are detailed in the following diff: + +``` diff +diff --git a/kong/templates/nginx_kong.lua b/kong/templates/nginx_kong.lua +index d4e416bc..8f268ffd 100644 +--- a/kong/templates/nginx_kong.lua ++++ b/kong/templates/nginx_kong.lua +@@ -66,7 +66,9 @@ upstream kong_upstream { + balancer_by_lua_block { + Kong.balancer() + } ++> if upstream_keepalive > 0 then + keepalive ${{UPSTREAM_KEEPALIVE}}; ++> end + } + + server { +@@ -85,7 +87,7 @@ server { + > if proxy_ssl_enabled then + ssl_certificate ${{SSL_CERT}}; + ssl_certificate_key ${{SSL_CERT_KEY}}; +- ssl_protocols TLSv1.1 TLSv1.2; ++ ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; + ssl_certificate_by_lua_block { + Kong.ssl_certificate() + } +@@ -200,7 +202,7 @@ server { + > if admin_ssl_enabled then + ssl_certificate ${{ADMIN_SSL_CERT}}; + ssl_certificate_key ${{ADMIN_SSL_CERT_KEY}}; +- ssl_protocols TLSv1.1 TLSv1.2; ++ ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; + + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; +``` + +### Core + +- The **API** entity and related concepts such as the + `/apis` endpoint, are removed. These were deprecated since + 0.13.0. Instead, use **Routes** to configure your + endpoints and **Services** to configure your upstream + services. +- The old DAO implementation (`kong.dao`) is removed, + which includes the old schema validation library. This + has implications to plugin developers, listed below. + - The last remaining entities that were converted to + the new DAO implementation were Plugins, Upstreams + and Targets. This has implications to the Admin API, + listed below. + +### Plugins + +Kong 1.0.0 marks the introduction of version 1.0.0 of +the Plugin Development Kit (PDK). No major changes are +made to the PDK compared to release 0.14, but some older +non-PDK functionality which was possibly used by custom +plugins is now removed. + +- Plugins now use the new schema format introduced by the + new DAO implementation, for both plugin schemas + (in `schema.lua`) and custom DAO entities (`daos.lua`). + To ease the transition of plugins, the plugin loader + in 1.0 includes a *best-effort* schema auto-translator + for `schema.lua`, which should be sufficient for many + plugins (in 1.0.0rc1, our bundled plugins used the + auto-translator; they now use the new format). + - If your plugin using the old format in `schema.lua` + fails to load, check the error logs for messages + produced by the auto-translator. If a field cannot + be auto-translated, you can make a gradual conversion + of the schema file by adding a `new_type` entry to + the field table translation of the format. See, + for example, the [key-auth schema in 1.0.0rc1](https://github.com/Kong/kong/blob/1.0.0rc1/kong/plugins/key-auth/schema.lua#L39-L54). + The `new_type` annotation is ignored by Kong 0.x. + - If your custom plugin uses custom DAO objects (i.e. + if it includes a `daos.lua` file), it needs to be + converted to the new format. Their code also needs + to be adjusted accordingly, replacing uses of + `singletons.dao` or `kong.dao` by `kong.db` (note + that this module exposes a different API from the + old DAO implementation). +- Some Kong modules that had their functionality replaced + by the PDK in 0.14.0 are now removed: + - `kong.tools.ip`: use `kong.ip` from the PDK instead. + - `kong.tools.public`: replaced by various functionalities + of the PDK. + - `kong.tools.responses`: use `kong.response.exit` from the PDK instead. You + might want to use `kong.log.err` to log internal server errors as well. +- The `kong.api.crud_helpers` module was removed. + Use `kong.api.endpoints` instead if you need to customize + the auto-generated endpoints. + +### Admin API + +- With the removal of the API entity, the `/apis` endpoint + is removed; accordingly, other endpoints that accepted + `api_id` no longer do so. Use Routes and Services instead. +- All entity endpoints now use the new Admin API implementaion. + This means their requests and responses now use the same + syntax, which was already in use in endpoints such as + `/routes` and `/services`. + - All endpoints now use the same syntax for + referencing other entities as `/routes` + (for example, `"service":{"id":"..."}` instead of + `"service_id":"..."`), both in requests and responses. + - This change affects `/plugins` as well as + plugin-specific endpoints. + - Array-typed values are not specified as a + comma-separated list anymore. It must be specified as a + JSON array or using the various formats supported by + the url-formencoded array notation of the new Admin API + implementation (`a[1]=x&a[2]=y`, `a[]=x&a[]=y`, + `a=x&a=y`). + - This change affects attributes of the `/upstreams` endpoint. + - Error responses for the updated endpoints use + the new standardized format. + - As a result of being moved to the new Admin API implementation, + all endpoints supporting `PUT` do so with proper semantics. + - See the [Admin API + reference](https://docs.konghq.com/1.0.x/admin-api) + for more details. + +## 2. Deprecation Notices + +There are no deprecation notices in this release. + +## 3. Suggested Upgrade Path + +### Preliminary Checks + +If your cluster is running a version lower than 0.14, you need to +upgrade to 0.14.1 first instead. Upgrading from a pre-0.14 cluster +straight to Kong 1.0 is **not** supported. + +If you still use the deprecated API entity to configure your endpoints and +upstream services (via `/apis`) instead of using Routes for endpoints (via +`/routes`) and Services for upstream services (via `/services`), now is the +time to do so. Kong 1.0 will refuse to run migrations if you have any entity +configured using `/apis` in your datastore. Create equivalent Routes and +Services and delete your APIs. (Note that Kong does not do this automatically +because the naive option of creating a Route and Service pair for each API +would miss the point of the improvements brought by Routes and Services; +the ideal mapping of Routes and Services depends on your microservice +architecture.) + +If you use additional plugins other than the ones bundled with Kong, +make sure they are compatible with Kong 1.0 prior to upgrading. +See the section above on Plugins for information on plugin compatibility. + +### Migration Steps from 0.14 + +Kong 1.0 introduces a new, improved migrations framework. +It supports a no-downtime, Blue/Green migration model for upgrading +from 0.14.x. The full migration is now split into two steps, +which are performed via commands `kong migrations up` and +`kong migrations finish`. + +For a no-downtime migration from a 0.14 cluster to a 1.0 cluster, +we recommend the following sequence of steps: + +1. Download 1.0, and configure it to point to the same datastore + as your 0.14 cluster. Run `kong migrations up`. +2. Both 0.14 and 1.0 nodes can now run simultaneously on the same + datastore. Start provisioning 1.0 nodes, but do not use their + Admin API yet. Prefer making Admin API requests to your 0.14 nodes + instead. +3. Gradually divert traffic away from your 0.14 nodes, and into + your 1.0 cluster. Monitor your traffic to make sure everything + is going smoothly. +4. When your traffic is fully migrated to the 1.0 cluster, + decommission your 0.14 nodes. +5. From your 1.0 cluster, run: `kong migrations finish`. + From this point on, it will not be possible to start 0.14 + 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.0 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 + decomissioned 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 1.0 Release Candidates + +The process is the same as for upgrading for 0.14 listed above, but on step 1 +you should run `kong migrations up --force` instead. + +## Upgrade Path for Patch Releases + +There are no migrations in upgrades between current or +future patch releases of the same minor release of Kong +(e.g. 1.0.0 to 1.0.1, 1.0.1 to 1.0.4, etc.). Therefore, the +upgrade process is simpler. + +Assuming that Kong is already running on your system, acquire the latest +version from any of the available [installation +methods](https://getkong.org/install/) and proceed to install it, overriding +your previous installation. + +If you are planning to make modifications to your configuration, this is a +good time to do so. + +Then, run migration to upgrade your database schema: + +```shell +$ kong migrations up [-c configuration_file] +``` + +If the command is successful, and no migration ran +(no output), then you only have to +[reload](https://getkong.org/docs/latest/cli/#reload) Kong: + +```shell +$ kong reload [-c configuration_file] +``` + +**Reminder**: `kong reload` leverages the Nginx `reload` signal that seamlessly +starts new workers, which take over from old workers before those old workers +are terminated. In this way, Kong will serve new requests via the new +configuration, without dropping existing in-flight connections. + +## Installing 1.0 on a Fresh Datastore + +For installing on a fresh datastore, Kong 1.0 introduces the `kong migrations +bootstrap` command. The following commands can be run to prepare a new 1.0 +cluster from a fresh datastore: + +``` +$ kong migrations bootstrap [-c config] +$ kong start [-c config] +``` + +